Skip to content

Commit

Permalink
[auth] PKI support to postgres provider
Browse files Browse the repository at this point in the history
  • Loading branch information
luipir committed Jan 13, 2016
1 parent ef91882 commit 68478a7
Show file tree
Hide file tree
Showing 15 changed files with 426 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/auth/basic/qgsauthbasicmethod.cpp
Expand Up @@ -36,7 +36,7 @@ QgsAuthBasicMethod::QgsAuthBasicMethod()
<< "ows" << "ows"
<< "wfs" // convert to lowercase << "wfs" // convert to lowercase
<< "wcs" << "wcs"
<< "wms" ); << "wms");
} }


QgsAuthBasicMethod::~QgsAuthBasicMethod() QgsAuthBasicMethod::~QgsAuthBasicMethod()
Expand Down
131 changes: 128 additions & 3 deletions src/auth/identcert/qgsauthidentcertmethod.cpp
Expand Up @@ -17,6 +17,9 @@
#include "qgsauthidentcertmethod.h" #include "qgsauthidentcertmethod.h"
#include "qgsauthidentcertedit.h" #include "qgsauthidentcertedit.h"


#include <QDir>
#include <QFile>
#include <QUuid>
#ifndef QT_NO_OPENSSL #ifndef QT_NO_OPENSSL
#include <QtCrypto> #include <QtCrypto>
#include <QSslConfiguration> #include <QSslConfiguration>
Expand All @@ -27,7 +30,6 @@
#include "qgsauthmanager.h" #include "qgsauthmanager.h"
#include "qgslogger.h" #include "qgslogger.h"



static const QString AUTH_METHOD_KEY = "Identity-Cert"; static const QString AUTH_METHOD_KEY = "Identity-Cert";
static const QString AUTH_METHOD_DESCRIPTION = "Identity certificate authentication"; static const QString AUTH_METHOD_DESCRIPTION = "Identity certificate authentication";


Expand All @@ -38,12 +40,13 @@ QgsAuthIdentCertMethod::QgsAuthIdentCertMethod()
: QgsAuthMethod() : QgsAuthMethod()
{ {
setVersion( 2 ); setVersion( 2 );
setExpansions( QgsAuthMethod::NetworkRequest ); setExpansions( QgsAuthMethod::NetworkRequest | QgsAuthMethod::DataSourceURI );
setDataProviders( QStringList() setDataProviders( QStringList()
<< "ows" << "ows"
<< "wfs" // convert to lowercase << "wfs" // convert to lowercase
<< "wcs" << "wcs"
<< "wms" ); << "wms"
<< "postgres" );
} }


QgsAuthIdentCertMethod::~QgsAuthIdentCertMethod() QgsAuthIdentCertMethod::~QgsAuthIdentCertMethod()
Expand Down Expand Up @@ -101,6 +104,128 @@ bool QgsAuthIdentCertMethod::updateNetworkRequest( QNetworkRequest &request, con
return true; return true;
} }


bool QgsAuthIdentCertMethod::updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
const QString &dataprovider )
{
Q_UNUSED( dataprovider )

QgsDebugMsg( QString( "Update URI items for authcfg: %1" ).arg( authcfg ) );

QString pkiTempFilePrefix = "tmppki_";

QgsAuthMethodConfig amConfig;
if ( !QgsAuthManager::instance()->loadAuthenticationConfig( authcfg, amConfig, true ) )
{
QgsDebugMsg( QString( "Update URI items: FAILED to retrieve config for authcfg: %1" ).arg( authcfg ) );
return false;
}

if ( !amConfig.isValid() )
{
QgsDebugMsg( QString( "Update URI items: FAILED retrieved invalid Auth method for authcfg: %1" ).arg( authcfg ) );
return false;
}

// get client cent and key
QSslCertificate clientCert = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).first;
QSslKey clientKey = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).second;

// get common name of the client certificate
QString commonName = QgsAuthCertUtils::resolvedCertName( clientCert, false);

// get CA
QByteArray caCert = QgsAuthManager::instance()->getTrustedCaCertsPemText();

// save client cert to temp file
QFile certFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
if( certFile.open( QIODevice::WriteOnly ) )
{
certFile.write( clientCert.toPem() );
}
else
{
QgsDebugMsg( QString( "Update URI items: FAILED to save client cert temporary file" ) );
return false;
}

certFile.setPermissions( QFile::ReadUser | QFile::WriteUser );

// save key cert to temp file setting it's permission only read to the current user
QFile keyFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
if( keyFile.open( QIODevice::WriteOnly ) )
{
keyFile.write( clientKey.toPem() );
}
else
{
QgsDebugMsg( QString( "Update URI items: FAILED to save client key temporary file" ) );
return false;
}

keyFile.setPermissions( QFile::ReadUser );

// save CA to tempo file
QFile caFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
if( caFile.open( QIODevice::WriteOnly ) )
{
caFile.write( caCert );
}
else
{
QgsDebugMsg( QString( "Update URI items: FAILED to save CAs to temporary file" ) );
return false;
}

caFile.setPermissions( QFile::ReadUser | QFile::WriteUser );

// add uri parameters
QString userparam = "user='" + commonName + "'";
int userindx = connectionItems.indexOf( QRegExp( "^user='.*" ) );
if ( userindx != -1 )
{
connectionItems.replace( userindx, userparam );
}
else
{
connectionItems.append( userparam );
}

QString certparam = "sslcert='" + certFile.fileName() + "'";
int sslcertindx = connectionItems.indexOf( QRegExp( "^sslcert='.*" ) );
if ( sslcertindx != -1 )
{
connectionItems.replace( sslcertindx, certparam );
}
else
{
connectionItems.append( certparam );
}

QString keyparam = "sslkey='" + keyFile.fileName() + "'";
int sslkeyindx = connectionItems.indexOf( QRegExp( "^sslkey='.*" ) );
if ( sslkeyindx != -1 )
{
connectionItems.replace( sslkeyindx, keyparam );
}
else
{
connectionItems.append( keyparam );
}

QString caparam = "sslrootcert='" + caFile.fileName() + "'";
int sslcaindx = connectionItems.indexOf( QRegExp( "^sslrootcert='.*" ) );
if ( sslcaindx != -1 )
{
connectionItems.replace( sslcaindx, caparam );
}
else
{
connectionItems.append( caparam );
}

return true;
}

void QgsAuthIdentCertMethod::clearCachedConfig( const QString &authcfg ) void QgsAuthIdentCertMethod::clearCachedConfig( const QString &authcfg )
{ {
removePkiConfigBundle( authcfg ); removePkiConfigBundle( authcfg );
Expand Down
3 changes: 3 additions & 0 deletions src/auth/identcert/qgsauthidentcertmethod.h
Expand Up @@ -41,6 +41,9 @@ class QgsAuthIdentCertMethod : public QgsAuthMethod
bool updateNetworkRequest( QNetworkRequest &request, const QString &authcfg, bool updateNetworkRequest( QNetworkRequest &request, const QString &authcfg,
const QString &dataprovider = QString() ) override; const QString &dataprovider = QString() ) override;


bool updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
const QString &dataprovider = QString() ) override;

void clearCachedConfig( const QString &authcfg ) override; void clearCachedConfig( const QString &authcfg ) override;


void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override; void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override;
Expand Down
119 changes: 117 additions & 2 deletions src/auth/pkipaths/qgsauthpkipathsmethod.cpp
Expand Up @@ -17,6 +17,9 @@
#include "qgsauthpkipathsmethod.h" #include "qgsauthpkipathsmethod.h"
#include "qgsauthpkipathsedit.h" #include "qgsauthpkipathsedit.h"


#include <QDir>
#include <QFile>
#include <QUuid>
#ifndef QT_NO_OPENSSL #ifndef QT_NO_OPENSSL
#include <QtCrypto> #include <QtCrypto>
#include <QSslConfiguration> #include <QSslConfiguration>
Expand All @@ -38,12 +41,13 @@ QgsAuthPkiPathsMethod::QgsAuthPkiPathsMethod()
: QgsAuthMethod() : QgsAuthMethod()
{ {
setVersion( 2 ); setVersion( 2 );
setExpansions( QgsAuthMethod::NetworkRequest ); setExpansions( QgsAuthMethod::NetworkRequest | QgsAuthMethod::DataSourceURI );
setDataProviders( QStringList() setDataProviders( QStringList()
<< "ows" << "ows"
<< "wfs" // convert to lowercase << "wfs" // convert to lowercase
<< "wcs" << "wcs"
<< "wms" ); << "wms"
<< "postgres" );
} }


QgsAuthPkiPathsMethod::~QgsAuthPkiPathsMethod() QgsAuthPkiPathsMethod::~QgsAuthPkiPathsMethod()
Expand Down Expand Up @@ -101,6 +105,117 @@ bool QgsAuthPkiPathsMethod::updateNetworkRequest( QNetworkRequest &request, cons
return true; return true;
} }


bool QgsAuthPkiPathsMethod::updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
const QString &dataprovider )
{
Q_UNUSED( dataprovider )

QgsDebugMsg( QString( "Update URI items for authcfg: %1" ).arg( authcfg ) );

QString pkiTempFilePrefix = "tmppki_";

QgsAuthMethodConfig amConfig;
if ( !QgsAuthManager::instance()->loadAuthenticationConfig( authcfg, amConfig, true ) )
{
QgsDebugMsg( QString( "Update URI items: FAILED to retrieve config for authcfg: %1" ).arg( authcfg ) );
return false;
}

if ( !amConfig.isValid() )
{
QgsDebugMsg( QString( "Update URI items: FAILED retrieved invalid Auth method for authcfg: %1" ).arg( authcfg ) );
return false;
}

// get client cent and key
QSslCertificate clientCert = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).first;
QSslKey clientKey = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).second;

// get common name of the client certificate
QString commonName = QgsAuthCertUtils::resolvedCertName( clientCert, false);

// get CA
QByteArray caCert = QgsAuthManager::instance()->getTrustedCaCertsPemText();

// save client cert to temp file
QFile certFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
if( certFile.open( QIODevice::WriteOnly ) )
{
certFile.write( clientCert.toPem() );
}
else
{
QgsDebugMsg( QString( "Update URI items: FAILED to save client cert temporary file" ) );
return false;
}

certFile.setPermissions( QFile::ReadUser | QFile::WriteUser );

// save key cert to temp file setting it's permission only read to the current user
QFile keyFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
if( keyFile.open( QIODevice::WriteOnly ) )
{
keyFile.write( clientKey.toPem() );
}
else
{
QgsDebugMsg( QString( "Update URI items: FAILED to save client key temporary file" ) );
return false;
}

keyFile.setPermissions( QFile::ReadUser );

// save CA to tempo file
QFile caFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
if( caFile.open( QIODevice::WriteOnly ) )
{
caFile.write( caCert );
}
else
{
QgsDebugMsg( QString( "Update URI items: FAILED to save CAs to temporary file" ) );
return false;
}

caFile.setPermissions( QFile::ReadUser | QFile::WriteUser );

// add uri parameters
QString certparam = "sslcert='" + certFile.fileName() + "'";
int sslcertindx = connectionItems.indexOf( QRegExp( "^sslcert='.*" ) );
if ( sslcertindx != -1 )
{
connectionItems.replace( sslcertindx, certparam );
}
else
{
connectionItems.append( certparam );
}

QString keyparam = "sslkey='" + keyFile.fileName() + "'";
int sslkeyindx = connectionItems.indexOf( QRegExp( "^sslkey='.*" ) );
if ( sslkeyindx != -1 )
{
connectionItems.replace( sslkeyindx, keyparam );
}
else
{
connectionItems.append( keyparam );
}

QString caparam = "sslrootcert='" + caFile.fileName() + "'";
int sslcaindx = connectionItems.indexOf( QRegExp( "^sslrootcert='.*" ) );
if ( sslcaindx != -1 )
{
connectionItems.replace( sslcaindx, caparam );
}
else
{
connectionItems.append( caparam );
}

return true;
}

void QgsAuthPkiPathsMethod::clearCachedConfig( const QString &authcfg ) void QgsAuthPkiPathsMethod::clearCachedConfig( const QString &authcfg )
{ {
removePkiConfigBundle( authcfg ); removePkiConfigBundle( authcfg );
Expand Down
3 changes: 3 additions & 0 deletions src/auth/pkipaths/qgsauthpkipathsmethod.h
Expand Up @@ -41,6 +41,9 @@ class QgsAuthPkiPathsMethod : public QgsAuthMethod
bool updateNetworkRequest( QNetworkRequest &request, const QString &authcfg, bool updateNetworkRequest( QNetworkRequest &request, const QString &authcfg,
const QString &dataprovider = QString() ) override; const QString &dataprovider = QString() ) override;


bool updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
const QString &dataprovider = QString() ) override;

void clearCachedConfig( const QString &authcfg ) override; void clearCachedConfig( const QString &authcfg ) override;


void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override; void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override;
Expand Down

0 comments on commit 68478a7

Please sign in to comment.