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.
This commit is contained in:
James Booth
2015-08-03 23:05:04 +01:00
parent 527bc0573a
commit 7cdef1e319

View File

@@ -1,7 +1,7 @@
/* auth.c /* auth.c
** strophe XMPP client library -- auth functions and handlers ** 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 ** This software is provided AS-IS with no warranty, either express or
** implied. ** implied.
@@ -9,7 +9,7 @@
** This program is dual licensed under the MIT and GPLv3 licenses. ** This program is dual licensed under the MIT and GPLv3 licenses.
*/ */
/** @file /** @file
* Authentication function and handlers. * 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 */ /* free old stream error if it's still there */
if (conn->stream_error) { if (conn->stream_error) {
xmpp_stanza_release(conn->stream_error->stanza); 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->text);
xmpp_free(conn->ctx, conn->stream_error); xmpp_free(conn->ctx, conn->stream_error);
} }
@@ -237,9 +237,9 @@ static int _handle_features(xmpp_conn_t * const conn,
/* check for SASL */ /* check for SASL */
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms"); child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) { 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)) { 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); text = xmpp_stanza_get_text(mech);
if (strcasecmp(text, "PLAIN") == 0) if (strcasecmp(text, "PLAIN") == 0)
conn->sasl_support |= SASL_MASK_PLAIN; conn->sasl_support |= SASL_MASK_PLAIN;
@@ -256,7 +256,7 @@ static int _handle_features(xmpp_conn_t * const conn,
} }
_auth(conn); _auth(conn);
return 0; return 0;
} }
@@ -281,7 +281,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
{ {
char *name; char *name;
name = xmpp_stanza_get_name(stanza); name = xmpp_stanza_get_name(stanza);
xmpp_debug(conn->ctx, "xmpp", xmpp_debug(conn->ctx, "xmpp",
"handle proceedtls called for %s", name); "handle proceedtls called for %s", name);
if (strcmp(name, "proceed") == 0) { if (strcmp(name, "proceed") == 0) {
@@ -295,7 +295,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
tls_free(conn->tls); tls_free(conn->tls);
conn->tls = NULL; conn->tls = NULL;
conn->tls_failed = 1; conn->tls_failed = 1;
/* failed tls spoils the connection, so disconnect */ /* failed tls spoils the connection, so disconnect */
xmpp_disconnect(conn); xmpp_disconnect(conn);
} }
@@ -321,14 +321,14 @@ static int _handle_sasl_result(xmpp_conn_t * const conn,
/* the server should send a <success> or <failure> stanza */ /* the server should send a <success> or <failure> stanza */
if (strcmp(name, "failure") == 0) { 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); (char *)userdata);
/* fall back to next auth method */ /* fall back to next auth method */
_auth(conn); _auth(conn);
} else if (strcmp(name, "success") == 0) { } else if (strcmp(name, "success") == 0) {
/* SASL PLAIN auth successful, we need to restart the stream */ /* 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); (char *)userdata);
/* reset parser */ /* reset parser */
@@ -373,10 +373,10 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
if (!auth) { if (!auth) {
disconnect_mem_error(conn); disconnect_mem_error(conn);
return 0; return 0;
} }
xmpp_stanza_set_name(auth, "response"); xmpp_stanza_set_name(auth, "response");
xmpp_stanza_set_ns(auth, XMPP_NS_SASL); xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
authdata = xmpp_stanza_new(conn->ctx); authdata = xmpp_stanza_new(conn->ctx);
if (!authdata) { if (!authdata) {
disconnect_mem_error(conn); 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_add_child(auth, authdata);
xmpp_stanza_release(authdata); xmpp_stanza_release(authdata);
handler_add(conn, _handle_digestmd5_rspauth, handler_add(conn, _handle_digestmd5_rspauth,
XMPP_NS_SASL, NULL, NULL, NULL); XMPP_NS_SASL, NULL, NULL, NULL);
xmpp_send(conn, auth); xmpp_send(conn, auth);
@@ -422,7 +422,7 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
if (!auth) { if (!auth) {
disconnect_mem_error(conn); disconnect_mem_error(conn);
return 0; return 0;
} }
xmpp_stanza_set_name(auth, "response"); xmpp_stanza_set_name(auth, "response");
xmpp_stanza_set_ns(auth, XMPP_NS_SASL); xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
xmpp_send(conn, auth); 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_name(starttls, "starttls");
xmpp_stanza_set_ns(starttls, XMPP_NS_TLS); xmpp_stanza_set_ns(starttls, XMPP_NS_TLS);
} }
return starttls; 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_ns(auth, XMPP_NS_SASL);
xmpp_stanza_set_attribute(auth, "mechanism", mechanism); xmpp_stanza_set_attribute(auth, "mechanism", mechanism);
} }
return auth; return auth;
} }
/* authenticate the connection /* authenticate the connection
* this may get called multiple times. if any auth method fails, * this may get called multiple times. if any auth method fails,
* this will get called again until one auth method succeeds or every * this will get called again until one auth method succeeds or every
* method fails * method fails
*/ */
static void _auth(xmpp_conn_t * const conn) static void _auth(xmpp_conn_t * const conn)
{ {
@@ -619,7 +619,7 @@ static void _auth(xmpp_conn_t * const conn)
return; return;
} }
handler_add(conn, _handle_proceedtls_default, handler_add(conn, _handle_proceedtls_default,
XMPP_NS_TLS, NULL, NULL, NULL); XMPP_NS_TLS, NULL, NULL, NULL);
xmpp_send(conn, auth); xmpp_send(conn, auth);
@@ -644,7 +644,7 @@ static void _auth(xmpp_conn_t * const conn)
/* SASL ANONYMOUS was tried, unset flag */ /* SASL ANONYMOUS was tried, unset flag */
conn->sasl_support &= ~SASL_MASK_ANONYMOUS; conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
} else if (anonjid) { } else if (anonjid) {
xmpp_error(conn->ctx, "auth", xmpp_error(conn->ctx, "auth",
"No node in JID, and SASL ANONYMOUS unsupported."); "No node in JID, and SASL ANONYMOUS unsupported.");
xmpp_disconnect(conn); xmpp_disconnect(conn);
} else if (conn->sasl_support & SASL_MASK_SCRAMSHA1) { } 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_NS_SASL, NULL, NULL, NULL);
xmpp_send(conn, auth); xmpp_send(conn, auth);
@@ -718,7 +718,7 @@ static void _auth(xmpp_conn_t * const conn)
if (!authdata) { if (!authdata) {
disconnect_mem_error(conn); disconnect_mem_error(conn);
return; return;
} }
authid = _get_authid(conn); authid = _get_authid(conn);
if (!authid) { if (!authid) {
disconnect_mem_error(conn); disconnect_mem_error(conn);
@@ -746,7 +746,7 @@ static void _auth(xmpp_conn_t * const conn)
conn->sasl_support &= ~SASL_MASK_PLAIN; conn->sasl_support &= ~SASL_MASK_PLAIN;
} else if (conn->type == XMPP_CLIENT) { } else if (conn->type == XMPP_CLIENT) {
/* legacy client authentication */ /* legacy client authentication */
iq = xmpp_stanza_new(conn->ctx); iq = xmpp_stanza_new(conn->ctx);
if (!iq) { if (!iq) {
disconnect_mem_error(conn); disconnect_mem_error(conn);
@@ -832,7 +832,7 @@ static void _auth(xmpp_conn_t * const conn)
} else { } else {
xmpp_stanza_release(authdata); xmpp_stanza_release(authdata);
xmpp_stanza_release(iq); xmpp_stanza_release(iq);
xmpp_error(conn->ctx, "auth", xmpp_error(conn->ctx, "auth",
"Cannot authenticate without resource"); "Cannot authenticate without resource");
xmpp_disconnect(conn); xmpp_disconnect(conn);
return; return;
@@ -841,7 +841,7 @@ static void _auth(xmpp_conn_t * const conn)
xmpp_stanza_release(authdata); xmpp_stanza_release(authdata);
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL); 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); LEGACY_TIMEOUT, NULL);
xmpp_send(conn, iq); xmpp_send(conn, iq);
@@ -853,7 +853,7 @@ static void _auth(xmpp_conn_t * const conn)
/** Set up handlers at stream start. /** Set up handlers at stream start.
* This function is called internally to Strophe for handling the opening * 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 * of an XMPP stream. It's called by the parser when a stream is opened
* or reset, and adds the initial handlers for <stream:error/> and * or reset, and adds the initial handlers for <stream:error/> and
* <stream:features/>. This function is not intended for use outside * <stream:features/>. This function is not intended for use outside
* of Strophe. * 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 bind is required, go ahead and start it */
if (conn->bind_required) { if (conn->bind_required) {
/* bind resource */ /* bind resource */
/* setup response handlers */ /* setup response handlers */
handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL); handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL);
handler_add_timed(conn, _handle_missing_bind, handler_add_timed(conn, _handle_missing_bind,
@@ -947,7 +947,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
resource = NULL; 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 */ server will assign us one */
if (resource) { if (resource) {
res = xmpp_stanza_new(conn->ctx); res = xmpp_stanza_new(conn->ctx);
@@ -998,7 +998,7 @@ static int _handle_missing_features_sasl(xmpp_conn_t * const conn,
xmpp_disconnect(conn); xmpp_disconnect(conn);
return 0; return 0;
} }
static int _handle_bind(xmpp_conn_t * const conn, static int _handle_bind(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, xmpp_stanza_t * const stanza,
void * const userdata) void * const userdata)
@@ -1030,7 +1030,7 @@ static int _handle_bind(xmpp_conn_t * const conn,
if (conn->session_required) { if (conn->session_required) {
/* setup response handlers */ /* setup response handlers */
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL); 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); SESSION_TIMEOUT, NULL);
/* send session request */ /* send session request */
@@ -1061,9 +1061,9 @@ static int _handle_bind(xmpp_conn_t * const conn,
xmpp_stanza_release(iq); xmpp_stanza_release(iq);
} else { } else {
conn->authenticated = 1; conn->authenticated = 1;
/* call connection handler */ /* call connection handler */
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
conn->userdata); conn->userdata);
} }
} else { } else {
@@ -1100,7 +1100,7 @@ static int _handle_session(xmpp_conn_t * const conn,
xmpp_debug(conn->ctx, "xmpp", "Session establishment successful."); xmpp_debug(conn->ctx, "xmpp", "Session establishment successful.");
conn->authenticated = 1; conn->authenticated = 1;
/* call connection handler */ /* call connection handler */
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata); conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
} else { } else {