Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client certificate authentication #130

Open
Massimo-B opened this issue Jun 4, 2018 · 10 comments
Open

Client certificate authentication #130

Massimo-B opened this issue Jun 4, 2018 · 10 comments

Comments

@Massimo-B
Copy link

Hello,

we like to connect to a HTTP server using certificate based authentication instead of Basic Authentication.
We are using
KDSoapClientInterface::setSslConfiguration

https://docs.kdab.com/kdsoap/latest/class_k_d_soap_client_interface.html#ab8af33800dfd4124948fbff84ea2586a

This should be similar to QNetworkRequest

Then I have set the private key and the local certificate:
QSslConfiguration::setPrivateKey()
and
QSslConfiguration::setLocalCertificate()

Is this the right way to setup a client certificate authentication?

However I always got the error from KDSoapMessage::faultAsString():
"Fault code 5: Operation canceled"
Not sure if this is an SSL error or already within the SOAP layer after a successful authentication.

I double-checked the connection using curl like this:

curl -v --cert cert.crt --key key.key --pass foobar https://testserver... which fails at the authentication as well.

Then I double-checked with a Firefox. However I needed to merge both files to a PKCS#12 format first and importing this one, then I got a soap:Fault as expected.

So how doing this in Qt and KDSoap?
``

@dfaure-kdab
Copy link
Member

This seems to be more of a Qt support request than a KDSoap request.
However here's a known working example, which you can use as a comparison point:
The unittest test_wsdl_document.cpp, method testMyWsdlSSL(), sets up a SSL server using KDSoapUnitTestHelpers::setSslConfiguration(), implemented in testtools/httpserver_p.cpp. It uses a self-signed certificate, and indeed calls setPrivateKey and setLocalCertificate.

@Massimo-B
Copy link
Author

Thanks for the hint. It's not done in https://github.com/KDAB/KDSoap/blob/master/testtools/httpserver_p.cpp#L164 but in setupSslServer() https://github.com/KDAB/KDSoap/blob/master/testtools/httpserver_p.cpp#L150

Difference to my KDSoap code is, here a QSslSocket is used and this one is setting up a server and not a client request. Does this mean it sets the server certificate and private key? Then probably I can't do the same for a client authentication in my code like this:

// Certificate
QByteArray cert;
QFile      certFile(certPath);
if(certFile.open(QIODevice::ReadOnly)) {
    cert = certFile.readAll();
    certFile.close();
    mydebug(9, QString("Successfully loaded client certificate \"%1\"").arg(certPath));
} else {
    myerror(QString("No certificate found at %1, %2").arg(certPath).arg(certFile.errorString()));
}

// Key
QByteArray key;
QFile      keyFile(keyPath);
if(keyFile.open(QIODevice::ReadOnly)) {
    key = keyFile.readAll();
    keyFile.close();
    mydebug(9, QString("Successfully loaded client key \"%1\"").arg(keyPath));
} else {
    myerror(QString("No key found at %1, %2").arg(keyPath).arg(keyFile.errorString()));
}

QSslKey         sslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, m_pass.toUtf8());
QSslCertificate sslCert(cert);
QSslConfiguration sslConfiguration;
sslConfiguration.setLocalCertificate(sslCert);
sslConfiguration.setPrivateKey(sslKey);
m_service.clientInterface()->setSslConfiguration(sslConfiguration);

@phbaer
Copy link
Contributor

phbaer commented Jun 13, 2018

We're authenticating via a client certficate as well and yes, using

sslConfig.setLocalCertificate(clientCert); // QSslCertificate
sslConfig.setPrivateKey(clientKey); // QSslKey

and then setting the sslConfig using soapService->clientInterface()->setSslConfiguration(sslConfig) is sufficient and works.

@Massimo-B
Copy link
Author

Hi, thanks for your comment.
We learned that the server requires an intermediate CA certificate additionally added to the TLS handshake. Old Qt4 is not able to do that, Qt5 added setLocalCertificateChain() for that. But on Qt4 branches this is really a blocker for us.
Why the server requires that is not clear as those CA certs are public available. And providing the whole trust chain isn't the idea of trust as the other peer should decide itself which CA certs are trusted and not relying on CA certs provided by the client.

@phbaer
Copy link
Contributor

phbaer commented Jun 13, 2018

Right, if the client cert is signed by an intermediate authority their certificate must be passed alongside the client cert. Or trusted on the server but that's not the idea behind the whole setup. It's the same for intermediate TLS certs for servers where the server typically provides the chain as well. Especially in companies with inspection proxies (where encryption is broken by design anyway) the intermediates are typically installed directly on the client.

Quite unfortunate that Qt4 doesn't support providing a chain. Just checked, maybe client certificate auth is just not that famous. It's also quite unfortunate that extending that Qt class is quite hard or impossible due to the pimpl pattern.

Thanks for the links, especially the curl behaviour!

@Massimo-B
Copy link
Author

Massimo-B commented Jun 13, 2018

You mean non-public intermediates, but this one is an intermediate from the CA that is public. For instance Firefox already has this one installed. Curiously Firefox does add it to the client cert automatically and I don't have any idea how Firefox knows that it is required. The server sends the accepted CAs first, but only on CA level without any signatures.

@dfaure-kdab
Copy link
Member

Hello - can we close this issue now, given that it's not a KDSoap issue?

@dfaure-kdab
Copy link
Member

@Massimo-B for information we are going to drop Qt4 support from the master branch, given that Qt6 is under development already. Is this OK with you? Do you need help porting your project to Qt5, if you haven't done so already?

@Massimo-B
Copy link
Author

Thanks for asking... I won't stop you dropping Qt4 support :)
We have dropped KDSoap for now due to the mentioned issues with Qt4 and missing WS-Security. The simple Soap client now just sends a static XML string, replacing parameter values, sent by system call using curl...
Qt4 also had missing latest TLS support. And we are going to migrate to Qt5 as well, maybe evaluating KDSoap again for next projects.
So just keep the project up to date.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants