Merge branch 'senko'
authorMikael Hallendal <micke@imendio.com>
Mon, 25 Feb 2008 20:37:24 +0100
changeset 338 e89c3874d6eb
parent 337 7bc0c6ad11ff (current diff)
parent 332 6b6ad42cd508 (diff)
child 339 b1e0d0551a8c
Merge branch 'senko'
.cvsignore
loudmouth/lm-connection.c
loudmouth/lm-socket.c
--- a/loudmouth/lm-connection.c	Sun Feb 24 01:01:24 2008 +0100
+++ b/loudmouth/lm-connection.c	Mon Feb 25 20:37:24 2008 +0100
@@ -79,7 +79,7 @@
 	GSList       *handlers[LM_MESSAGE_TYPE_UNKNOWN];
 
 	/* XMPP1.0 stuff (SASL, resource binding, StartTLS) */
-	gboolean      use_xmpp;
+	gboolean      use_sasl;
 	LmSASL       *sasl;
 	gchar        *resource;
 	LmMessageHandler *features_cb;
@@ -455,11 +455,7 @@
 	}
 
 	if (!connection_get_server_from_jid (connection->jid, &domain)) {
-		g_set_error (error,
-			LM_ERROR,
-			LM_ERROR_CONNECTION_FAILED,
-			"You need to either set server hostname or jid");
-		return FALSE;
+		domain = g_strdup (connection->server);
 	}
 
 	lm_message_queue_attach (connection->queue, connection->context);
@@ -737,7 +733,7 @@
 		lm_verbose ("XMPP 1.0 stream received: %s\n",
 			    connection->stream_id);
 
-		connection->use_xmpp = TRUE;
+		connection->use_sasl = TRUE;
 		
 		/* stream is started multiple times, but we only want
 		 * one sasl mechanism */
@@ -787,7 +783,7 @@
 static void
 connection_stream_error (LmConnection *connection, LmMessage *m)
 {
-	LmMessageNode *node;
+	LmMessageNode *node, *reason_node;
 	LmDisconnectReason reason;
 
 	g_return_if_fail (connection != NULL);
@@ -796,16 +792,16 @@
 	node = m->node;
 
 	/* Resource conflict */
-	node = lm_message_node_get_child (node, "conflict");
-	if (node) {
+	reason_node = lm_message_node_get_child (node, "conflict");
+	if (reason_node) {
 		lm_verbose ("Stream error: Conflict (resource connected elsewhere)\n");
 		reason = LM_DISCONNECT_REASON_RESOURCE_CONFLICT;
 		return;
 	}
 
 	/* XML is crack */
-	node = lm_message_node_get_child (node, "xml-not-well-formed");
-	if (node) {
+	reason_node = lm_message_node_get_child (node, "xml-not-well-formed");
+	if (reason_node) {
 		lm_verbose ("Stream error: XML not well formed\n");
 		reason = LM_DISCONNECT_REASON_INVALID_XML;
 		return;
@@ -1039,6 +1035,7 @@
 {
 	LmMessageNode *bind_node;
 	LmMessageNode    *starttls_node;
+	LmMessageNode *old_auth;
 	
 	starttls_node = lm_message_node_find_child (message->node, "starttls");
 	if (connection->ssl && lm_ssl_get_use_starttls (connection->ssl)) {
@@ -1107,6 +1104,33 @@
 		}
 	}
 
+	old_auth = lm_message_node_find_child (message->node, "auth");
+	if (connection->use_sasl && old_auth) {
+		g_debug ("Server uses XEP-0078 (jabber iq auth) instead of SASL");
+		/* So the server is XMPP1.0, but doesn't support SASL and uses
+		 * obsolete XEP-0078 instead. Let's cope. */
+
+		connection->use_sasl = FALSE;
+
+		if (connection->sasl) {
+			const gchar *user, *pass;
+
+			lm_sasl_get_auth_params (connection->sasl, &user, &pass);
+			if (user && pass) {
+				GError *error = NULL;
+				_lm_connection_old_auth (connection, user, pass,
+					connection->resource, &error);
+
+				if (error)
+					g_error_free (error);
+
+			}
+
+			lm_sasl_free (connection->sasl);
+			connection->sasl = NULL;
+		}
+	}
+
 	return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
 }
 
@@ -1152,7 +1176,7 @@
 	connection->keep_alive_source = NULL;
 	connection->keep_alive_rate   = 0;
 	connection->socket            = NULL;
-	connection->use_xmpp          = FALSE;
+	connection->use_sasl          = FALSE;
 	connection->tls_started       = FALSE;
 	
 	connection->id_handlers = g_hash_table_new_full (g_str_hash, 
@@ -1384,11 +1408,6 @@
 			    GDestroyNotify     notify,
 			    GError           **error)
 {
-	LmMessage        *m;
-	LmMessageHandler *handler;
-	gboolean          result;
-	AuthReqData      *data;
-	
 	g_return_val_if_fail (connection != NULL, FALSE);
 	g_return_val_if_fail (username != NULL, FALSE);
 	g_return_val_if_fail (password != NULL, FALSE);
@@ -1412,7 +1431,7 @@
 	connection->effective_jid = g_strdup_printf ("%s/%s", 
 		connection->jid, connection->resource);
 
-	if (connection->use_xmpp) {
+	if (connection->use_sasl) {
 		lm_sasl_authenticate (connection->sasl,
 				      username, password,
 				      connection->server,
@@ -1429,6 +1448,20 @@
 		return TRUE;
 	}
 
+	return _lm_connection_old_auth (connection, username, password,
+		resource, error);
+}
+
+gboolean
+_lm_connection_old_auth (LmConnection *connection, const gchar *username,
+	const gchar *password, const gchar *resource, GError **error)
+{
+	LmMessage        *m;
+	AuthReqData      *data;
+	LmMessageHandler *handler;
+	gboolean          result;
+	
+
 	m = connection_create_auth_req_msg (username);
 		
 	data = g_new0 (AuthReqData, 1);
--- a/loudmouth/lm-connection.h	Sun Feb 24 01:01:24 2008 +0100
+++ b/loudmouth/lm-connection.h	Mon Feb 25 20:37:24 2008 +0100
@@ -164,6 +164,11 @@
 LmConnection* lm_connection_ref               (LmConnection       *connection);
 void          lm_connection_unref             (LmConnection       *connection);
 
+gboolean
+_lm_connection_old_auth (LmConnection *connection, const gchar *username,
+			 const gchar *password, const gchar *resource,
+			 GError **errror);
+
 
 G_END_DECLS
 
--- a/loudmouth/lm-message.c	Sun Feb 24 01:01:24 2008 +0100
+++ b/loudmouth/lm-message.c	Mon Feb 25 20:37:24 2008 +0100
@@ -36,14 +36,15 @@
 	{ LM_MESSAGE_TYPE_IQ,              "iq"              },
 	{ LM_MESSAGE_TYPE_STREAM,          "stream:stream"   },
 	{ LM_MESSAGE_TYPE_STREAM_FEATURES, "stream:features" },
+	{ LM_MESSAGE_TYPE_STREAM_ERROR,    "stream:error"    },
 	{ LM_MESSAGE_TYPE_AUTH,            "auth"            },
 	{ LM_MESSAGE_TYPE_CHALLENGE,       "challenge"       },
 	{ LM_MESSAGE_TYPE_RESPONSE,        "response"        },
 	{ LM_MESSAGE_TYPE_SUCCESS,         "success"         },
 	{ LM_MESSAGE_TYPE_FAILURE,         "failure"         },
-	{ LM_MESSAGE_TYPE_STREAM_ERROR,    "stream:error"    },
 	{ LM_MESSAGE_TYPE_PROCEED,         "proceed"         },
-	{ LM_MESSAGE_TYPE_STARTTLS,        "starttls"        }
+	{ LM_MESSAGE_TYPE_STARTTLS,        "starttls"        },
+	{ LM_MESSAGE_TYPE_UNKNOWN,         NULL              }
 };
 
 static struct SubTypeNames 
@@ -83,10 +84,10 @@
         }
 
         for (i = LM_MESSAGE_TYPE_MESSAGE;
-	     i <= LM_MESSAGE_TYPE_STARTTLS;
+	     i < LM_MESSAGE_TYPE_UNKNOWN;
 	     ++i) {
                 if (strcmp (type_str, type_names[i].name) == 0) {
-                        return i;
+                        return type_names[i].type;
                 }
         }
 
--- a/loudmouth/lm-message.h	Sun Feb 24 01:01:24 2008 +0100
+++ b/loudmouth/lm-message.h	Mon Feb 25 20:37:24 2008 +0100
@@ -42,13 +42,13 @@
 	LM_MESSAGE_TYPE_PRESENCE,
 	LM_MESSAGE_TYPE_IQ,
 	LM_MESSAGE_TYPE_STREAM,
+	LM_MESSAGE_TYPE_STREAM_ERROR,
 	LM_MESSAGE_TYPE_STREAM_FEATURES,
 	LM_MESSAGE_TYPE_AUTH,
 	LM_MESSAGE_TYPE_CHALLENGE,
 	LM_MESSAGE_TYPE_RESPONSE,
 	LM_MESSAGE_TYPE_SUCCESS,
 	LM_MESSAGE_TYPE_FAILURE,
-	LM_MESSAGE_TYPE_STREAM_ERROR,
 	LM_MESSAGE_TYPE_PROCEED,
 	LM_MESSAGE_TYPE_STARTTLS,
 	LM_MESSAGE_TYPE_UNKNOWN
--- a/loudmouth/lm-sasl.c	Sun Feb 24 01:01:24 2008 +0100
+++ b/loudmouth/lm-sasl.c	Mon Feb 25 20:37:24 2008 +0100
@@ -834,3 +834,11 @@
 }
 
 
+void
+lm_sasl_get_auth_params (LmSASL *sasl, const gchar **username,
+	const gchar **password)
+{
+	*username = sasl->username;
+	*password = sasl->password;
+}
+
--- a/loudmouth/lm-sasl.h	Sun Feb 24 01:01:24 2008 +0100
+++ b/loudmouth/lm-sasl.h	Mon Feb 25 20:37:24 2008 +0100
@@ -46,6 +46,10 @@
 
 void lm_sasl_free (LmSASL *sasl);
 
+void
+lm_sasl_get_auth_params (LmSASL *sasl, const gchar **username,
+	const gchar **password);
+
 G_END_DECLS
 
 #endif /* __LM_SASL_H__ */
--- a/loudmouth/lm-socket.c	Sun Feb 24 01:01:24 2008 +0100
+++ b/loudmouth/lm-socket.c	Mon Feb 25 20:37:24 2008 +0100
@@ -496,10 +496,12 @@
 			g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_NET,
 			       "Connection failed.\n");
 
-			_lm_socket_failed_with_error (connect_data, err);
-
-			socket->watch_connect = NULL;
-			return FALSE;
+			/* error condition, but might be possible to recover
+			 * from it (by connecting to the next host) */
+			if (!_lm_socket_failed_with_error (connect_data, err)) {
+				socket->watch_connect = NULL;
+				return FALSE;
+			}
 		}
 	}