--- a/loudmouth/lm-sasl.c Sat Feb 24 02:23:46 2007 +0100
+++ b/loudmouth/lm-sasl.c Sat Feb 24 02:50:25 2007 +0100
@@ -45,137 +45,62 @@
} AuthType;
typedef enum {
- SASL_AUTH_STATE_NO_MECH = 0,
- 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,
+ 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;
+ 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;
- LmSASLResultHandler handler;
+ LmSASLResultHandler handler;
};
#define XMPP_NS_SASL_AUTH "urn:ietf:params:xml:ns:xmpp-sasl"
-static LmHandlerResult
-features_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data);
-
-static LmHandlerResult
-challenge_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data);
-
-static LmHandlerResult
-success_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data);
-
-static LmHandlerResult
-failure_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data);
+static LmHandlerResult sasl_features_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data);
-LmSASL *
-lm_sasl_new (LmConnection *connection,
- const gchar *username,
- const gchar *password,
- const gchar *server,
- LmSASLResultHandler handler)
-{
- LmSASL *sasl = g_new0 (LmSASL, 1);
-
- sasl->connection = connection;
- sasl->username = g_strdup (username);
- sasl->password = g_strdup (password);
- sasl->server = g_strdup (server);
- sasl->handler = handler;
-
- sasl->features_cb =
- lm_message_handler_new (features_cb,
- sasl,
- NULL);
- lm_connection_register_message_handler (connection,
- sasl->features_cb,
- LM_MESSAGE_TYPE_STREAM_FEATURES,
- LM_HANDLER_PRIORITY_FIRST);
+static LmHandlerResult sasl_challenge_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data);
- sasl->challenge_cb =
- lm_message_handler_new (challenge_cb,
- sasl,
- NULL);
- lm_connection_register_message_handler (connection,
- sasl->challenge_cb,
- LM_MESSAGE_TYPE_CHALLENGE,
- LM_HANDLER_PRIORITY_FIRST);
- sasl->success_cb =
- lm_message_handler_new (success_cb,
- sasl,
- NULL);
- lm_connection_register_message_handler (connection,
- sasl->success_cb,
- LM_MESSAGE_TYPE_SUCCESS,
- LM_HANDLER_PRIORITY_FIRST);
+static LmHandlerResult sasl_success_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data);
- sasl->failure_cb =
- lm_message_handler_new (failure_cb,
- sasl,
- NULL);
- lm_connection_register_message_handler (connection,
- sasl->failure_cb,
- LM_MESSAGE_TYPE_FAILURE,
- LM_HANDLER_PRIORITY_FIRST);
- return sasl;
-}
-
-void
-lm_sasl_free (LmSASL *sasl)
-{
- g_return_if_fail (sasl != NULL);
+static LmHandlerResult sasl_failure_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data);
- if (sasl->username)
- g_free (sasl->username);
- if (sasl->password)
- g_free (sasl->password);
- if (sasl->server)
- 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);
-
- g_free (sasl);
-}
/* DIGEST-MD5 mechanism code from libgibber */
static gchar *
-strndup_unescaped(const gchar *str, gsize len) {
+sasl_strndup_unescaped (const gchar *str, gsize len)
+{
const gchar *s;
- gchar *d, *ret;
+ gchar *d;
+ gchar *ret;
- ret = g_malloc0(len + 1);
+ ret = g_malloc0 (len + 1);
for (s = str, d = ret ; s < (str + len) ; s++, d++) {
if (*s == '\\') s++;
*d = *s;
@@ -185,12 +110,15 @@
}
static GHashTable *
-digest_md5_challenge_to_hash(const gchar * challenge) {
+sasl_digest_md5_challenge_to_hash (const gchar * challenge)
+{
const gchar *keystart, *keyend, *valstart;
const gchar *c = challenge;
- gchar *key, *val;
- GHashTable *result = g_hash_table_new_full(g_str_hash,
- g_str_equal, g_free, g_free);
+ gchar *key, *val;
+ GHashTable *result;
+
+ result = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
do {
keystart = c;
@@ -206,18 +134,18 @@
valstart = c;
for (; *c != '\0' && *c != '"'; c++);
if (*c == '\0' || c == valstart) goto error;
- val = strndup_unescaped(valstart, c - valstart);
+ 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);
+ val = g_strndup (valstart, c - valstart);
}
- key = g_strndup(keystart, keyend - keystart);
+ key = g_strndup (keystart, keyend - keystart);
- g_hash_table_insert(result, key, val);
+ g_hash_table_insert (result, key, val);
if (*c == ',') c++;
} while (*c != '\0');
@@ -225,53 +153,66 @@
return result;
error:
g_debug ("Failed to parse challenge: %s", challenge);
- g_hash_table_destroy(result);
+ g_hash_table_destroy (result);
return NULL;
}
static gchar *
-md5_hex_hash(gchar *value, gsize len) {
- md5_byte_t digest_md5[16];
- md5_state_t md5_calc;
- GString *str = g_string_sized_new(32);
- int i;
+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);
+ 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]);
+ g_string_append_printf (str, "%02x", digest_md5[i]);
}
- return g_string_free(str, FALSE);
+
+ return g_string_free (str, FALSE);
}
static gchar *
-digest_md5_generate_cnonce(void) {
+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++)
+
+ for (i = 0; i < NR; i++) {
n[i] = g_random_int();
- return base64_encode((gchar *)n, sizeof(n));
+ }
+
+ return base64_encode ((gchar *)n, sizeof(n));
}
static gchar *
-md5_prepare_response(LmSASL *sasl, GHashTable *challenge) {
- GString *response = g_string_new("");
+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;
+ 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_debug ("%s: no username or password provided", G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, FALSE, "no username/password provided");
+ sasl->handler (sasl, sasl->connection,
+ FALSE, "no username/password provided");
}
goto error;
}
@@ -280,12 +221,13 @@
if (nonce == NULL || nonce == '\0') {
g_debug ("%s: server didn't provide a nonce in the challenge", G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, FALSE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ FALSE, "server error");
}
goto error;
}
- cnonce = digest_md5_generate_cnonce();
+ cnonce = sasl_digest_md5_generate_cnonce ();
/* FIXME challenge can contain multiple realms */
realm = g_hash_table_lookup (challenge, "realm");
@@ -294,74 +236,81 @@
}
/* 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);
+ 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");
+ 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);
+ 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 = md5_hex_hash(a1, len);
+ 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 = md5_hex_hash(a2, strlen(a2));
+ 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 = md5_hex_hash(kd, strlen(kd));
- g_string_append_printf(response, ",response=%s", kdh);
+ 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);
+ 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 = md5_hex_hash(a2, strlen(a2));
+ 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);
+ kd = g_strdup_printf ("%s:%s:00000001:%s:auth:%s", a1h, nonce, cnonce, a2h);
g_free (sasl->digest_md5_rspauth);
- sasl->digest_md5_rspauth = md5_hex_hash(kd, strlen(kd));
+ 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);
+ g_free (a1);
+ g_free (a1h);
+ g_free (a2);
+ g_free (a2h);
+ g_free (kd);
out:
- g_free(cnonce);
-
- return response != NULL ? g_string_free(response, FALSE) : NULL;
+ g_free (cnonce);
+ if (response) {
+ return g_string_free (response, FALSE);
+ } else {
+ return NULL;
+ }
error:
- g_string_free(response, TRUE);
+ g_string_free (response, TRUE);
response = NULL;
goto out;
}
static gboolean
-digest_md5_send_initial_response(LmSASL *sasl, GHashTable *challenge) {
+sasl_digest_md5_send_initial_response (LmSASL *sasl, GHashTable *challenge)
+{
LmMessage *msg;
- gchar *response, *response64;
- int result;
+ gchar *response;
+ gchar *response64;
+ int result;
- response = md5_prepare_response(sasl, challenge);
+ response = sasl_md5_prepare_response(sasl, challenge);
if (response == NULL) {
return FALSE;
}
- response64 = base64_encode((gchar *)response, strlen(response));
+ response64 = base64_encode ((gchar *)response, strlen(response));
msg = lm_message_new (NULL, LM_MESSAGE_TYPE_RESPONSE);
lm_message_node_set_attributes (msg->node,
@@ -371,12 +320,13 @@
result = lm_connection_send (sasl->connection, msg, NULL);
- g_free(response);
- g_free(response64);
+ g_free (response);
+ g_free (response64);
lm_message_unref (msg);
- if (!result)
+ if (!result) {
return FALSE;
+ }
sasl->state = SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE;
@@ -384,10 +334,11 @@
}
static gboolean
-digest_md5_check_server_response(LmSASL *sasl, GHashTable *challenge) {
- LmMessage *msg;
+sasl_digest_md5_check_server_response(LmSASL *sasl, GHashTable *challenge)
+{
+ LmMessage *msg;
const gchar *rspauth;
- int result;
+ int result;
rspauth = g_hash_table_lookup (challenge, "rspauth");
if (rspauth == NULL) {
@@ -396,18 +347,20 @@
G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, TRUE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ TRUE, "server error");
}
return FALSE;
}
- if (strcmp(sasl->digest_md5_rspauth, rspauth)) {
+ 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);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, TRUE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ TRUE, "server error");
}
return FALSE;
}
@@ -431,12 +384,12 @@
}
static gboolean
-digest_md5_handle_challenge (LmSASL *sasl, LmMessageNode *node)
+sasl_digest_md5_handle_challenge (LmSASL *sasl, LmMessageNode *node)
{
const gchar *encoded;
- gchar *challenge;
- gsize len;
- GHashTable *h;
+ gchar *challenge;
+ gsize len;
+ GHashTable *h;
encoded = lm_message_node_get_value (node);
if (!encoded) {
@@ -445,47 +398,53 @@
}
challenge = (gchar *) base64_decode (encoded, &len);
- h = digest_md5_challenge_to_hash (challenge);
+ h = sasl_digest_md5_challenge_to_hash (challenge);
g_free(challenge);
if (!h) {
g_debug ("%s: server sent an invalid challenge", G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, FALSE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ FALSE, "server error");
}
return FALSE;
}
switch (sasl->state) {
case SASL_AUTH_STATE_DIGEST_MD5_STARTED:
- digest_md5_send_initial_response(sasl, h);
+ sasl_digest_md5_send_initial_response (sasl, h);
break;
case SASL_AUTH_STATE_DIGEST_MD5_SENT_AUTH_RESPONSE:
- digest_md5_check_server_response(sasl, h);
+ sasl_digest_md5_check_server_response (sasl, h);
break;
default:
g_debug ("%s: server sent a challenge at the wrong time", G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, FALSE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ FALSE, "server error");
}
+
return FALSE;
}
+
g_hash_table_destroy(h);
+
return TRUE;
}
static LmHandlerResult
-challenge_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
+sasl_challenge_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data)
{
- LmSASL *sasl;
+ LmSASL *sasl;
const gchar *ns;
ns = lm_message_node_get_attribute (message->node, "xmlns");
- if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH))
+ if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+ }
sasl = (LmSASL *) user_data;
@@ -496,31 +455,34 @@
G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, FALSE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ FALSE, "server error");
}
break;
case AUTH_TYPE_DIGEST:
- digest_md5_handle_challenge (sasl, message->node);
+ sasl_digest_md5_handle_challenge (sasl, message->node);
break;
default:
- g_assert_not_reached ();
+ g_warning ("Wrong auth type");
+ break;
}
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}
static LmHandlerResult
-success_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
+sasl_success_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data)
{
- LmSASL *sasl;
+ LmSASL *sasl;
const gchar *ns;
ns = lm_message_node_get_attribute (message->node, "xmlns");
- if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH))
+ if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+ }
sasl = (LmSASL *) user_data;
@@ -529,7 +491,8 @@
if (sasl->state != SASL_AUTH_STATE_PLAIN_STARTED) {
g_debug ("%s: server sent success before finishing auth", G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, FALSE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ FALSE, "server error");
}
}
break;
@@ -538,15 +501,18 @@
sasl->state != SASL_AUTH_STATE_DIGEST_MD5_SENT_FINAL_RESPONSE) {
g_debug ("%s: server sent success before finishing auth", G_STRFUNC);
if (sasl->handler) {
- sasl->handler (sasl, sasl->connection, FALSE, "server error");
+ sasl->handler (sasl, sasl->connection,
+ FALSE, "server error");
}
}
break;
default:
- g_assert_not_reached ();
+ g_warning ("Wrong auth type");
+ break;
}
g_debug ("%s: SASL authentication successful", G_STRFUNC);
+
if (sasl->handler) {
sasl->handler (sasl, sasl->connection, TRUE, NULL);
}
@@ -556,26 +522,33 @@
}
static LmHandlerResult
-failure_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
+sasl_failure_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data)
{
- LmSASL *sasl;
+ LmSASL *sasl;
const gchar *ns;
const gchar *reason = "unknown reason";
ns = lm_message_node_get_attribute (message->node, "xmlns");
- if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH))
+ 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 = lm_message_node_get_value (message->node->children);
- if (r) reason = r;
+ const gchar *r;
+
+ r = lm_message_node_get_value (message->node->children);
+ if (r) {
+ reason = r;
+ }
}
+
g_debug ("%s: SASL authentication failed: %s", G_STRFUNC, reason);
+
if (sasl->handler) {
sasl->handler (sasl, sasl->connection, FALSE, reason);
}
@@ -585,17 +558,19 @@
static gboolean
-lm_sasl_start (LmSASL *sasl)
+sasl_start (LmSASL *sasl)
{
- LmMessage *auth_msg;
- gboolean result;
+ LmMessage *auth_msg;
+ gboolean result;
const char *mech = NULL;
auth_msg = lm_message_new (NULL, LM_MESSAGE_TYPE_AUTH);
if (sasl->auth_type == AUTH_TYPE_PLAIN) {
- GString *str = g_string_new("");
- gchar *cstr;
+ GString *str;
+ gchar *cstr;
+
+ str = g_string_new ("");
mech = "PLAIN";
sasl->state = SASL_AUTH_STATE_PLAIN_STARTED;
@@ -605,19 +580,20 @@
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);
+ 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);
+ 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,
@@ -625,7 +601,8 @@
"ga:client-uses-full-bind-result", "true",
NULL);
- } else if (sasl->auth_type == AUTH_TYPE_DIGEST) {
+ }
+ else if (sasl->auth_type == AUTH_TYPE_DIGEST) {
mech = "DIGEST-MD5";
sasl->state = SASL_AUTH_STATE_DIGEST_MD5_STARTED;
}
@@ -637,8 +614,10 @@
result = lm_connection_send (sasl->connection, auth_msg, NULL);
lm_message_unref (auth_msg);
- if (!result)
+
+ if (!result) {
return FALSE;
+ }
return TRUE;
}
@@ -647,22 +626,27 @@
lm_sasl_authenticate (LmSASL *sasl, LmMessageNode *mechanisms)
{
LmMessageNode *m;
- AuthType auth_type = 0;
- const gchar *ns;
+ AuthType auth_type = 0;
+ const gchar *ns;
ns = lm_message_node_get_attribute (mechanisms, "xmlns");
- if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH))
+ if (!ns || strcmp (ns, XMPP_NS_SASL_AUTH) != 0) {
return FALSE;
+ }
for (m = mechanisms->children; m; m = m->next) {
- const gchar *name = lm_message_node_get_value (m);
- if (!name)
+ const gchar *name;
+
+ name = lm_message_node_get_value (m);
+
+ if (!name) {
continue;
- if (!strcmp (name, "PLAIN")) {
+ }
+ if (strcmp (name, "PLAIN") == 0) {
auth_type |= AUTH_TYPE_PLAIN;
continue;
}
- if (!strcmp (name, "DIGEST-MD5")) {
+ if (strcmp (name, "DIGEST-MD5") == 0) {
auth_type |= AUTH_TYPE_DIGEST;
continue;
}
@@ -675,28 +659,29 @@
/* Prefer DIGEST */
if (auth_type & AUTH_TYPE_DIGEST) {
sasl->auth_type = AUTH_TYPE_DIGEST;
- return lm_sasl_start (sasl);
- } else if (auth_type & AUTH_TYPE_PLAIN) {
+ return sasl_start (sasl);
+ }
+ else if (auth_type & AUTH_TYPE_PLAIN) {
sasl->auth_type = AUTH_TYPE_PLAIN;
- return lm_sasl_start (sasl);
+ return sasl_start (sasl);
}
- g_assert_not_reached ();
return FALSE;
}
static LmHandlerResult
-features_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
+sasl_features_cb (LmMessageHandler *handler,
+ LmConnection *connection,
+ LmMessage *message,
+ gpointer user_data)
{
LmMessageNode *mechanisms;
- LmSASL *sasl;
+ LmSASL *sasl;
mechanisms = lm_message_node_find_child (message->node, "mechanisms");
- if (!mechanisms)
+ if (!mechanisms) {
return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+ }
sasl = (LmSASL *) user_data;
@@ -705,4 +690,89 @@
return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
}
+LmSASL *
+lm_sasl_new (LmConnection *connection,
+ const gchar *username,
+ const gchar *password,
+ const gchar *server,
+ LmSASLResultHandler handler)
+{
+ LmSASL *sasl = g_new0 (LmSASL, 1);
+ sasl->connection = connection;
+ sasl->username = g_strdup (username);
+ sasl->password = g_strdup (password);
+ sasl->server = g_strdup (server);
+ sasl->handler = handler;
+
+ sasl->features_cb = lm_message_handler_new (sasl_features_cb,
+ sasl,
+ NULL);
+ lm_connection_register_message_handler (connection,
+ sasl->features_cb,
+ LM_MESSAGE_TYPE_STREAM_FEATURES,
+ LM_HANDLER_PRIORITY_FIRST);
+
+ sasl->challenge_cb = lm_message_handler_new (sasl_challenge_cb,
+ sasl,
+ NULL);
+ lm_connection_register_message_handler (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 (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 (connection,
+ sasl->failure_cb,
+ LM_MESSAGE_TYPE_FAILURE,
+ LM_HANDLER_PRIORITY_FIRST);
+ return sasl;
+}
+
+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);
+}
+
+