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
** 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 <success> or <failure> 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 <stream:error/> and
* or reset, and adds the initial handlers for <stream:error/> and
* <stream:features/>. 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 {