Mercurial > trustbridge
diff ui/sslconnection.cpp @ 46:d28e2624c1d5
Reset connection before the next request.
This makes the downloader work for the first simple test.
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Mon, 17 Mar 2014 10:51:47 +0000 |
parents | c6125d73faf4 |
children | 0aacc291c04b |
line wrap: on
line diff
--- a/ui/sslconnection.cpp Fri Mar 14 16:40:53 2014 +0000 +++ b/ui/sslconnection.cpp Mon Mar 17 10:51:47 2014 +0000 @@ -7,6 +7,7 @@ #include <QApplication> #define MAX_IO_TRIES 10 +#define MAX_RESETS 10 #ifdef CONNECTION_DEBUG static void my_debug(void *ctx, int level, const char *str) @@ -36,6 +37,7 @@ int ret = -1; memset(&mSSL, 0, sizeof(ssl_context)); + memset(&mSavedSession, 0, sizeof( ssl_session ) ); if (certificate.isEmpty()) { QFile certResource(":certs/kolab.org"); @@ -111,13 +113,7 @@ } SSLConnection::~SSLConnection() { - if (mConnected) { - ssl_close_notify (&mSSL); - if (mServerFD != -1) { - net_close(mServerFD); - mServerFD = -1; - } - } + disconnect(); x509_crt_free(&mX509PinnedCert); entropy_free(&mEntropy); if (mInitialized) { @@ -125,9 +121,20 @@ } } +void SSLConnection::disconnect() { + if (mConnected) { + ssl_close_notify(&mSSL); + if (mServerFD != -1) { + net_close(mServerFD); + mServerFD = -1; + } + ssl_session_free(&mSavedSession); + mConnected = false; + } +} + int SSLConnection::connect() { int ret = -1; - const x509_crt *peerCert; if (!mInitialized) { mErrorState = ErrUnknown; @@ -138,6 +145,7 @@ mUrl.port(443)); if (ret != 0) { + qDebug() << "Connect failed: " << getErrorMsg(ret); mErrorState = NoConnection; return ret; } @@ -148,13 +156,34 @@ while ((ret = ssl_handshake(&mSSL)) != 0) { if (ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) { - qDebug() << "SSL Handshake failed: " - << getErrorMsg(ret); + qDebug() << "SSL Handshake failed: " << getErrorMsg(ret); mErrorState = SSLHandshakeFailed; return ret; } } + ret = ssl_get_session(&mSSL, &mSavedSession); + if (ret != 0) { + qDebug() << "SSL get session failed: " << getErrorMsg(ret); + + mErrorState = NoConnection; + return ret; + } + printf( " ok\n [ Ciphersuite is %s ]\n", + ssl_get_ciphersuite( &mSSL) ); + ret = validateCertificate(); + + if (ret == 0) { + mConnected = true; + } + return ret; +} + +int SSLConnection::validateCertificate() +{ + int ret = -1; + const x509_crt *peerCert = NULL; + /* we might want to set the verify function * with ssl_set_verify before to archive the * certificate pinning. */ @@ -218,7 +247,15 @@ const unsigned char *buf = (const unsigned char *) request.constData(); size_t len = (size_t) request.size(); - qDebug() << "Seinding request: " << request; + if (mNeedsReset) { + ret = reset(); + if (ret != 0) { + qDebug() << "Reset failed: " << getErrorMsg(ret); + return ret; + } + } + + qDebug() << "Sending request: " << request; /* According to doc for ssl_write: * * When this function returns POLARSSL_ERR_NET_WANT_WRITE, @@ -235,8 +272,8 @@ return -1; } } - - if (ret != POLARSSL_ERR_NET_WANT_WRITE) { + if (ret != POLARSSL_ERR_NET_WANT_WRITE && + ret != POLARSSL_ERR_NET_WANT_READ) { return ret; } tries++; @@ -247,20 +284,72 @@ return ret; } + +int SSLConnection::reset() +{ + int ret = -1; + ssl_close_notify(&mSSL); + + ret = ssl_session_reset(&mSSL); + if (ret != 0) + { + qDebug() << "SSL Connection reset failed: " + << getErrorMsg(ret); + return ret; + } + + ssl_set_session(&mSSL, &mSavedSession); + + ret = net_connect(&mServerFD, mUrl.host().toLatin1().constData(), + mUrl.port(443)); + + if (ret != 0) { + mErrorState = NoConnection; + qDebug() << "Connection failed." << getErrorMsg(ret); + return ret; + } + + while ((ret = ssl_handshake(&mSSL)) != 0) { + if (ret != POLARSSL_ERR_NET_WANT_READ && + ret != POLARSSL_ERR_NET_WANT_WRITE) { + qDebug() << "SSL Handshake failed: " + << getErrorMsg(ret); + mErrorState = SSLHandshakeFailed; + return ret; + } + } + + qDebug() << "Reset connection. "; + /* Validation should not be necessary as we reused a saved + * session. But just to be sure. */ + return validateCertificate(); +} + QByteArray SSLConnection::read(size_t len) { unsigned char buf[len]; QByteArray retval(""); int ret = -1; + unsigned int tries = 0; + mNeedsReset = true; do { memset (buf, 0, sizeof(buf)); ret = ssl_read(&mSSL, buf, len); + qDebug() << "Read retval : " << ret; + qDebug() << "Len is: " << len; if (ret == 0 || - ret == POLARSSL_ERR_SSL_CONN_EOF) { + ret == POLARSSL_ERR_SSL_CONN_EOF || + ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) { /* EOF */ return retval; } + if (ret == POLARSSL_ERR_NET_WANT_WRITE || + ret == POLARSSL_ERR_NET_WANT_READ) { + net_usleep(100000); /* sleep 100ms to give the socket a chance + to recover */ + tries++; + } if (ret <= 0) { qDebug() << "Read failed: " << getErrorMsg(ret); return QByteArray(); @@ -271,8 +360,8 @@ return QByteArray(); } len -= (unsigned int) ret; - retval.append((const char *)buf, len); - } while (len > 0); + retval.append((const char *)buf, ret); + } while (len > 0 && tries < MAX_IO_TRIES); return retval; }