Mercurial > trustbridge
comparison 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 |
comparison
equal
deleted
inserted
replaced
45:c6125d73faf4 | 46:d28e2624c1d5 |
---|---|
5 #include <QFile> | 5 #include <QFile> |
6 #include <QUuid> | 6 #include <QUuid> |
7 #include <QApplication> | 7 #include <QApplication> |
8 | 8 |
9 #define MAX_IO_TRIES 10 | 9 #define MAX_IO_TRIES 10 |
10 #define MAX_RESETS 10 | |
10 | 11 |
11 #ifdef CONNECTION_DEBUG | 12 #ifdef CONNECTION_DEBUG |
12 static void my_debug(void *ctx, int level, const char *str) | 13 static void my_debug(void *ctx, int level, const char *str) |
13 { | 14 { |
14 fprintf((FILE *) ctx, "%s", str); | 15 fprintf((FILE *) ctx, "%s", str); |
34 mErrorState(NoError) | 35 mErrorState(NoError) |
35 { | 36 { |
36 int ret = -1; | 37 int ret = -1; |
37 | 38 |
38 memset(&mSSL, 0, sizeof(ssl_context)); | 39 memset(&mSSL, 0, sizeof(ssl_context)); |
40 memset(&mSavedSession, 0, sizeof( ssl_session ) ); | |
39 | 41 |
40 if (certificate.isEmpty()) { | 42 if (certificate.isEmpty()) { |
41 QFile certResource(":certs/kolab.org"); | 43 QFile certResource(":certs/kolab.org"); |
42 certResource.open(QFile::ReadOnly); | 44 certResource.open(QFile::ReadOnly); |
43 mPinnedCert = certResource.readAll(); | 45 mPinnedCert = certResource.readAll(); |
109 | 111 |
110 return 0; | 112 return 0; |
111 } | 113 } |
112 | 114 |
113 SSLConnection::~SSLConnection() { | 115 SSLConnection::~SSLConnection() { |
114 if (mConnected) { | 116 disconnect(); |
115 ssl_close_notify (&mSSL); | |
116 if (mServerFD != -1) { | |
117 net_close(mServerFD); | |
118 mServerFD = -1; | |
119 } | |
120 } | |
121 x509_crt_free(&mX509PinnedCert); | 117 x509_crt_free(&mX509PinnedCert); |
122 entropy_free(&mEntropy); | 118 entropy_free(&mEntropy); |
123 if (mInitialized) { | 119 if (mInitialized) { |
124 ssl_free(&mSSL); | 120 ssl_free(&mSSL); |
125 } | 121 } |
126 } | 122 } |
127 | 123 |
124 void SSLConnection::disconnect() { | |
125 if (mConnected) { | |
126 ssl_close_notify(&mSSL); | |
127 if (mServerFD != -1) { | |
128 net_close(mServerFD); | |
129 mServerFD = -1; | |
130 } | |
131 ssl_session_free(&mSavedSession); | |
132 mConnected = false; | |
133 } | |
134 } | |
135 | |
128 int SSLConnection::connect() { | 136 int SSLConnection::connect() { |
129 int ret = -1; | 137 int ret = -1; |
130 const x509_crt *peerCert; | |
131 | 138 |
132 if (!mInitialized) { | 139 if (!mInitialized) { |
133 mErrorState = ErrUnknown; | 140 mErrorState = ErrUnknown; |
134 return -1; | 141 return -1; |
135 } | 142 } |
136 | 143 |
137 ret = net_connect(&mServerFD, mUrl.host().toLatin1().constData(), | 144 ret = net_connect(&mServerFD, mUrl.host().toLatin1().constData(), |
138 mUrl.port(443)); | 145 mUrl.port(443)); |
139 | 146 |
140 if (ret != 0) { | 147 if (ret != 0) { |
148 qDebug() << "Connect failed: " << getErrorMsg(ret); | |
141 mErrorState = NoConnection; | 149 mErrorState = NoConnection; |
142 return ret; | 150 return ret; |
143 } | 151 } |
144 | 152 |
145 ssl_set_bio(&mSSL, net_recv, &mServerFD, | 153 ssl_set_bio(&mSSL, net_recv, &mServerFD, |
146 net_send, &mServerFD); | 154 net_send, &mServerFD); |
147 | 155 |
148 while ((ret = ssl_handshake(&mSSL)) != 0) { | 156 while ((ret = ssl_handshake(&mSSL)) != 0) { |
149 if (ret != POLARSSL_ERR_NET_WANT_READ && | 157 if (ret != POLARSSL_ERR_NET_WANT_READ && |
150 ret != POLARSSL_ERR_NET_WANT_WRITE) { | 158 ret != POLARSSL_ERR_NET_WANT_WRITE) { |
151 qDebug() << "SSL Handshake failed: " | 159 qDebug() << "SSL Handshake failed: " << getErrorMsg(ret); |
152 << getErrorMsg(ret); | |
153 mErrorState = SSLHandshakeFailed; | 160 mErrorState = SSLHandshakeFailed; |
154 return ret; | 161 return ret; |
155 } | 162 } |
156 } | 163 } |
164 | |
165 ret = ssl_get_session(&mSSL, &mSavedSession); | |
166 if (ret != 0) { | |
167 qDebug() << "SSL get session failed: " << getErrorMsg(ret); | |
168 | |
169 mErrorState = NoConnection; | |
170 return ret; | |
171 } | |
172 printf( " ok\n [ Ciphersuite is %s ]\n", | |
173 ssl_get_ciphersuite( &mSSL) ); | |
174 ret = validateCertificate(); | |
175 | |
176 if (ret == 0) { | |
177 mConnected = true; | |
178 } | |
179 return ret; | |
180 } | |
181 | |
182 int SSLConnection::validateCertificate() | |
183 { | |
184 int ret = -1; | |
185 const x509_crt *peerCert = NULL; | |
157 | 186 |
158 /* we might want to set the verify function | 187 /* we might want to set the verify function |
159 * with ssl_set_verify before to archive the | 188 * with ssl_set_verify before to archive the |
160 * certificate pinning. */ | 189 * certificate pinning. */ |
161 | 190 |
216 int ret = -1; | 245 int ret = -1; |
217 | 246 |
218 const unsigned char *buf = (const unsigned char *) request.constData(); | 247 const unsigned char *buf = (const unsigned char *) request.constData(); |
219 size_t len = (size_t) request.size(); | 248 size_t len = (size_t) request.size(); |
220 | 249 |
221 qDebug() << "Seinding request: " << request; | 250 if (mNeedsReset) { |
251 ret = reset(); | |
252 if (ret != 0) { | |
253 qDebug() << "Reset failed: " << getErrorMsg(ret); | |
254 return ret; | |
255 } | |
256 } | |
257 | |
258 qDebug() << "Sending request: " << request; | |
222 /* According to doc for ssl_write: | 259 /* According to doc for ssl_write: |
223 * | 260 * |
224 * When this function returns POLARSSL_ERR_NET_WANT_WRITE, | 261 * When this function returns POLARSSL_ERR_NET_WANT_WRITE, |
225 * it must be called later with the same arguments, | 262 * it must be called later with the same arguments, |
226 * until it returns a positive value. | 263 * until it returns a positive value. |
233 } else { | 270 } else { |
234 qDebug() << "Write failed to write everything"; | 271 qDebug() << "Write failed to write everything"; |
235 return -1; | 272 return -1; |
236 } | 273 } |
237 } | 274 } |
238 | 275 if (ret != POLARSSL_ERR_NET_WANT_WRITE && |
239 if (ret != POLARSSL_ERR_NET_WANT_WRITE) { | 276 ret != POLARSSL_ERR_NET_WANT_READ) { |
240 return ret; | 277 return ret; |
241 } | 278 } |
242 tries++; | 279 tries++; |
243 net_usleep(100000); /* sleep 100ms to give the socket a chance | 280 net_usleep(100000); /* sleep 100ms to give the socket a chance |
244 to clean up. */ | 281 to clean up. */ |
245 } while (tries < MAX_IO_TRIES); | 282 } while (tries < MAX_IO_TRIES); |
246 | 283 |
247 return ret; | 284 return ret; |
248 } | 285 } |
249 | 286 |
287 | |
288 int SSLConnection::reset() | |
289 { | |
290 int ret = -1; | |
291 ssl_close_notify(&mSSL); | |
292 | |
293 ret = ssl_session_reset(&mSSL); | |
294 if (ret != 0) | |
295 { | |
296 qDebug() << "SSL Connection reset failed: " | |
297 << getErrorMsg(ret); | |
298 return ret; | |
299 } | |
300 | |
301 ssl_set_session(&mSSL, &mSavedSession); | |
302 | |
303 ret = net_connect(&mServerFD, mUrl.host().toLatin1().constData(), | |
304 mUrl.port(443)); | |
305 | |
306 if (ret != 0) { | |
307 mErrorState = NoConnection; | |
308 qDebug() << "Connection failed." << getErrorMsg(ret); | |
309 return ret; | |
310 } | |
311 | |
312 while ((ret = ssl_handshake(&mSSL)) != 0) { | |
313 if (ret != POLARSSL_ERR_NET_WANT_READ && | |
314 ret != POLARSSL_ERR_NET_WANT_WRITE) { | |
315 qDebug() << "SSL Handshake failed: " | |
316 << getErrorMsg(ret); | |
317 mErrorState = SSLHandshakeFailed; | |
318 return ret; | |
319 } | |
320 } | |
321 | |
322 qDebug() << "Reset connection. "; | |
323 /* Validation should not be necessary as we reused a saved | |
324 * session. But just to be sure. */ | |
325 return validateCertificate(); | |
326 } | |
327 | |
250 QByteArray SSLConnection::read(size_t len) | 328 QByteArray SSLConnection::read(size_t len) |
251 { | 329 { |
252 unsigned char buf[len]; | 330 unsigned char buf[len]; |
253 QByteArray retval(""); | 331 QByteArray retval(""); |
254 int ret = -1; | 332 int ret = -1; |
255 | 333 unsigned int tries = 0; |
334 | |
335 mNeedsReset = true; | |
256 do { | 336 do { |
257 memset (buf, 0, sizeof(buf)); | 337 memset (buf, 0, sizeof(buf)); |
258 ret = ssl_read(&mSSL, buf, len); | 338 ret = ssl_read(&mSSL, buf, len); |
339 qDebug() << "Read retval : " << ret; | |
340 qDebug() << "Len is: " << len; | |
259 if (ret == 0 || | 341 if (ret == 0 || |
260 ret == POLARSSL_ERR_SSL_CONN_EOF) { | 342 ret == POLARSSL_ERR_SSL_CONN_EOF || |
343 ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) { | |
261 /* EOF */ | 344 /* EOF */ |
262 return retval; | 345 return retval; |
346 } | |
347 if (ret == POLARSSL_ERR_NET_WANT_WRITE || | |
348 ret == POLARSSL_ERR_NET_WANT_READ) { | |
349 net_usleep(100000); /* sleep 100ms to give the socket a chance | |
350 to recover */ | |
351 tries++; | |
263 } | 352 } |
264 if (ret <= 0) { | 353 if (ret <= 0) { |
265 qDebug() << "Read failed: " << getErrorMsg(ret); | 354 qDebug() << "Read failed: " << getErrorMsg(ret); |
266 return QByteArray(); | 355 return QByteArray(); |
267 } | 356 } |
269 /* Should never happen if ssl_read behaves */ | 358 /* Should never happen if ssl_read behaves */ |
270 qDebug() << "integer overflow in polarSSLRead"; | 359 qDebug() << "integer overflow in polarSSLRead"; |
271 return QByteArray(); | 360 return QByteArray(); |
272 } | 361 } |
273 len -= (unsigned int) ret; | 362 len -= (unsigned int) ret; |
274 retval.append((const char *)buf, len); | 363 retval.append((const char *)buf, ret); |
275 } while (len > 0); | 364 } while (len > 0 && tries < MAX_IO_TRIES); |
276 | 365 |
277 return retval; | 366 return retval; |
278 } | 367 } |
279 | 368 |