changeset 22657:23fe481afccf

The next version of RFC 3920, the draft of which can be found at http://www.xmpp.org/internet-drafts/draft-saintandre-rfc3920bis-04.html, and subsequent email clarifications with Peter Saint-Andre and Alexey Melnikov indicate that we should be trying the next mechanism in line after one mechanism fails. We should also be ensuring that the mech list is sorted in order of descending security, which we don't do yet; however, servers are supposed to send us a sorted list, as well, so this isn't a major issue. committer: Evan Schoenberg <evan.s@dreskin.net>
author Stu Tomlinson <stu@nosnilmot.com>
date Sun, 13 Apr 2008 06:37:47 +0000
parents def8f39f542a
children 5cc1bb16edcd e062a1dfe6ad
files libpurple/protocols/jabber/auth.c libpurple/protocols/jabber/jabber.h
diffstat 2 files changed, 28 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/auth.c	Sat Apr 12 23:34:27 2008 +0000
+++ b/libpurple/protocols/jabber/auth.c	Sun Apr 13 06:37:47 2008 +0000
@@ -264,7 +264,7 @@
 
 static void jabber_auth_start_cyrus(JabberStream *js)
 {
-	const char *clientout = NULL, *mech = NULL;
+	const char *clientout = NULL;
 	char *enc_out;
 	unsigned coutlen = 0;
 	xmlnode *auth;
@@ -297,7 +297,7 @@
 		if (js->sasl_state==SASL_OK) {
 			sasl_setprop(js->sasl, SASL_SEC_PROPS, &secprops);
 			purple_debug_info("sasl", "Mechs found: %s\n", js->sasl_mechs->str);
-			js->sasl_state = sasl_client_start(js->sasl, js->sasl_mechs->str, NULL, &clientout, &coutlen, &mech);
+			js->sasl_state = sasl_client_start(js->sasl, js->sasl_mechs->str, NULL, &clientout, &coutlen, &js->current_mech);
 		}
 		switch (js->sasl_state) {
 			/* Success */
@@ -372,10 +372,10 @@
 				 * due to mechanism specific issues, so we want to try one of the other
 				 * supported mechanisms. This code handles that case
 				 */
-				if (mech && strlen(mech) > 0) {
+				if (js->current_mech && strlen(js->current_mech) > 0) {
 					char *pos;
-					if ((pos = strstr(js->sasl_mechs->str, mech))) {
-						g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(mech));
+					if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) {
+						g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(js->current_mech));
 					}
 					again = TRUE;
 				}
@@ -387,7 +387,7 @@
 	if (js->sasl_state == SASL_CONTINUE || js->sasl_state == SASL_OK) {
 		auth = xmlnode_new("auth");
 		xmlnode_set_namespace(auth, "urn:ietf:params:xml:ns:xmpp-sasl");
-		xmlnode_set_attrib(auth, "mechanism", mech);
+		xmlnode_set_attrib(auth, "mechanism", js->current_mech);
 		if (clientout) {
 			if (coutlen == 0) {
 				xmlnode_insert_data(auth, "=", -1);
@@ -1101,8 +1101,24 @@
 void jabber_auth_handle_failure(JabberStream *js, xmlnode *packet)
 {
 	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-	char *msg = jabber_parse_error(js, packet, &reason);
+	char *msg;
 
+#ifdef HAVE_CYRUS_SASL
+	if(js->auth_fail_count++ < 5) {
+		if (js->current_mech && strlen(js->current_mech) > 0) {
+			char *pos;
+			if ((pos = strstr(js->sasl_mechs->str, js->current_mech))) {
+				g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(js->current_mech));
+			}
+		}
+
+		sasl_dispose(&js->sasl);
+
+		jabber_auth_start_cyrus(js);
+		return;
+	}
+#endif
+	msg = jabber_parse_error(js, packet, &reason);
 	if(!msg) {
 		purple_connection_error_reason (js->gc,
 			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
--- a/libpurple/protocols/jabber/jabber.h	Sat Apr 12 23:34:27 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Sun Apr 13 06:37:47 2008 +0000
@@ -158,6 +158,11 @@
 	void *sasl;
 	void *sasl_cb;
 #endif
+	/* did someone say something about the end of the struct? */
+#ifdef HAVE_CYRUS_SASL
+	const char *current_mech;
+	int auth_fail_count;
+#endif
 
 	int sasl_state;
 	int sasl_maxbuf;