diff -r d0f3a028347a -r 59927b2d3b75 loudmouth/src/lm-sasl.c --- 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 -#include -#include - -//hack - to get over compilation error -#include -#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; -} -