Mercurial > pidgin
comparison libpurple/plugins/ssl/ssl-gnutls.c @ 29659:df9de37e0274
gnutls/nss: Don't call the handshake functions synchronously. Fixes #11525
If the handshake callbacks are called sychronously and they fail
(e.g. passing GnuTLS a bad priority string or doing voodoo with NSS, see
#11524 for details), the error_cb is called and the gsc destroyed, but this
happens /before/ the assignment to, e.g., js->gsc happens (see
jabber.c:tls_init). Thus, js->gsc is assigned a (now invalid) pointer
and jabber_close tries to free it (again).
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Thu, 01 Apr 2010 05:26:44 +0000 |
parents | 1b8ed243d6d1 |
children | 43af903bd816 |
comparison
equal
deleted
inserted
replaced
29658:89de871ecffc | 29659:df9de37e0274 |
---|---|
34 | 34 |
35 typedef struct | 35 typedef struct |
36 { | 36 { |
37 gnutls_session session; | 37 gnutls_session session; |
38 guint handshake_handler; | 38 guint handshake_handler; |
39 guint handshake_timer; | |
39 } PurpleSslGnutlsData; | 40 } PurpleSslGnutlsData; |
40 | 41 |
41 #define PURPLE_SSL_GNUTLS_DATA(gsc) ((PurpleSslGnutlsData *)gsc->private_data) | 42 #define PURPLE_SSL_GNUTLS_DATA(gsc) ((PurpleSslGnutlsData *)gsc->private_data) |
42 | 43 |
43 static gnutls_certificate_client_credentials xcred = NULL; | 44 static gnutls_certificate_client_credentials xcred = NULL; |
365 } | 366 } |
366 } | 367 } |
367 | 368 |
368 } | 369 } |
369 | 370 |
371 static gboolean | |
372 start_handshake_cb(gpointer data) | |
373 { | |
374 PurpleSslConnection *gsc = data; | |
375 PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); | |
376 | |
377 purple_debug_info("gnutls", "Starting handshake with %s\n", gsc->host); | |
378 | |
379 gnutls_data->handshake_timer = 0; | |
380 | |
381 ssl_gnutls_handshake_cb(gsc, gsc->fd, PURPLE_INPUT_READ); | |
382 return FALSE; | |
383 } | |
370 | 384 |
371 static void | 385 static void |
372 ssl_gnutls_connect(PurpleSslConnection *gsc) | 386 ssl_gnutls_connect(PurpleSslConnection *gsc) |
373 { | 387 { |
374 PurpleSslGnutlsData *gnutls_data; | 388 PurpleSslGnutlsData *gnutls_data; |
408 gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(gsc->fd)); | 422 gnutls_transport_set_ptr(gnutls_data->session, GINT_TO_POINTER(gsc->fd)); |
409 | 423 |
410 gnutls_data->handshake_handler = purple_input_add(gsc->fd, | 424 gnutls_data->handshake_handler = purple_input_add(gsc->fd, |
411 PURPLE_INPUT_READ, ssl_gnutls_handshake_cb, gsc); | 425 PURPLE_INPUT_READ, ssl_gnutls_handshake_cb, gsc); |
412 | 426 |
413 purple_debug_info("gnutls", "Starting handshake with %s\n", gsc->host); | |
414 | |
415 /* Orborde asks: Why are we configuring a callback, then | 427 /* Orborde asks: Why are we configuring a callback, then |
416 immediately calling it? | 428 (almost) immediately calling it? |
417 | 429 |
418 Answer: gnutls_handshake (up in handshake_cb) needs to be called | 430 Answer: gnutls_handshake (up in handshake_cb) needs to be called |
419 once in order to get the ball rolling on the SSL connection. | 431 once in order to get the ball rolling on the SSL connection. |
420 Once it has done so, only then will the server reply, triggering | 432 Once it has done so, only then will the server reply, triggering |
421 the callback. | 433 the callback. |
422 | 434 |
423 Since the logic driving gnutls_handshake is the same with the first | 435 Since the logic driving gnutls_handshake is the same with the first |
424 and subsequent calls, we'll just fire the callback immediately to | 436 and subsequent calls, we'll just fire the callback immediately to |
425 accomplish this. | 437 accomplish this. |
426 */ | 438 */ |
427 ssl_gnutls_handshake_cb(gsc, gsc->fd, PURPLE_INPUT_READ); | 439 gnutls_data->handshake_timer = purple_timeout_add(0, start_handshake_cb, |
440 gsc); | |
428 } | 441 } |
429 | 442 |
430 static void | 443 static void |
431 ssl_gnutls_close(PurpleSslConnection *gsc) | 444 ssl_gnutls_close(PurpleSslConnection *gsc) |
432 { | 445 { |
435 if(!gnutls_data) | 448 if(!gnutls_data) |
436 return; | 449 return; |
437 | 450 |
438 if(gnutls_data->handshake_handler) | 451 if(gnutls_data->handshake_handler) |
439 purple_input_remove(gnutls_data->handshake_handler); | 452 purple_input_remove(gnutls_data->handshake_handler); |
453 if (gnutls_data->handshake_timer) | |
454 purple_timeout_remove(gnutls_data->handshake_timer); | |
440 | 455 |
441 gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR); | 456 gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR); |
442 | 457 |
443 gnutls_deinit(gnutls_data->session); | 458 gnutls_deinit(gnutls_data->session); |
444 | 459 |