changeset 28509:17617d892bc4

oscar: Properly support TLS when using clientLogin.
author Paul Aurich <paul@darkrain42.org>
date Fri, 06 Nov 2009 03:58:26 +0000
parents 281bd8a973d8
children 7963477c2019
files ChangeLog libpurple/protocols/oscar/clientlogin.c libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h
diffstat 4 files changed, 48 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Nov 06 01:17:25 2009 +0000
+++ b/ChangeLog	Fri Nov 06 03:58:26 2009 +0000
@@ -11,14 +11,14 @@
 	* Fix building the GnuTLS plugin with older versions of GnuTLS.
 	* Fix DNS TXT query resolution.
 	* Always rejoin open chats after an account reconnects.
+
 	AIM and ICQ:
 	* Better rate limit calculations and other improvements.  (Aman Gupta)
 	* More detailed error messages when messages fail to send.  (Aman Gupta)
 	* The simultaneous login account option is respected when using
 	  the clientLogin authentication method.
-
-	AIM and ICQ:
 	* Fix offline message retrieval (broken in 2.6.3)
+	* Fix SSL when clientLogin is enabled.
 
 	MSN:
 	* Don't forget display names for buddies.
--- a/libpurple/protocols/oscar/clientlogin.c	Fri Nov 06 01:17:25 2009 +0000
+++ b/libpurple/protocols/oscar/clientlogin.c	Fri Nov 06 03:58:26 2009 +0000
@@ -40,6 +40,7 @@
 #include "core.h"
 
 #include "oscar.h"
+#include "oscarcommon.h"
 
 #define URL_CLIENT_LOGIN "https://api.screenname.aol.com/auth/clientLogin"
 #define URL_START_OSCAR_SESSION "http://api.oscar.aol.com/aim/startOSCARSession"
@@ -102,12 +103,15 @@
 	return signature;
 }
 
-static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie)
+static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie, char **tls_certname)
 {
 	xmlnode *response_node, *tmp_node, *data_node;
-	xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL;
+	xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL, *tls_node = NULL;
+	gboolean use_tls;
 	char *tmp;
 
+	use_tls = purple_account_get_bool(purple_connection_get_account(gc), "use_ssl", OSCAR_DEFAULT_USE_SSL);
+
 	/* Parse the response as XML */
 	response_node = xmlnode_from_str(response, response_len);
 	if (response_node == NULL)
@@ -131,6 +135,7 @@
 		host_node = xmlnode_get_child(data_node, "host");
 		port_node = xmlnode_get_child(data_node, "port");
 		cookie_node = xmlnode_get_child(data_node, "cookie");
+		tls_node = xmlnode_get_child(data_node, "tlsCertName");
 	}
 
 	/* Make sure we have a status code */
@@ -177,7 +182,8 @@
 
 	/* Make sure we have everything else */
 	if (data_node == NULL || host_node == NULL ||
-		port_node == NULL || cookie_node == NULL)
+		port_node == NULL || cookie_node == NULL ||
+		(use_tls && tls_node == NULL))
 	{
 		char *msg;
 		purple_debug_error("oscar", "startOSCARSession response was missing "
@@ -195,7 +201,12 @@
 	*host = xmlnode_get_data_unescaped(host_node);
 	tmp = xmlnode_get_data_unescaped(port_node);
 	*cookie = xmlnode_get_data_unescaped(cookie_node);
-	if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || cookie == NULL || *cookie == '\0')
+
+	if (use_tls)
+		*tls_certname = xmlnode_get_data_unescaped(tls_node);
+
+	if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || cookie == NULL || *cookie == '\0' ||
+			(use_tls && (*tls_certname == NULL || **tls_certname == '\0')))
 	{
 		char *msg;
 		purple_debug_error("oscar", "startOSCARSession response was missing "
@@ -223,6 +234,7 @@
 	OscarData *od;
 	PurpleConnection *gc;
 	char *host, *cookie;
+	char *tls_certname = NULL;
 	unsigned short port;
 	guint8 *cookiedata;
 	gsize cookiedata_len;
@@ -244,28 +256,30 @@
 		return;
 	}
 
-	if (!parse_start_oscar_session_response(gc, url_text, len, &host, &port, &cookie))
+	if (!parse_start_oscar_session_response(gc, url_text, len, &host, &port, &cookie, &tls_certname))
 		return;
 
 	cookiedata = purple_base64_decode(cookie, &cookiedata_len);
-	oscar_connect_to_bos(gc, od, host, port, cookiedata, cookiedata_len);
+	oscar_connect_to_bos(gc, od, host, port, cookiedata, cookiedata_len, tls_certname);
 	g_free(cookiedata);
 
 	g_free(host);
 	g_free(cookie);
+	g_free(tls_certname);
 }
 
 static void send_start_oscar_session(OscarData *od, const char *token, const char *session_key, time_t hosttime)
 {
 	char *query_string, *signature, *url;
+	gboolean use_tls = purple_account_get_bool(purple_connection_get_account(od->gc), "use_ssl", OSCAR_DEFAULT_USE_SSL);
 
 	/* Construct the GET parameters */
 	query_string = g_strdup_printf("a=%s"
 			"&f=xml"
 			"&k=%s"
 			"&ts=%" PURPLE_TIME_T_MODIFIER
-			"&useTLS=0",
-			purple_url_encode(token), get_client_key(od), hosttime);
+			"&useTLS=%d",
+			purple_url_encode(token), get_client_key(od), hosttime, use_tls);
 	signature = generate_signature("GET", URL_START_OSCAR_SESSION,
 			query_string, session_key);
 	url = g_strdup_printf(URL_START_OSCAR_SESSION "?%s&sig_sha256=%s",
--- a/libpurple/protocols/oscar/oscar.c	Fri Nov 06 01:17:25 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Fri Nov 06 03:58:26 2009 +0000
@@ -1827,17 +1827,35 @@
 	return 1;
 }
 
-int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen)
+int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname)
 {
+	PurpleAccount *account;
 	FlapConnection *conn;
 
+	account = purple_connection_get_account(gc);
+
 	conn = flap_connection_new(od, SNAC_FAMILY_LOCATE);
 	conn->cookielen = cookielen;
 	conn->cookie = g_memdup(cookie, cookielen);
-	conn->connect_data = purple_proxy_connect(NULL,
-			purple_connection_get_account(gc), host, port,
-			connection_established_cb, conn);
-	if (conn->connect_data == NULL)
+
+	/*
+	 * tls_certname is only set (and must be set if we get this far) if
+	 * SSL is enabled.
+	 */
+	if (tls_certname)
+	{
+		conn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port,
+				ssl_connection_established_cb, ssl_connection_error_cb,
+				tls_certname, conn);
+	}
+	else
+	{
+		conn->connect_data = purple_proxy_connect(NULL,
+				account, host, port,
+				connection_established_cb, conn);
+	}
+
+	if (conn->gsc == NULL && conn->connect_data == NULL)
 	{
 		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
 		return 0;
--- a/libpurple/protocols/oscar/oscar.h	Fri Nov 06 01:17:25 2009 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Fri Nov 06 03:58:26 2009 +0000
@@ -623,7 +623,7 @@
 	} chat;
 };
 
-int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen);
+int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname);
 
 /* family_auth.c */