PDA

View Full Version : QNetworkAccessManager: "SSL handshake failed"



kleag
13th February 2009, 22:58
Hello,

I'm trying to access to a SOAP web service protected by certificate (the server one is auto-signed, the client one should be presented).
I'm using Qt4.5 from qt-copy (in kde) under GNU/Linux but I had the same problem with Qt4.4.x

I'm using the following code:


qDebug() << "setting up SSL configuration: " << m_sslKeyFile;
QSslConfiguration sslConfiguration = request.sslConfiguration();
QFile sslCertificateFile(m_sslKeyFile);
if (sslCertificateFile.open(QIODevice::ReadOnly))
{
QSslCertificate certif(&sslCertificateFile);
sslCertificateFile.close();
if (certif.isNull())
{
qDebug() << "Failed to load certificate";
}
qDebug() << "certif version=" << certif.version() << ", serial=" << certif.serialNumber()
<< ", issuer=" << certif.issuerInfo(QSslCertificate::Organization)
<< " and subject=" << certif.subjectInfo(QSslCertificate::CommonName);
sslConfiguration.setLocalCertificate(certif);
sslCertificateFile.close();
sslCertificateFile.open(QIODevice::ReadOnly);
QSslKey key(&sslCertificateFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
qDebug() << "key isNull ? " << key.isNull();
sslConfiguration.setPrivateKey(key);
sslConfiguration.setProtocol(QSsl::SslV2);
sslConfiguration.setPeerVerifyMode(QSslSocket::Que ryPeer);
request.setSslConfiguration(sslConfiguration);
}
...
qDebug() << "send post";
m_networkReply = m_networkAccessManager->post(request, m_tempFile); // m_networkAccessManager est QNetworkAccessManager
...
void QSoapServiceClient::slotNetworkReplyError(QNetwork Reply::NetworkError)
{
qDebug() << "QSoapServiceClient::slotNetworkReplyError: " << m_networkReply->errorString();
m_answer = "";
}


And I obtain at runtime:

setting up SSL configuration: "/path/to/pem/file"
certif version= "" , serial= "" , issuer= "xxx" and subject= "yyy"
key isNull ? false
send post
connecting reply signals
sent
QSoapServiceClient::slotNetworkReplyError: "SSL handshake failed"


Note that by using a QProcess launching curl with options -k and -E, it works... Thus the certificate is OK. It's really my code which is bad but I cannot see where...

Any idea ?

jacek
13th February 2009, 23:38
Maybe you should run wireshark and compare what your application and curl do?

kleag
15th February 2009, 21:58
jacek: That was a good idea! I did the test with wireshark and found a difference: the curl call uses TLSv1 while the QNetworkAccessManager one use SSLv3.

Thus, I tried to force the use of TLSv1 with no success. I did:


sslConfiguration.setProtocol(QSsl::TlsV1);
request.setSslConfiguration(sslConfiguration);
qDebug() << "send post" << request.sslConfiguration().protocol();
m_networkReply = m_networkAccessManager->post(request, m_tempFile);

Then the qDebug write 'send post 2' where 2 is the value for TLSv1, but wireshark still shows a connection with SSLv3.

I tried to llok at the Qt code to see if there was not a problem in the handling of this configuration but was not able to find anything...

More ideas ? Does it look like a Qt bug ? Do you think that I am ready to report it or should I do more tests ?

AuE
21st October 2009, 07:26
Hi,
did anyone solve this?
I'm facing same problem! Everytime I try to connect I recieve the handshake failed!


Where do you get the "request" variablefrom?? This one doesnt work for me so far!

I tried to do a reimplement of the code above but



void MainWindow::setUpSSL()
{
QFile file(":/cert/client.pem");
// QtSoapHttpTransport http;/*defined in h*/
QNetworkReply *request = http.networkReply(); // this fails....ok its a NULL ptr. when is it initialied? Or better what to use to set the cert?
Q_ASSERT(file.open(QIODevice::ReadOnly));
QSslCertificate cert(&file, QSsl::Pem);
file.close();

if(cert.isValid() && !cert.isNull())
{

QSslConfiguration sslConfiguration = request->sslConfiguration();
sslConfiguration.setLocalCertificate(cert);
file.close();
file.open(QIODevice::ReadOnly);
QSslKey key(&file, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
qDebug() << "key isNull ? " << key.isNull();
sslConfiguration.setPrivateKey(key);
sslConfiguration.setProtocol(QSsl::SslV2);
sslConfiguration.setPeerVerifyMode(QSslSocket::Que ryPeer);
request->setSslConfiguration(sslConfiguration);
}
qDebug() << "sending post";

}




BTW:
I find it quite strange that I only get the readyResponse Signal
I'm connected to several others
connect(http.networkAccessManager(), SIGNAL(authenticationRequired(QNetworkReply*,QAuth enticator*))
,this, SLOT(authReq(QNetworkReply*,QAuthenticator*)));

connect(http.networkAccessManager(),SIGNAL(sslErro rs(QNetworkReply*,QList<QSslError>)), this, SLOT(on_sslErr(QNetworkReply*,QList<QSslError>)));
connect(http.networkAccessManager(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,Q Authenticator*)), this,SLOT(on_proxyReq(QNetworkProxy,QAuthenticator *)));

connect(&http, SIGNAL(responseReady()), SLOT(readResponse()));

Only Slot readresponse is called!.
Connect works fine (no messages in output pane)


Where amI doing something wrong??

AuE
21st October 2009, 11:14
Anyone of you has an idea or maybe some sample code how to connect to a server usig own certificate and ssl?

App Output


Network transport error (6): SSL handshake failed

"Unknown error"
"SSL handshake failed"
################################################## ##################################################
CA cert: (QSslCertificate("","","smth","MyCompany GmbH","MyCompany GmbH",QMap() , QDateTime("Mon Oct 30 15:49:02 2006") , QDateTime("Sun Oct 30 15:49:02 2011") ) )
Local cert QSslCertificate( "" , "" , "smth" , "MyCompany GmbH" , "MyCompany GmbH" , QMap() , QDateTime("Mon Oct 30 15:49:02 2006") , QDateTime("Sun Oct 30 15:49:02 2011") )
SSL Protocoll 1
Private Key QSslKey( PrivateKey , RSA , -1 )
################################################## ##################################################
"<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" >
<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Fault xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<Faultcode xsi:type="xsd:string" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" >SOAP-ENV:Client</Faultcode>
<Faultstring xsi:type="xsd:string" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" >Network transport error (6): SSL handshake failed</Faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"

qtcsteve
21st October 2009, 13:49
I too have had problems getting client certificates to work with Qt4.5.x, both with clients coded with Qt itself, and with libcurl.

I raised a bug in Tasktracker sometime ago (258725) but for some reason, it doesn't seem to show up when I do a search (do Nokia hide some of them, for some reason ?)

If anyone is sufficiently interested, I can send them a tarball of the code and bug report that I submitted to Tasktracker.

AuE
21st October 2009, 14:39
Hey!

How did you do this? Would love to see some code!
And did you solve it anyway?

When to set the QSslConfiguration?
How to get my Ssl cfg into the QtSoapHttpTransport class?

qtcsteve
21st October 2009, 15:25
>How did you do this?

I assume that you mean me ? If so, how did I do what ? How did I submit a bug report to Nokia ?

>Would love to see some code!

You want to see the code for the submitted bug report ?

>And did you solve it anyway?

No. It's still an outstanding problem. AFAICS there's a bug in Qt's SSL logic, and I'm hoping that they'll look at it someday. I've had no response to the bug report so far.

AuE
21st October 2009, 15:47
No,I mean how you found out that there is a bug!
The strange thing is: I connect to gammel.de using setHost("gammel.de", true);
and there I try to get the method "j_security_check" n the same subfolder.,
As soon as I do thos I receive the sslError Signal. Telling me that I do not have ca cert and so on!

But when I do this local this doesnt work! I just receive readyRead and the message is Fault!

May I see your code?

What do you think the the error comes from?
ow/where when do you submit your Sslconfiguraion?



QSslConfiguration sslConfiguration = request->sslConfiguration();
sslConfiguration.setLocalCertificate(cert);
file.close();
QString passphrase = "antivir_default";
file.open(QIODevice::ReadOnly);

QSslKey key(&file, QSsl::Rsa, QSsl::Pem,QSsl::PrivateKey , passphrase.toAscii());

sslConfiguration.setCaCertificates(QList<QSslCertificate>() << cert);
sslConfiguration.setPrivateKey(key);
sslConfiguration.setProtocol(QSsl::TlsV1);
sslConfiguration.setPeerVerifyMode(QSslSocket::Que ryPeer);



Where request is QNetworkReply *request = http.networkReply(); // this fails....ok its a NULL ptr. when is it initialied? Or better what to use to set the cert?
and http is QtSoapHttpTransport http;

So I thought with request->setSslConfiguration(sslConfiguration);
this would be used for next request but doesnt!

mgoetz
6th November 2009, 10:41
Hi,

Does it work when you do setProtocol(QSsl::AnyProtocol) ?