# HG changeset patch # User Paul Aurich # Date 1270099604 0 # Node ID df9de37e02748eb8590ad251901a59ad29ac3fa8 # Parent 89de871ecffc3dc44d60d15020b079cf88a0ea09 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). diff -r 89de871ecffc -r df9de37e0274 ChangeLog --- a/ChangeLog Thu Apr 01 04:58:17 2010 +0000 +++ b/ChangeLog Thu Apr 01 05:26:44 2010 +0000 @@ -6,6 +6,9 @@ * Changed GLib minimum version requirement to 2.12.0. * Using the --disable-nls argument to configre now works properly. You will no longer be forced to have intltool to configure and build. + * Fix two related crashes in the GnuTLS and NSS plugins when they + suffer internal errors immediately upon attempting to establish + an SSL connection. * Added support for PURPLE_GNUTLS_PRIORITIES environment variable. This can be used to specify GnuTLS priorities on a per-host basis. The format is "host=priority;host2=priority;...". The default diff -r 89de871ecffc -r df9de37e0274 libpurple/plugins/ssl/ssl-gnutls.c --- a/libpurple/plugins/ssl/ssl-gnutls.c Thu Apr 01 04:58:17 2010 +0000 +++ b/libpurple/plugins/ssl/ssl-gnutls.c Thu Apr 01 05:26:44 2010 +0000 @@ -36,6 +36,7 @@ { gnutls_session session; guint handshake_handler; + guint handshake_timer; } PurpleSslGnutlsData; #define PURPLE_SSL_GNUTLS_DATA(gsc) ((PurpleSslGnutlsData *)gsc->private_data) @@ -367,6 +368,19 @@ } +static gboolean +start_handshake_cb(gpointer data) +{ + PurpleSslConnection *gsc = data; + PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); + + purple_debug_info("gnutls", "Starting handshake with %s\n", gsc->host); + + gnutls_data->handshake_timer = 0; + + ssl_gnutls_handshake_cb(gsc, gsc->fd, PURPLE_INPUT_READ); + return FALSE; +} static void ssl_gnutls_connect(PurpleSslConnection *gsc) @@ -410,10 +424,8 @@ gnutls_data->handshake_handler = purple_input_add(gsc->fd, PURPLE_INPUT_READ, ssl_gnutls_handshake_cb, gsc); - purple_debug_info("gnutls", "Starting handshake with %s\n", gsc->host); - /* Orborde asks: Why are we configuring a callback, then - immediately calling it? + (almost) immediately calling it? Answer: gnutls_handshake (up in handshake_cb) needs to be called once in order to get the ball rolling on the SSL connection. @@ -424,7 +436,8 @@ and subsequent calls, we'll just fire the callback immediately to accomplish this. */ - ssl_gnutls_handshake_cb(gsc, gsc->fd, PURPLE_INPUT_READ); + gnutls_data->handshake_timer = purple_timeout_add(0, start_handshake_cb, + gsc); } static void @@ -437,6 +450,8 @@ if(gnutls_data->handshake_handler) purple_input_remove(gnutls_data->handshake_handler); + if (gnutls_data->handshake_timer) + purple_timeout_remove(gnutls_data->handshake_timer); gnutls_bye(gnutls_data->session, GNUTLS_SHUT_RDWR); diff -r 89de871ecffc -r df9de37e0274 libpurple/plugins/ssl/ssl-nss.c --- a/libpurple/plugins/ssl/ssl-nss.c Thu Apr 01 04:58:17 2010 +0000 +++ b/libpurple/plugins/ssl/ssl-nss.c Thu Apr 01 05:26:44 2010 +0000 @@ -51,7 +51,7 @@ PRFileDesc *fd; PRFileDesc *in; guint handshake_handler; - + guint handshake_timer; } PurpleSslNssData; #define PURPLE_SSL_NSS_DATA(gsc) ((PurpleSslNssData *)gsc->private_data) @@ -368,6 +368,18 @@ } } +static gboolean +start_handshake_cb(gpointer data) +{ + PurpleSslConnection *gsc = data; + PurpleSslNssData *nss_data = PURPLE_SSL_NSS_DATA(gsc); + + nss_data->handshake_timer = 0; + + ssl_nss_handshake_cb(gsc, gsc->fd, PURPLE_INPUT_READ); + return FALSE; +} + static void ssl_nss_connect(PurpleSslConnection *gsc) { @@ -438,7 +450,7 @@ nss_data->handshake_handler = purple_input_add(gsc->fd, PURPLE_INPUT_READ, ssl_nss_handshake_cb, gsc); - ssl_nss_handshake_cb(gsc, gsc->fd, PURPLE_INPUT_READ); + nss_data->handshake_timer = purple_timeout_add(0, start_handshake_cb, gsc); } static void @@ -460,6 +472,9 @@ if (nss_data->handshake_handler) purple_input_remove(nss_data->handshake_handler); + if (nss_data->handshake_timer) + purple_timeout_remove(nss_data->handshake_timer); + g_free(nss_data); gsc->private_data = NULL; }