loudmouth/src/lm-sasl.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
--- a/loudmouth/src/lm-sasl.c	Tue Feb 02 01:10:06 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,876 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <glib.h>
-
-//hack - to get over compilation error
-#include <glib_global.h>
-#include "lm-sock.h"
-#include "lm-debug.h"
-#include "lm-error.h"
-#include "lm-internals.h"
-#include "lm-message-queue.h"
-#include "lm-misc.h"
-#include "lm-ssl-internals.h"
-#include "lm-parser.h"
-#include "lm-sha.h"
-#include "lm-connection.h"
-#include "lm-utils.h"
-#include "lm-socket.h"
-#include "lm-sasl.h"
-
-#include "md5.h"
-#include "base64.h"
-
-typedef enum {
-	AUTH_TYPE_PLAIN  = 1,
-	AUTH_TYPE_DIGEST = 2
-} AuthType;
-
-typedef enum {
-	SASL_AUTH_STATE_NO_MECH,
-	SASL_AUTH_STATE_PLAIN_STARTED,
-	SASL_AUTH_STATE_DIGEST_MD5_STARTED,
-	SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE,
-	SASL_AUTH_STATE_DIGEST_MD5_SENT_FINAL_RESPONSE,
-} SaslAuthState;
-
-struct _LmSASL {
-	LmConnection        *connection;
-	AuthType             auth_type;
-	SaslAuthState        state;
-	gchar               *username;
-	gchar               *password;
-	gchar               *server;
-	gchar               *digest_md5_rspauth;
-	LmMessageHandler    *features_cb;
-	LmMessageHandler    *challenge_cb;
-	LmMessageHandler    *success_cb;
-	LmMessageHandler    *failure_cb;
-
-	gboolean             features_received;
-	gboolean             start_auth;
-
-	LmSASLResultHandler  handler;
-};
-
-#define XMPP_NS_SASL_AUTH "urn:ietf:params:xml:ns:xmpp-sasl"
-
-static LmHandlerResult     sasl_features_cb  (LmMessageHandler *handler,
-					      LmConnection     *connection,
-					      LmMessage        *message,
-					      gpointer          user_data);
-
-static LmHandlerResult     sasl_challenge_cb (LmMessageHandler *handler,
-					      LmConnection     *connection,
-					      LmMessage        *message,
-					      gpointer          user_data);
-
-static LmHandlerResult     sasl_success_cb   (LmMessageHandler *handler,
-					      LmConnection     *connection,
-					      LmMessage        *message,
-					      gpointer          user_data);
-
-static LmHandlerResult     sasl_failure_cb   (LmMessageHandler *handler,
-					      LmConnection     *connection,
-					      LmMessage        *message,
-					      gpointer          user_data);
-
-
-/* DIGEST-MD5 mechanism code from libgibber */
-
-static gchar *
-sasl_strndup_unescaped (const gchar *str, gsize len) 
-{
-	const gchar *s;
-	gchar       *d;
-	gchar       *ret;
-
-	ret = g_malloc0 (len + 1);
-	for (s = str, d = ret ; s < (str + len) ; s++, d++) {
-		if (*s == '\\') s++;
-		*d = *s;
-	}
-
-	return ret;
-}
-
-static GHashTable *
-sasl_digest_md5_challenge_to_hash (const gchar * challenge)
-{
-	const gchar *keystart, *keyend, *valstart;
-	const gchar *c = challenge;
-	gchar       *key, *val;
-	GHashTable  *result;
-	
-	result = g_hash_table_new_full (g_str_hash, g_str_equal, 
-					g_free, g_free);
-
-	do { 
-		while (g_ascii_isspace(*c)) c++;
-
-		keystart = c;
-		for (; *c != '\0' && *c != '='; c++);
-
-		if (*c == '\0' || c == keystart) goto error;
-
-		keyend = c; 
-		c++;
-
-		if (*c == '"') {
-			c++;
-			valstart = c;
-			for (; *c != '\0' && *c != '"'; c++);
-			if (*c == '\0' || c == valstart) goto error;
-			val = sasl_strndup_unescaped (valstart, c - valstart);
-			c++;
-		} else {
-			valstart = c;
-			for (; *c !=  '\0' && *c != ','; c++);
-			if (c == valstart) goto error;
-			val = g_strndup (valstart, c - valstart);
-		}
-
-		key = g_strndup (keystart, keyend - keystart);
-
-		g_hash_table_insert (result, key, val);
-
-		if (*c == ',') c++;
-	} while (*c != '\0');
-
-	return result;
-error:
-	/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL, 
-	       "Failed to parse challenge: %s", challenge);*/
-	lm_verbose("[sasl_digest_md5_challenge_to_hash]:Failed to parse challenge: %s", challenge);
-	g_hash_table_destroy (result);
-	return NULL;
-}
-
-static gchar *
-sasl_md5_hex_hash (gchar *value, gsize len) 
-{
-	md5_byte_t   digest_md5[16];
-	md5_state_t  md5_calc;
-	GString     *str;
-	int          i;
-
-	str = g_string_sized_new (32);
-
-	md5_init (&md5_calc);
-	md5_append (&md5_calc, (const md5_byte_t *)value, len);
-	md5_finish (&md5_calc, digest_md5);
-
-	for (i = 0 ; i < 16 ; i++) {
-		g_string_append_printf (str, "%02x", digest_md5[i]);
-	}
-
-	return g_string_free (str, FALSE);
-}
-
-static gchar *
-sasl_digest_md5_generate_cnonce(void)
-{
-	/* RFC 2831 recommends the the nonce to be either hexadecimal or base64 with
-	 * at least 64 bits of entropy */
-#define NR 8
-	guint32 n[NR]; 
-	int i;
-
-	for (i = 0; i < NR; i++) {
-		n[i] = g_random_int();
-	}
-
-	return base64_encode ((gchar *)n, sizeof(n));
-}
-
-static gchar *
-sasl_md5_prepare_response (LmSASL *sasl, GHashTable *challenge)
-{
-	GString     *response;
-	const gchar *realm, *nonce;
-	gchar       *a1, *a1h, *a2, *a2h, *kd, *kdh;
-	gchar       *cnonce = NULL;
-	gchar       *tmp;
-	md5_byte_t   digest_md5[16];
-	md5_state_t  md5_calc;
-	gsize        len;
-
-	response = g_string_new ("");
-
-	if (sasl->username == NULL || sasl->password == NULL) {
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-		       "%s: no username or password provided", G_STRFUNC);*/
-		lm_verbose("[sasl_md5_prepare_response]: %s: no username or password provided", G_STRFUNC);
-		if (sasl->handler) {
-			sasl->handler (sasl, sasl->connection, 
-				       FALSE, "no username/password provided");
-		}
-		goto error;
-	}
-
-	nonce = g_hash_table_lookup (challenge, "nonce");
-	if (nonce == NULL || nonce == '\0') {
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-		       "%s: server didn't provide a nonce in the challenge", 
-		       G_STRFUNC);*/
-		lm_verbose("[sasl_md5_prepare_response]: %s: server didn't provide a nonce in the challenge", G_STRFUNC);
-		if (sasl->handler) {
-			sasl->handler (sasl, sasl->connection,
-				       FALSE, "server error");
-		}
-		goto error;
-	}
-
-	cnonce = sasl_digest_md5_generate_cnonce ();
-
-	/* FIXME challenge can contain multiple realms */
-	realm = g_hash_table_lookup (challenge, "realm");
-	if (realm == NULL) {
-		realm = sasl->server;
-	}
-
-	/* FIXME properly escape values */
-	g_string_append_printf (response, "username=\"%s\"", sasl->username);
-	g_string_append_printf (response, ",realm=\"%s\"", realm);
-	g_string_append_printf (response, ",digest-uri=\"xmpp/%s\"", realm);
-	g_string_append_printf (response, ",nonce=\"%s\",nc=00000001", nonce);
-	g_string_append_printf (response, ",cnonce=\"%s\"", cnonce);
-	/* FIXME should check if auth is in the cop challenge val */
-	g_string_append_printf (response, ",qop=auth,charset=utf-8");
-
-	tmp = g_strdup_printf ("%s:%s:%s", 
-			       sasl->username, realm, sasl->password);
-	md5_init (&md5_calc);
-	md5_append (&md5_calc, (const md5_byte_t *)tmp, strlen(tmp));
-	md5_finish (&md5_calc, digest_md5);
-	g_free (tmp);
-
-	a1 = g_strdup_printf ("0123456789012345:%s:%s", nonce, cnonce);
-	len = strlen (a1);
-	memcpy (a1, digest_md5, 16);
-	a1h = sasl_md5_hex_hash (a1, len);
-
-	a2 = g_strdup_printf ("AUTHENTICATE:xmpp/%s", realm);
-	a2h = sasl_md5_hex_hash (a2, strlen(a2));
-
-	kd = g_strdup_printf ("%s:%s:00000001:%s:auth:%s",
-			      a1h, nonce, cnonce, a2h);
-	kdh = sasl_md5_hex_hash (kd, strlen(kd));
-	g_string_append_printf (response, ",response=%s", kdh);
-
-	g_free (kd);
-	g_free (kdh);
-	g_free (a2);
-	g_free (a2h);
-
-	/* Calculate the response we expect from the server */
-	a2 = g_strdup_printf (":xmpp/%s", realm);
-	a2h = sasl_md5_hex_hash (a2, strlen(a2));
-
-	kd = g_strdup_printf ("%s:%s:00000001:%s:auth:%s", a1h, nonce, cnonce, a2h);
-	g_free (sasl->digest_md5_rspauth);
-	sasl->digest_md5_rspauth = sasl_md5_hex_hash (kd, strlen(kd));
-
-	g_free (a1);
-	g_free (a1h);
-	g_free (a2);
-	g_free (a2h);
-	g_free (kd);
-
-out:
-	g_free (cnonce);
-	if (response) {
-		return g_string_free (response, FALSE);
-	} else {
-		return NULL;
-	}
-
-error:
-	g_string_free (response, TRUE);
-	response = NULL;
-	goto out;
-}
-
-static gboolean
-sasl_digest_md5_send_initial_response (LmSASL *sasl, GHashTable *challenge)
-{
-	LmMessage *msg;
-	gchar     *response;
-	gchar     *response64;
-	int        result;
-
-	response = sasl_md5_prepare_response(sasl, challenge);
-	if (response == NULL) {
-		return FALSE;
-	}
-
-	response64 = base64_encode ((gchar *)response, strlen(response));
-
-	msg = lm_message_new (NULL, LM_MESSAGE_TYPE_RESPONSE);
-	lm_message_node_set_attributes (msg->node,
-					"xmlns", XMPP_NS_SASL_AUTH,
-					NULL);
-	lm_message_node_set_value (msg->node, response64);
-
-	result = lm_connection_send (sasl->connection, msg, NULL);
-
-	g_free (response);
-	g_free (response64);
-	lm_message_unref (msg);
-
-	if (!result) {
-		return FALSE;
-	}
-
-	sasl->state = SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE;
-
-	return TRUE;
-}
-
-static gboolean
-sasl_digest_md5_check_server_response(LmSASL *sasl, GHashTable *challenge)
-{
-	LmMessage   *msg;
-	const gchar *rspauth;
-	int          result;
-
-	rspauth = g_hash_table_lookup (challenge, "rspauth");
-	if (rspauth == NULL) {
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
-		       "%s: server sent an invalid reply (no rspauth)\n",
-		       G_STRFUNC);*/
-		lm_verbose("%s: server sent an invalid reply (no rspauth)\n",G_STRFUNC);
-
-		if (sasl->handler) {
-			sasl->handler (sasl, sasl->connection, 
-				       TRUE, "server error");
-		}
-		return FALSE;
-	}
-
-	if (strcmp (sasl->digest_md5_rspauth, rspauth) != 0) {
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
-		       "%s: server sent an invalid reply (rspauth not matching)\n", 
-		       G_STRFUNC);*/
-		lm_verbose("%s: server sent an invalid reply (rspauth not matching)\n", 
-		       G_STRFUNC);
-
-		if (sasl->handler) {
-			sasl->handler (sasl, sasl->connection,
-				       TRUE, "server error");
-		}
-		return FALSE;
-	}
-
-	msg = lm_message_new (NULL, LM_MESSAGE_TYPE_RESPONSE);
-	lm_message_node_set_attributes (msg->node,
-					"xmlns", XMPP_NS_SASL_AUTH,
-					NULL);
-
-	result = lm_connection_send (sasl->connection, msg, NULL);
-	lm_message_unref (msg);
-
-	if (!result) {
-		g_warning ("Failed to send SASL response\n");
-		return FALSE;
-	}
-
-	sasl->state = SASL_AUTH_STATE_DIGEST_MD5_SENT_FINAL_RESPONSE;
-
-	return TRUE;
-}
-
-static gboolean
-sasl_digest_md5_handle_challenge (LmSASL *sasl, LmMessageNode *node)
-{
-	const gchar *encoded;
-	gchar       *challenge;
-	gsize        len;
-	GHashTable  *h;
-
-	encoded = lm_message_node_get_value (node);
-	if (!encoded) {
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-		       "%s: got empty challenge!", G_STRFUNC);*/
-		lm_verbose("[sasl_digest_md5_handle_challenge]: %s: got empty challenge!", G_STRFUNC);
-		return FALSE;
-	}
-
-	challenge = (gchar *) base64_decode (encoded, &len);
-	h = sasl_digest_md5_challenge_to_hash (challenge);
-	g_free(challenge);
-
-	if (!h) {
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-		       "%s: server sent an invalid challenge", G_STRFUNC);*/
-		lm_verbose("[sasl_digest_md5_handle_challenge]: %s: server sent an invalid challenge", G_STRFUNC);
-		if (sasl->handler) {
-			sasl->handler (sasl, sasl->connection, 
-				       FALSE, "server error");
-		}
-		return FALSE;
-	}
-
-	switch (sasl->state) {
-	case SASL_AUTH_STATE_DIGEST_MD5_STARTED:
-		sasl_digest_md5_send_initial_response (sasl, h); 
-		break;
-	case SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE:
-		sasl_digest_md5_check_server_response (sasl, h); 
-		break;
-	default:
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-		       "%s: server sent a challenge at the wrong time", 
-		       G_STRFUNC);*/
-		lm_verbose( "[sasl_digst_md5_handle_challenge]: %s: server sent a challenge at the wrong time", 
-		       G_STRFUNC);
-		if (sasl->handler) {
-			sasl->handler (sasl, sasl->connection,
-				       FALSE, "server error");
-		}
-
-		return FALSE;
-	} 
-
-	g_hash_table_destroy(h);
-
-	return TRUE;
-}
-
-static LmHandlerResult
-sasl_challenge_cb (LmMessageHandler *handler,
-		   LmConnection     *connection,
-		   LmMessage        *message,
-		   gpointer          user_data)
-{
-	LmSASL      *sasl;
-	const gchar *ns;
-
-	ns = lm_message_node_get_attribute (message->node, "xmlns");
-	if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
-		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-	}
-
-	sasl = (LmSASL *) user_data;
-
-	switch (sasl->auth_type) {
-	case AUTH_TYPE_PLAIN:
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
-		       "%s: server sent challenge for PLAIN mechanism",
-		       G_STRFUNC);*/
-		lm_verbose("[sasl_challenge_cb]: %s: server sent challenge for PLAIN mechanism",G_STRFUNC);
-
-		if (sasl->handler) {
-			sasl->handler (sasl, sasl->connection, 
-				       FALSE, "server error");
-		}
-		break;
-	case AUTH_TYPE_DIGEST:
-		sasl_digest_md5_handle_challenge (sasl, message->node);
-		break;
-	default:
-		g_warning ("Wrong auth type");
-		break;
-	}
-	UNUSED_FORMAL_PARAM(handler);
-	UNUSED_FORMAL_PARAM(connection);
-	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static LmHandlerResult
-sasl_success_cb (LmMessageHandler *handler,
-		 LmConnection     *connection,
-		 LmMessage        *message,
-		 gpointer          user_data)
-{
-	LmSASL      *sasl;
-	const gchar *ns;
-	
-	ns = lm_message_node_get_attribute (message->node, "xmlns");
-	if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
-		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-	}
-
-	sasl = (LmSASL *) user_data;
-
-	switch (sasl->auth_type) {
-	case AUTH_TYPE_PLAIN:
-		if (sasl->state != SASL_AUTH_STATE_PLAIN_STARTED) {
-			/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-			       "%s: server sent success before finishing auth", 
-			       G_STRFUNC);*/
-			lm_verbose("[sasl_success_cb]: %s: server sent success before finishing auth", G_STRFUNC);
-			if (sasl->handler) {
-				sasl->handler (sasl, sasl->connection, 
-					       FALSE, "server error");
-			}
-		}
-		break;
-	case AUTH_TYPE_DIGEST:
-		if (sasl->state != SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE &&
-		    sasl->state != SASL_AUTH_STATE_DIGEST_MD5_SENT_FINAL_RESPONSE) {
-			/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-			       "%s: server sent success before finishing auth", 
-			       G_STRFUNC);*/
-			lm_verbose("[sasl_success_cb]: %s: server sent success before finishing auth", G_STRFUNC);
-			if (sasl->handler) {
-				sasl->handler (sasl, sasl->connection, 
-					       FALSE, "server error");
-			}
-		}
-		break;
-	default:
-		g_warning ("Wrong auth type");
-		break;
-	}
-
-/*	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-	       "%s: SASL authentication successful", G_STRFUNC);*/
-	lm_verbose("[sasl_success_cb]: %s: SASL authentication successful", G_STRFUNC);
-
-	if (sasl->handler) {
-		sasl->handler (sasl, sasl->connection, TRUE, NULL);
-	}
-	UNUSED_FORMAL_PARAM(handler);
-	UNUSED_FORMAL_PARAM(connection);
-	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-	
-}
-
-static LmHandlerResult
-sasl_failure_cb (LmMessageHandler *handler,
-		 LmConnection     *connection,
-		 LmMessage        *message,
-		 gpointer          user_data)
-{
-	LmSASL      *sasl;
-	const gchar *ns;
-	const gchar *reason = "unknown reason";
-	lm_verbose("[sasl_failure_cb]: inside sasl_failure_cb\n");
-	ns = lm_message_node_get_attribute (message->node, "xmlns");
-	if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
-		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-	}
-
-	sasl = (LmSASL *) user_data;
-
-	if (message->node->children) {
-		const gchar *r;
-		
-		r = lm_message_node_get_value (message->node->children);
-		if (r) {
-			reason = r;
-		}
-	}
-	lm_verbose("[sasl_failure_cb]: %s: SASL authentication failed: %s\n", G_STRFUNC, reason);
-	/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-	       "%s: SASL authentication failed: %s", G_STRFUNC, reason);*/
-
-	if (sasl->handler) {
-		sasl->handler (sasl, sasl->connection, FALSE, reason);
-	}
-	UNUSED_FORMAL_PARAM(handler);
-	UNUSED_FORMAL_PARAM(connection);
-	return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-
-static gboolean
-sasl_start (LmSASL *sasl)
-{
-	LmMessage  *auth_msg;
-	gboolean    result;
-	const char *mech = NULL;
-
-	auth_msg = lm_message_new (NULL, LM_MESSAGE_TYPE_AUTH);
-	lm_verbose("[sasl_start]: inside sasl_start\n");
-	if (sasl->auth_type == AUTH_TYPE_PLAIN) {
-      		GString *str;
-		gchar   *cstr;
-
-		str = g_string_new ("");
-
-		mech = "PLAIN";
-		sasl->state = SASL_AUTH_STATE_PLAIN_STARTED;
-		lm_verbose("[sasl_start]: inside sasl_start: auth type is PLAIN\n");
-		if (sasl->username == NULL || sasl->password == NULL) {
-			lm_verbose("[sasl_start]: no username or password provided\n");
-			/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-			       "%s: no username or password provided", 
-			       G_STRFUNC);*/
-			if (sasl->handler) {
-				sasl->handler (sasl, sasl->connection, FALSE, "no username/password provided");
-			}
-
-			return FALSE;
-		}
-
-		g_string_append_c (str, '\0');
-		g_string_append (str, sasl->username);
-		g_string_append_c (str, '\0');
-		g_string_append (str, sasl->password);
-		cstr = base64_encode ((gchar *)str->str, str->len);
-
-		lm_message_node_set_value (auth_msg->node, cstr);
-
-		g_string_free (str, TRUE);
-		g_free (cstr);
-
-		/* Here we say the Google magic word. Bad Google. */
-		lm_message_node_set_attributes (auth_msg->node,
-						"xmlns:ga", "http://www.google.com/talk/protocol/auth",
-						"ga:client-uses-full-bind-result", "true",
-						NULL);
-
-	} 
-	else if (sasl->auth_type == AUTH_TYPE_DIGEST) {
-		mech = "DIGEST-MD5";
-		sasl->state = SASL_AUTH_STATE_DIGEST_MD5_STARTED;
-	}
-
-	lm_message_node_set_attributes (auth_msg->node,
-					"xmlns", XMPP_NS_SASL_AUTH,
-					"mechanism", mech,
-					NULL);
-
-	result = lm_connection_send (sasl->connection, auth_msg, NULL);
-	lm_message_unref (auth_msg);
-
-	if (!result) {
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static gboolean
-sasl_set_auth_type (LmSASL *sasl, LmMessageNode *mechanisms)
-{
-	LmMessageNode *m;
-	const gchar   *ns;
-
-	sasl->auth_type = 0;
-	lm_verbose("[sasl_set_auth_type]: inside sasl_set_auth_type\n");
-	ns = lm_message_node_get_attribute (mechanisms, "xmlns");
-	if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
-		return FALSE;
-	}
-
-	for (m = mechanisms->children; m; m = m->next) {
-		const gchar *name;
-		
-		name = lm_message_node_get_value (m);
-
-		if (!name) {
-			continue;
-		}
-		if (strcmp (name, "PLAIN") == 0) {
-			sasl->auth_type |= AUTH_TYPE_PLAIN;
-			continue;
-		}
-		if (strcmp (name, "DIGEST-MD5") == 0) {
-			sasl->auth_type |= AUTH_TYPE_DIGEST;
-			continue;
-		}
-
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-		       "%s: unknown SASL auth mechanism: %s", G_STRFUNC, name);*/
-		lm_verbose ("[sasl_set_auth_type]: %s: unknown SASL auth mechanism: %s", G_STRFUNC, name);
-	}
-
-	return TRUE;
-}
-
-static gboolean
-sasl_authenticate (LmSASL *sasl)
-{
-	lm_verbose ("[sasl_authenticate]: inside sasl_authenticate\n");
-	if (sasl->auth_type == 0) {
-		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL,
-		      "%s: no supported SASL auth mechanisms found",
-		      G_STRFUNC);*/
-	  lm_verbose ("[sasl_authenticate]: %s: no supported SASL auth mechanisms found",G_STRFUNC);
-
-		return FALSE;
-	}
-
-	/* Prefer DIGEST */
-	if (sasl->auth_type & AUTH_TYPE_DIGEST) {
-		sasl->auth_type = AUTH_TYPE_DIGEST;
-		return sasl_start (sasl);
-	}
-	else if (sasl->auth_type & AUTH_TYPE_PLAIN) {
-		sasl->auth_type = AUTH_TYPE_PLAIN;
-		return sasl_start (sasl);
-	} 
-
-	return FALSE;
-}
-
-static LmHandlerResult
-sasl_features_cb (LmMessageHandler *handler,
-		  LmConnection     *connection,
-		  LmMessage        *message,
-		  gpointer          user_data)
-{
-    	LmMessageNode *mechanisms;
-	LmSASL        *sasl;
-
-	lm_verbose ("\n[sasl_feature_cb]: Stream features received\n\n");
-	//g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SASL, "Stream features received\n");
-	mechanisms = lm_message_node_find_child (message->node, "mechanisms");
-	if (!mechanisms) {
-	    gchar* childname = NULL;
-		lm_message_node_get_child(message->node,childname);
-		lm_verbose("[sasl_feature_cb]: Child name of stream:features %s\n", message->node->children->name);
-		lm_verbose("[sasl_feature_cb]: Child pointer of stream:features %u\n", message->node->children);
-		lm_verbose ("[sasl_feature_cb]: mechanisms empty:LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS \n");
-		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-	}
-	lm_verbose("[sasl_features_cb]: Mechanisms not null\n");
-
-	sasl = (LmSASL *) user_data;
-	sasl->features_received = TRUE;
-
-	sasl_set_auth_type (sasl, mechanisms);
-
-	if (sasl->start_auth) {
-		lm_verbose ("[sasl_feature_cb]: Going to call sasl_authenticate\n");
-		sasl_authenticate (sasl);
-	}
-	UNUSED_FORMAL_PARAM(handler);
-	UNUSED_FORMAL_PARAM(connection);
-	return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
-
-LmSASL *
-lm_sasl_new (LmConnection *connection)
-{
-	LmSASL *sasl;
-	
-	sasl = g_new0 (LmSASL, 1);
-
-	sasl->connection = connection;
-	sasl->features_received = FALSE;
-	sasl->start_auth = FALSE;
-
-	sasl->features_cb = lm_message_handler_new (sasl_features_cb,
-						    sasl,
-						    NULL);
-	lm_verbose ("[lm_sasl_new]: inside \n");
-	lm_connection_register_message_handler (connection,
-						sasl->features_cb,
-						LM_MESSAGE_TYPE_STREAM_FEATURES,
-						LM_HANDLER_PRIORITY_LAST);
-	return sasl;
-}
-
-void
-lm_sasl_authenticate (LmSASL              *sasl,
-		      const gchar         *username,
-		      const gchar         *password,
-		      const gchar         *server,
-		      LmSASLResultHandler  handler)
-{
-	sasl->username   = g_strdup (username);
-	sasl->password   = g_strdup (password);
-	sasl->server     = g_strdup (server);
-	sasl->handler    = handler;
-
-	sasl->challenge_cb = lm_message_handler_new (sasl_challenge_cb,
-						     sasl,
-						     NULL);
-	lm_connection_register_message_handler (sasl->connection,
-						sasl->challenge_cb,
-						LM_MESSAGE_TYPE_CHALLENGE,
-						LM_HANDLER_PRIORITY_FIRST);
-	
-	sasl->success_cb = lm_message_handler_new (sasl_success_cb,
-						   sasl,
-						   NULL);
-	lm_connection_register_message_handler (sasl->connection,
-						sasl->success_cb,
-						LM_MESSAGE_TYPE_SUCCESS,
-						LM_HANDLER_PRIORITY_FIRST);
-
-	sasl->failure_cb = lm_message_handler_new (sasl_failure_cb,
-						   sasl,
-						   NULL);
-	lm_connection_register_message_handler (sasl->connection,
-						sasl->failure_cb,
-						LM_MESSAGE_TYPE_FAILURE,
-						LM_HANDLER_PRIORITY_FIRST);
-
-	if (sasl->features_received) {
-		lm_verbose("[lm_sasl_authenticate]: calling sasl_authenticate\n");
-		sasl_authenticate (sasl);
-	} else {
-		sasl->start_auth = TRUE;
-	}
-}
-
-void
-lm_sasl_free (LmSASL *sasl)
-{
-	g_return_if_fail (sasl != NULL);
-
-	g_free (sasl->username);
-	g_free (sasl->password);
-	g_free (sasl->server);
-
-	if (sasl->features_cb) {
-		lm_connection_unregister_message_handler (sasl->connection,
-							  sasl->features_cb, 
-							  LM_MESSAGE_TYPE_STREAM_FEATURES);
-	}
-
-	if (sasl->challenge_cb) {
-		lm_connection_unregister_message_handler (sasl->connection,
-							  sasl->challenge_cb,
-							  LM_MESSAGE_TYPE_CHALLENGE);
-	}
-
-	if (sasl->success_cb) {
-		lm_connection_unregister_message_handler (sasl->connection,
-							  sasl->success_cb,
-							  LM_MESSAGE_TYPE_SUCCESS);
-	}
-
-	if (sasl->failure_cb) {
-		lm_connection_unregister_message_handler (sasl->connection,
-							  sasl->failure_cb,
-							  LM_MESSAGE_TYPE_FAILURE);
-	}
-
-	g_free (sasl);
-}
-
-
-void
-lm_sasl_get_auth_params (LmSASL *sasl, const gchar **username,
-	const gchar **password)
-{
-	*username = sasl->username;
-	*password = sasl->password;
-}
-