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

http://wald.intevation.org/projects/trustbridge/