Skip to content

Commit 68478a7

Browse files
committed
[auth] PKI support to postgres provider
1 parent ef91882 commit 68478a7

15 files changed

+426
-46
lines changed

src/auth/basic/qgsauthbasicmethod.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ QgsAuthBasicMethod::QgsAuthBasicMethod()
3636
<< "ows"
3737
<< "wfs" // convert to lowercase
3838
<< "wcs"
39-
<< "wms" );
39+
<< "wms");
4040
}
4141

4242
QgsAuthBasicMethod::~QgsAuthBasicMethod()

src/auth/identcert/qgsauthidentcertmethod.cpp

+128-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "qgsauthidentcertmethod.h"
1818
#include "qgsauthidentcertedit.h"
1919

20+
#include <QDir>
21+
#include <QFile>
22+
#include <QUuid>
2023
#ifndef QT_NO_OPENSSL
2124
#include <QtCrypto>
2225
#include <QSslConfiguration>
@@ -27,7 +30,6 @@
2730
#include "qgsauthmanager.h"
2831
#include "qgslogger.h"
2932

30-
3133
static const QString AUTH_METHOD_KEY = "Identity-Cert";
3234
static const QString AUTH_METHOD_DESCRIPTION = "Identity certificate authentication";
3335

@@ -38,12 +40,13 @@ QgsAuthIdentCertMethod::QgsAuthIdentCertMethod()
3840
: QgsAuthMethod()
3941
{
4042
setVersion( 2 );
41-
setExpansions( QgsAuthMethod::NetworkRequest );
43+
setExpansions( QgsAuthMethod::NetworkRequest | QgsAuthMethod::DataSourceURI );
4244
setDataProviders( QStringList()
4345
<< "ows"
4446
<< "wfs" // convert to lowercase
4547
<< "wcs"
46-
<< "wms" );
48+
<< "wms"
49+
<< "postgres" );
4750
}
4851

4952
QgsAuthIdentCertMethod::~QgsAuthIdentCertMethod()
@@ -101,6 +104,128 @@ bool QgsAuthIdentCertMethod::updateNetworkRequest( QNetworkRequest &request, con
101104
return true;
102105
}
103106

107+
bool QgsAuthIdentCertMethod::updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
108+
const QString &dataprovider )
109+
{
110+
Q_UNUSED( dataprovider )
111+
112+
QgsDebugMsg( QString( "Update URI items for authcfg: %1" ).arg( authcfg ) );
113+
114+
QString pkiTempFilePrefix = "tmppki_";
115+
116+
QgsAuthMethodConfig amConfig;
117+
if ( !QgsAuthManager::instance()->loadAuthenticationConfig( authcfg, amConfig, true ) )
118+
{
119+
QgsDebugMsg( QString( "Update URI items: FAILED to retrieve config for authcfg: %1" ).arg( authcfg ) );
120+
return false;
121+
}
122+
123+
if ( !amConfig.isValid() )
124+
{
125+
QgsDebugMsg( QString( "Update URI items: FAILED retrieved invalid Auth method for authcfg: %1" ).arg( authcfg ) );
126+
return false;
127+
}
128+
129+
// get client cent and key
130+
QSslCertificate clientCert = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).first;
131+
QSslKey clientKey = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).second;
132+
133+
// get common name of the client certificate
134+
QString commonName = QgsAuthCertUtils::resolvedCertName( clientCert, false);
135+
136+
// get CA
137+
QByteArray caCert = QgsAuthManager::instance()->getTrustedCaCertsPemText();
138+
139+
// save client cert to temp file
140+
QFile certFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
141+
if( certFile.open( QIODevice::WriteOnly ) )
142+
{
143+
certFile.write( clientCert.toPem() );
144+
}
145+
else
146+
{
147+
QgsDebugMsg( QString( "Update URI items: FAILED to save client cert temporary file" ) );
148+
return false;
149+
}
150+
151+
certFile.setPermissions( QFile::ReadUser | QFile::WriteUser );
152+
153+
// save key cert to temp file setting it's permission only read to the current user
154+
QFile keyFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
155+
if( keyFile.open( QIODevice::WriteOnly ) )
156+
{
157+
keyFile.write( clientKey.toPem() );
158+
}
159+
else
160+
{
161+
QgsDebugMsg( QString( "Update URI items: FAILED to save client key temporary file" ) );
162+
return false;
163+
}
164+
165+
keyFile.setPermissions( QFile::ReadUser );
166+
167+
// save CA to tempo file
168+
QFile caFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
169+
if( caFile.open( QIODevice::WriteOnly ) )
170+
{
171+
caFile.write( caCert );
172+
}
173+
else
174+
{
175+
QgsDebugMsg( QString( "Update URI items: FAILED to save CAs to temporary file" ) );
176+
return false;
177+
}
178+
179+
caFile.setPermissions( QFile::ReadUser | QFile::WriteUser );
180+
181+
// add uri parameters
182+
QString userparam = "user='" + commonName + "'";
183+
int userindx = connectionItems.indexOf( QRegExp( "^user='.*" ) );
184+
if ( userindx != -1 )
185+
{
186+
connectionItems.replace( userindx, userparam );
187+
}
188+
else
189+
{
190+
connectionItems.append( userparam );
191+
}
192+
193+
QString certparam = "sslcert='" + certFile.fileName() + "'";
194+
int sslcertindx = connectionItems.indexOf( QRegExp( "^sslcert='.*" ) );
195+
if ( sslcertindx != -1 )
196+
{
197+
connectionItems.replace( sslcertindx, certparam );
198+
}
199+
else
200+
{
201+
connectionItems.append( certparam );
202+
}
203+
204+
QString keyparam = "sslkey='" + keyFile.fileName() + "'";
205+
int sslkeyindx = connectionItems.indexOf( QRegExp( "^sslkey='.*" ) );
206+
if ( sslkeyindx != -1 )
207+
{
208+
connectionItems.replace( sslkeyindx, keyparam );
209+
}
210+
else
211+
{
212+
connectionItems.append( keyparam );
213+
}
214+
215+
QString caparam = "sslrootcert='" + caFile.fileName() + "'";
216+
int sslcaindx = connectionItems.indexOf( QRegExp( "^sslrootcert='.*" ) );
217+
if ( sslcaindx != -1 )
218+
{
219+
connectionItems.replace( sslcaindx, caparam );
220+
}
221+
else
222+
{
223+
connectionItems.append( caparam );
224+
}
225+
226+
return true;
227+
}
228+
104229
void QgsAuthIdentCertMethod::clearCachedConfig( const QString &authcfg )
105230
{
106231
removePkiConfigBundle( authcfg );

src/auth/identcert/qgsauthidentcertmethod.h

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class QgsAuthIdentCertMethod : public QgsAuthMethod
4141
bool updateNetworkRequest( QNetworkRequest &request, const QString &authcfg,
4242
const QString &dataprovider = QString() ) override;
4343

44+
bool updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
45+
const QString &dataprovider = QString() ) override;
46+
4447
void clearCachedConfig( const QString &authcfg ) override;
4548

4649
void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override;

src/auth/pkipaths/qgsauthpkipathsmethod.cpp

+117-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "qgsauthpkipathsmethod.h"
1818
#include "qgsauthpkipathsedit.h"
1919

20+
#include <QDir>
21+
#include <QFile>
22+
#include <QUuid>
2023
#ifndef QT_NO_OPENSSL
2124
#include <QtCrypto>
2225
#include <QSslConfiguration>
@@ -38,12 +41,13 @@ QgsAuthPkiPathsMethod::QgsAuthPkiPathsMethod()
3841
: QgsAuthMethod()
3942
{
4043
setVersion( 2 );
41-
setExpansions( QgsAuthMethod::NetworkRequest );
44+
setExpansions( QgsAuthMethod::NetworkRequest | QgsAuthMethod::DataSourceURI );
4245
setDataProviders( QStringList()
4346
<< "ows"
4447
<< "wfs" // convert to lowercase
4548
<< "wcs"
46-
<< "wms" );
49+
<< "wms"
50+
<< "postgres" );
4751
}
4852

4953
QgsAuthPkiPathsMethod::~QgsAuthPkiPathsMethod()
@@ -101,6 +105,117 @@ bool QgsAuthPkiPathsMethod::updateNetworkRequest( QNetworkRequest &request, cons
101105
return true;
102106
}
103107

108+
bool QgsAuthPkiPathsMethod::updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
109+
const QString &dataprovider )
110+
{
111+
Q_UNUSED( dataprovider )
112+
113+
QgsDebugMsg( QString( "Update URI items for authcfg: %1" ).arg( authcfg ) );
114+
115+
QString pkiTempFilePrefix = "tmppki_";
116+
117+
QgsAuthMethodConfig amConfig;
118+
if ( !QgsAuthManager::instance()->loadAuthenticationConfig( authcfg, amConfig, true ) )
119+
{
120+
QgsDebugMsg( QString( "Update URI items: FAILED to retrieve config for authcfg: %1" ).arg( authcfg ) );
121+
return false;
122+
}
123+
124+
if ( !amConfig.isValid() )
125+
{
126+
QgsDebugMsg( QString( "Update URI items: FAILED retrieved invalid Auth method for authcfg: %1" ).arg( authcfg ) );
127+
return false;
128+
}
129+
130+
// get client cent and key
131+
QSslCertificate clientCert = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).first;
132+
QSslKey clientKey = QgsAuthManager::instance()->getCertIdentityBundle( amConfig.config( "certid" ) ).second;
133+
134+
// get common name of the client certificate
135+
QString commonName = QgsAuthCertUtils::resolvedCertName( clientCert, false);
136+
137+
// get CA
138+
QByteArray caCert = QgsAuthManager::instance()->getTrustedCaCertsPemText();
139+
140+
// save client cert to temp file
141+
QFile certFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
142+
if( certFile.open( QIODevice::WriteOnly ) )
143+
{
144+
certFile.write( clientCert.toPem() );
145+
}
146+
else
147+
{
148+
QgsDebugMsg( QString( "Update URI items: FAILED to save client cert temporary file" ) );
149+
return false;
150+
}
151+
152+
certFile.setPermissions( QFile::ReadUser | QFile::WriteUser );
153+
154+
// save key cert to temp file setting it's permission only read to the current user
155+
QFile keyFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
156+
if( keyFile.open( QIODevice::WriteOnly ) )
157+
{
158+
keyFile.write( clientKey.toPem() );
159+
}
160+
else
161+
{
162+
QgsDebugMsg( QString( "Update URI items: FAILED to save client key temporary file" ) );
163+
return false;
164+
}
165+
166+
keyFile.setPermissions( QFile::ReadUser );
167+
168+
// save CA to tempo file
169+
QFile caFile( QDir::tempPath() + QDir::separator() + pkiTempFilePrefix + QUuid::createUuid() + ".pem" );
170+
if( caFile.open( QIODevice::WriteOnly ) )
171+
{
172+
caFile.write( caCert );
173+
}
174+
else
175+
{
176+
QgsDebugMsg( QString( "Update URI items: FAILED to save CAs to temporary file" ) );
177+
return false;
178+
}
179+
180+
caFile.setPermissions( QFile::ReadUser | QFile::WriteUser );
181+
182+
// add uri parameters
183+
QString certparam = "sslcert='" + certFile.fileName() + "'";
184+
int sslcertindx = connectionItems.indexOf( QRegExp( "^sslcert='.*" ) );
185+
if ( sslcertindx != -1 )
186+
{
187+
connectionItems.replace( sslcertindx, certparam );
188+
}
189+
else
190+
{
191+
connectionItems.append( certparam );
192+
}
193+
194+
QString keyparam = "sslkey='" + keyFile.fileName() + "'";
195+
int sslkeyindx = connectionItems.indexOf( QRegExp( "^sslkey='.*" ) );
196+
if ( sslkeyindx != -1 )
197+
{
198+
connectionItems.replace( sslkeyindx, keyparam );
199+
}
200+
else
201+
{
202+
connectionItems.append( keyparam );
203+
}
204+
205+
QString caparam = "sslrootcert='" + caFile.fileName() + "'";
206+
int sslcaindx = connectionItems.indexOf( QRegExp( "^sslrootcert='.*" ) );
207+
if ( sslcaindx != -1 )
208+
{
209+
connectionItems.replace( sslcaindx, caparam );
210+
}
211+
else
212+
{
213+
connectionItems.append( caparam );
214+
}
215+
216+
return true;
217+
}
218+
104219
void QgsAuthPkiPathsMethod::clearCachedConfig( const QString &authcfg )
105220
{
106221
removePkiConfigBundle( authcfg );

src/auth/pkipaths/qgsauthpkipathsmethod.h

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class QgsAuthPkiPathsMethod : public QgsAuthMethod
4141
bool updateNetworkRequest( QNetworkRequest &request, const QString &authcfg,
4242
const QString &dataprovider = QString() ) override;
4343

44+
bool updateDataSourceUriItems( QStringList &connectionItems, const QString &authcfg,
45+
const QString &dataprovider = QString() ) override;
46+
4447
void clearCachedConfig( const QString &authcfg ) override;
4548

4649
void updateMethodConfig( QgsAuthMethodConfig &mconfig ) override;

0 commit comments

Comments
 (0)