From 7cdef1e319ea887cfeedddd72338f78476ebae0b Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 3 Aug 2015 23:05:04 +0100 Subject: [PATCH] Check for name element when reading mechanisms Fixes an issue where the server sends whitespace between elements, a segfault would occur when performing a strcmp on the name. --- src/auth.c | 70 +++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/auth.c b/src/auth.c index b06f18c..b3056a2 100644 --- a/src/auth.c +++ b/src/auth.c @@ -1,7 +1,7 @@ /* auth.c ** strophe XMPP client library -- auth functions and handlers ** -** Copyright (C) 2005-2009 Collecta, Inc. +** Copyright (C) 2005-2009 Collecta, Inc. ** ** This software is provided AS-IS with no warranty, either express or ** implied. @@ -9,7 +9,7 @@ ** This program is dual licensed under the MIT and GPLv3 licenses. */ -/** @file +/** @file * Authentication function and handlers. */ @@ -116,7 +116,7 @@ static int _handle_error(xmpp_conn_t * const conn, /* free old stream error if it's still there */ if (conn->stream_error) { xmpp_stanza_release(conn->stream_error->stanza); - if (conn->stream_error->text) + if (conn->stream_error->text) xmpp_free(conn->ctx, conn->stream_error->text); xmpp_free(conn->ctx, conn->stream_error); } @@ -237,9 +237,9 @@ static int _handle_features(xmpp_conn_t * const conn, /* check for SASL */ child = xmpp_stanza_get_child_by_name(stanza, "mechanisms"); if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) { - for (mech = xmpp_stanza_get_children(child); mech; + for (mech = xmpp_stanza_get_children(child); mech; mech = xmpp_stanza_get_next(mech)) { - if (strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) { + if (xmpp_stanza_get_name(mech) && strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) { text = xmpp_stanza_get_text(mech); if (strcasecmp(text, "PLAIN") == 0) conn->sasl_support |= SASL_MASK_PLAIN; @@ -256,7 +256,7 @@ static int _handle_features(xmpp_conn_t * const conn, } _auth(conn); - + return 0; } @@ -281,7 +281,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn, { char *name; name = xmpp_stanza_get_name(stanza); - xmpp_debug(conn->ctx, "xmpp", + xmpp_debug(conn->ctx, "xmpp", "handle proceedtls called for %s", name); if (strcmp(name, "proceed") == 0) { @@ -295,7 +295,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn, tls_free(conn->tls); conn->tls = NULL; conn->tls_failed = 1; - + /* failed tls spoils the connection, so disconnect */ xmpp_disconnect(conn); } @@ -321,14 +321,14 @@ static int _handle_sasl_result(xmpp_conn_t * const conn, /* the server should send a or stanza */ if (strcmp(name, "failure") == 0) { - xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed", + xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed", (char *)userdata); - + /* fall back to next auth method */ _auth(conn); } else if (strcmp(name, "success") == 0) { /* SASL PLAIN auth successful, we need to restart the stream */ - xmpp_debug(conn->ctx, "xmpp", "SASL %s auth successful", + xmpp_debug(conn->ctx, "xmpp", "SASL %s auth successful", (char *)userdata); /* reset parser */ @@ -373,10 +373,10 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn, if (!auth) { disconnect_mem_error(conn); return 0; - } + } xmpp_stanza_set_name(auth, "response"); xmpp_stanza_set_ns(auth, XMPP_NS_SASL); - + authdata = xmpp_stanza_new(conn->ctx); if (!authdata) { disconnect_mem_error(conn); @@ -389,7 +389,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn, xmpp_stanza_add_child(auth, authdata); xmpp_stanza_release(authdata); - handler_add(conn, _handle_digestmd5_rspauth, + handler_add(conn, _handle_digestmd5_rspauth, XMPP_NS_SASL, NULL, NULL, NULL); xmpp_send(conn, auth); @@ -422,7 +422,7 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn, if (!auth) { disconnect_mem_error(conn); return 0; - } + } xmpp_stanza_set_name(auth, "response"); xmpp_stanza_set_ns(auth, XMPP_NS_SASL); xmpp_send(conn, auth); @@ -555,7 +555,7 @@ static xmpp_stanza_t *_make_starttls(xmpp_conn_t * const conn) xmpp_stanza_set_name(starttls, "starttls"); xmpp_stanza_set_ns(starttls, XMPP_NS_TLS); } - + return starttls; } @@ -571,14 +571,14 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t * const conn, xmpp_stanza_set_ns(auth, XMPP_NS_SASL); xmpp_stanza_set_attribute(auth, "mechanism", mechanism); } - + return auth; } -/* authenticate the connection - * this may get called multiple times. if any auth method fails, +/* authenticate the connection + * this may get called multiple times. if any auth method fails, * this will get called again until one auth method succeeds or every - * method fails + * method fails */ static void _auth(xmpp_conn_t * const conn) { @@ -619,7 +619,7 @@ static void _auth(xmpp_conn_t * const conn) return; } - handler_add(conn, _handle_proceedtls_default, + handler_add(conn, _handle_proceedtls_default, XMPP_NS_TLS, NULL, NULL, NULL); xmpp_send(conn, auth); @@ -644,7 +644,7 @@ static void _auth(xmpp_conn_t * const conn) /* SASL ANONYMOUS was tried, unset flag */ conn->sasl_support &= ~SASL_MASK_ANONYMOUS; } else if (anonjid) { - xmpp_error(conn->ctx, "auth", + xmpp_error(conn->ctx, "auth", "No node in JID, and SASL ANONYMOUS unsupported."); xmpp_disconnect(conn); } else if (conn->sasl_support & SASL_MASK_SCRAMSHA1) { @@ -700,7 +700,7 @@ static void _auth(xmpp_conn_t * const conn) } - handler_add(conn, _handle_digestmd5_challenge, + handler_add(conn, _handle_digestmd5_challenge, XMPP_NS_SASL, NULL, NULL, NULL); xmpp_send(conn, auth); @@ -718,7 +718,7 @@ static void _auth(xmpp_conn_t * const conn) if (!authdata) { disconnect_mem_error(conn); return; - } + } authid = _get_authid(conn); if (!authid) { disconnect_mem_error(conn); @@ -746,7 +746,7 @@ static void _auth(xmpp_conn_t * const conn) conn->sasl_support &= ~SASL_MASK_PLAIN; } else if (conn->type == XMPP_CLIENT) { /* legacy client authentication */ - + iq = xmpp_stanza_new(conn->ctx); if (!iq) { disconnect_mem_error(conn); @@ -832,7 +832,7 @@ static void _auth(xmpp_conn_t * const conn) } else { xmpp_stanza_release(authdata); xmpp_stanza_release(iq); - xmpp_error(conn->ctx, "auth", + xmpp_error(conn->ctx, "auth", "Cannot authenticate without resource"); xmpp_disconnect(conn); return; @@ -841,7 +841,7 @@ static void _auth(xmpp_conn_t * const conn) xmpp_stanza_release(authdata); handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL); - handler_add_timed(conn, _handle_missing_legacy, + handler_add_timed(conn, _handle_missing_legacy, LEGACY_TIMEOUT, NULL); xmpp_send(conn, iq); @@ -853,7 +853,7 @@ static void _auth(xmpp_conn_t * const conn) /** Set up handlers at stream start. * This function is called internally to Strophe for handling the opening * of an XMPP stream. It's called by the parser when a stream is opened - * or reset, and adds the initial handlers for and + * or reset, and adds the initial handlers for and * . This function is not intended for use outside * of Strophe. * @@ -915,7 +915,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn, /* if bind is required, go ahead and start it */ if (conn->bind_required) { /* bind resource */ - + /* setup response handlers */ handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL); handler_add_timed(conn, _handle_missing_bind, @@ -947,7 +947,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn, resource = NULL; } - /* if we have a resource to request, do it. otherwise the + /* if we have a resource to request, do it. otherwise the server will assign us one */ if (resource) { res = xmpp_stanza_new(conn->ctx); @@ -998,7 +998,7 @@ static int _handle_missing_features_sasl(xmpp_conn_t * const conn, xmpp_disconnect(conn); return 0; } - + static int _handle_bind(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) @@ -1030,7 +1030,7 @@ static int _handle_bind(xmpp_conn_t * const conn, if (conn->session_required) { /* setup response handlers */ handler_add_id(conn, _handle_session, "_xmpp_session1", NULL); - handler_add_timed(conn, _handle_missing_session, + handler_add_timed(conn, _handle_missing_session, SESSION_TIMEOUT, NULL); /* send session request */ @@ -1061,9 +1061,9 @@ static int _handle_bind(xmpp_conn_t * const conn, xmpp_stanza_release(iq); } else { conn->authenticated = 1; - + /* call connection handler */ - conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, + conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata); } } else { @@ -1100,7 +1100,7 @@ static int _handle_session(xmpp_conn_t * const conn, xmpp_debug(conn->ctx, "xmpp", "Session establishment successful."); conn->authenticated = 1; - + /* call connection handler */ conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata); } else {