pidgin: 3b944aaf: gnutls: Use gnutls_priority_init for the...

darkrain42 at pidgin.im darkrain42 at pidgin.im
Thu Apr 1 02:42:11 EDT 2010


-----------------------------------------------------------------
Revision: 3b944aafdeba3b75bf206536534e8db56c5bd70f
Ancestor: dfecabe492257b96e1cdc59323c35a3605a9f68c
Author: darkrain42 at pidgin.im
Date: 2010-04-01T04:54:43
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/3b944aafdeba3b75bf206536534e8db56c5bd70f

Modified files:
        libpurple/plugins/ssl/ssl-gnutls.c

ChangeLog: 

gnutls: Use gnutls_priority_init for the default priority.

This contains hacks to work around a memory leak (on invalid priority
strings) in GnuTLS.

-------------- next part --------------
============================================================
--- libpurple/plugins/ssl/ssl-gnutls.c	9857f9843f5fcd823db5632fab9ac824e89f1ccb
+++ libpurple/plugins/ssl/ssl-gnutls.c	7a0c8b54c6bd1e12c9ebddbd9c24fae3758e365e
@@ -43,10 +43,15 @@ static gnutls_certificate_client_credent
 static gnutls_certificate_client_credentials xcred = NULL;
 
 #ifdef HAVE_GNUTLS_PRIORITY_FUNCS
-/* Priority strings.  The default one is, well, the default (and is always set).
- * The hash table is of the form hostname => priority (both char *)
+/* Priority strings.  The default one is, well, the default (and is always
+ * set).  The hash table is of the form hostname => priority (both
+ * char *).
+ *
+ * We only use a gnutls_priority_t for the default on the assumption that
+ * that's the more common case.  Improvement patches (like matching on
+ * subdomains) welcome.
  */
-static char *default_priority = NULL;
+static gnutls_priority_t default_priority = NULL;
 static GHashTable *host_priorities = NULL;
 #endif
 
@@ -104,6 +109,7 @@ ssl_gnutls_init_gnutls(void)
 		                     "this. :-(");
 #else /* HAVE_GNUTLS_PRIORITY_FUNCS */
 		char **entries = g_strsplit(host_priorities_str, ";", -1);
+		char *default_priority_str = NULL;
 		guint i;
 
 		host_priorities = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -126,8 +132,8 @@ ssl_gnutls_init_gnutls(void)
 					/* TODO: Validate each of these and complain */
 					if (g_str_equal(host, "*")) {
 						/* Override the default priority */
-						g_free(default_priority);
-						default_priority = g_strdup(prio_str);
+						g_free(default_priority_str);
+						default_priority_str = g_strdup(prio_str);
 					} else
 						g_hash_table_insert(host_priorities, g_strdup(host),
 						                    g_strdup(prio_str));
@@ -135,14 +141,33 @@ ssl_gnutls_init_gnutls(void)
 			}
 		}
 
+		if (default_priority_str) {
+			if (gnutls_priority_init(&default_priority, default_priority_str, NULL)) {
+				purple_debug_warning("gnutls", "Unable to set default priority to %s\n",
+				                     default_priority_str);
+				/* Versions of GnuTLS as of 2.8.6 (2010-03-31) don't free/NULL
+				 * this on error.
+				 */
+				gnutls_free(default_priority);
+				default_priority = NULL;
+			}
+
+			g_free(default_priority_str);
+		}
+
 		g_strfreev(entries);
 #endif /* HAVE_GNUTLS_PRIORITY_FUNCS */
 	}
 
 #ifdef HAVE_GNUTLS_PRIORITY_FUNCS
 	/* Make sure we set have a default priority! */
-	if (!default_priority)
-		default_priority = g_strdup("NORMAL:%SSL3_RECORD_VERSION");
+	if (!default_priority) {
+		if (gnutls_priority_init(&default_priority, "NORMAL:%SSL3_RECORD_VERSION", NULL)) {
+			/* See comment above about memory leak */
+			gnutls_free(default_priority);
+			gnutls_priority_init(&default_priority, "NORMAL", NULL);
+		}
+	}
 #endif /* HAVE_GNUTLS_PRIORITY_FUNCS */
 
 	gnutls_global_init();
@@ -174,7 +199,7 @@ ssl_gnutls_uninit(void)
 		host_priorities = NULL;
 	}
 
-	g_free(default_priority);
+	gnutls_priority_deinit(default_priority);
 	default_priority = NULL;
 #endif
 }
@@ -356,24 +381,19 @@ ssl_gnutls_connect(PurpleSslConnection *
 #ifdef HAVE_GNUTLS_PRIORITY_FUNCS
 	{
 		const char *prio_str = NULL;
+		gboolean set = FALSE;
 
 		/* Let's see if someone has specified a specific priority */
 		if (gsc->host && host_priorities)
 			prio_str = g_hash_table_lookup(host_priorities, gsc->host);
 
-		/* If not, let's use the default! */
-		if (!prio_str)
-			prio_str = default_priority;
+		if (prio_str)
+			set = (GNUTLS_E_SUCCESS ==
+					gnutls_priority_set_direct(gnutls_data->session, prio_str,
+				                               NULL));
 
-		/* TODO: Use a gnutls_priority_t cache, so this doesn't require three levels! */
-		/* The logic here is to try the specified string, fall back to the default
-		 * (which may also be user-specified), and if *that* doesn't work, fall back
-		 * to the default default (which I'm not sure is necessary, but whatever).
-		 */
-		if (gnutls_priority_set_direct(gnutls_data->session,
-		                               prio_str, NULL))
-			if (gnutls_priority_set_direct(gnutls_data->session, default_priority, NULL))
-				gnutls_priority_set_direct(gnutls_data->session, "NORMAL", NULL);
+		if (!set)
+			gnutls_priority_set(gnutls_data->session, default_priority);
 	}
 #else
 	gnutls_set_default_priority(gnutls_data->session);


More information about the Commits mailing list