cpw.darkrain42.xmpp.scram: 90b6819f: Let's try a more complex set of return s...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Tue Dec 1 02:36:47 EST 2009
-----------------------------------------------------------------
Revision: 90b6819fa75dbf90fc1c2132fe445eaf4661c383
Ancestor: f23be1307e15efad8ead51f499dd2eb638d0306f
Author: darkrain42 at pidgin.im
Date: 2009-12-01T07:32:53
Branch: im.pidgin.cpw.darkrain42.xmpp.scram
URL: http://d.pidgin.im/viewmtn/revision/info/90b6819fa75dbf90fc1c2132fe445eaf4661c383
Modified files:
libpurple/protocols/jabber/auth.c
libpurple/protocols/jabber/auth.h
libpurple/protocols/jabber/auth_digest_md5.c
libpurple/protocols/jabber/auth_plain.c
libpurple/protocols/jabber/auth_scram.c
ChangeLog:
Let's try a more complex set of return states / values for auth mechs.
This won't build with Cyrus support yet.
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/auth.c 33525782a88e6371457b1b7bb399cf0bfcdee44a
+++ libpurple/protocols/jabber/auth.c 4e6fdfa14bb38a130dee2106af5c38772201ecdf
@@ -162,8 +162,10 @@ jabber_auth_start(JabberStream *js, xmln
{
GSList *mechanisms = NULL;
GSList *l;
- xmlnode *response;
+ xmlnode *response = NULL;
xmlnode *mechs, *mechnode;
+ JabberSaslState state;
+ const char *msg = NULL;
if(js->registration) {
jabber_register_start(js);
@@ -214,8 +216,12 @@ jabber_auth_start(JabberStream *js, xmln
return;
}
- response = js->auth_mech->start(js, mechs);
- if (response) {
+ state = js->auth_mech->start(js, mechs, &response, &msg);
+ if (state == JABBER_SASL_STATE_FAIL) {
+ purple_connection_error_reason(js->gc,
+ PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
+ msg ? msg : _("Unknown Error"));
+ } else if (response) {
jabber_send(js, response);
xmlnode_free(response);
}
@@ -413,8 +419,14 @@ jabber_auth_handle_challenge(JabberStrea
}
if (js->auth_mech && js->auth_mech->handle_challenge) {
- xmlnode *response = js->auth_mech->handle_challenge(js, packet);
- if (response != NULL) {
+ xmlnode *response = NULL;
+ const char *msg = NULL;
+ JabberSaslState state = js->auth_mech->handle_challenge(js, packet, &response, &msg);
+ if (state == JABBER_SASL_STATE_FAIL) {
+ purple_connection_error_reason(js->gc,
+ PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
+ msg ? msg : _("Invalid challenge from server"));
+ } else if (response) {
jabber_send(js, response);
xmlnode_free(response);
}
@@ -433,9 +445,21 @@ void jabber_auth_handle_success(JabberSt
return;
}
- if (js->auth_mech && js->auth_mech->handle_success &&
- !js->auth_mech->handle_success(js, packet)) {
- return;
+ if (js->auth_mech && js->auth_mech->handle_success) {
+ const char *msg = NULL;
+ JabberSaslState state = js->auth_mech->handle_success(js, packet, &msg);
+
+ if (state == JABBER_SASL_STATE_FAIL) {
+ purple_connection_error_reason(js->gc,
+ PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
+ msg ? msg : _("Invalid response from server"));
+ return;
+ } else if (state == JABBER_SASL_STATE_CONTINUE) {
+ purple_connection_error_reason(js->gc,
+ PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
+ msg ? msg : _("Server thinks authentication is complete, but client does not"));
+ return;
+ }
}
/*
@@ -452,8 +476,11 @@ void jabber_auth_handle_failure(JabberSt
char *msg;
if (js->auth_mech && js->auth_mech->handle_failure) {
- xmlnode *stanza = js->auth_mech->handle_failure(js, packet);
- if (stanza) {
+ xmlnode *stanza = NULL;
+ const char *msg = NULL;
+ JabberSaslState state = js->auth_mech->handle_failure(js, packet, &stanza, &msg);
+
+ if (state != JABBER_SASL_STATE_FAIL && stanza) {
jabber_send(js, stanza);
xmlnode_free(stanza);
return;
============================================================
--- libpurple/protocols/jabber/auth.h 5c420ab419bd1cd5f25ad5e609b280c3a063f838
+++ libpurple/protocols/jabber/auth.h 5de434da6e406659e76310786a8840555fff589c
@@ -29,13 +29,19 @@ typedef struct _JabberSaslMech JabberSas
#include "jabber.h"
#include "xmlnode.h"
+typedef enum {
+ JABBER_SASL_STATE_FAIL = -1, /* Abort, Retry, Fail? */
+ JABBER_SASL_STATE_OK = 0, /* Hooray! */
+ JABBER_SASL_STATE_CONTINUE = 1 /* More authentication required */
+} JabberSaslState;
+
struct _JabberSaslMech {
gint8 priority; /* Higher priority will be tried before lower priority */
const gchar *name;
- xmlnode *(*start)(JabberStream *js, xmlnode *mechanisms);
- xmlnode *(*handle_challenge)(JabberStream *js, xmlnode *packet);
- gboolean (*handle_success)(JabberStream *js, xmlnode *packet);
- xmlnode *(*handle_failure)(JabberStream *js, xmlnode *packet);
+ JabberSaslState (*start)(JabberStream *js, xmlnode *mechanisms, xmlnode **reply, const char **msg);
+ JabberSaslState (*handle_challenge)(JabberStream *js, xmlnode *packet, xmlnode **reply, const char **msg);
+ JabberSaslState (*handle_success)(JabberStream *js, xmlnode *packet, const char **msg);
+ JabberSaslState (*handle_failure)(JabberStream *js, xmlnode *packet, xmlnode **reply, const char **msg);
void (*dispose)(JabberStream *js);
};
============================================================
--- libpurple/protocols/jabber/auth_digest_md5.c d9ecb35ff0a36daefb463c56905396dfadc8938f
+++ libpurple/protocols/jabber/auth_digest_md5.c 54b9882edca5af04170c7b4402fd1e8b5d9f7833
@@ -30,15 +30,16 @@
#include "auth.h"
#include "jabber.h"
-static xmlnode *digest_md5_start(JabberStream *js, xmlnode *packet)
+static JabberSaslState
+digest_md5_start(JabberStream *js, xmlnode *packet, xmlnode **response,
+ const char **msg)
{
- xmlnode *auth;
-
- auth = xmlnode_new("auth");
+ xmlnode *auth = xmlnode_new("auth");
xmlnode_set_namespace(auth, NS_XMPP_SASL);
xmlnode_set_attrib(auth, "mechanism", "DIGEST-MD5");
- return auth;
+ *response = auth;
+ return JABBER_SASL_STATE_CONTINUE;
}
/* Parts of this algorithm are inspired by stuff in libgsasl */
@@ -163,19 +164,20 @@ generate_response_value(JabberID *jid, c
return z;
}
-static xmlnode *digest_md5_handle_challenge(JabberStream *js, xmlnode *packet)
+static JabberSaslState
+digest_md5_handle_challenge(JabberStream *js, xmlnode *packet,
+ xmlnode **response, const char **msg)
{
xmlnode *reply = NULL;
char *enc_in = xmlnode_get_data(packet);
char *dec_in;
char *enc_out;
GHashTable *parts;
+ JabberSaslState state = JABBER_SASL_STATE_CONTINUE;
if (!enc_in) {
- purple_connection_error_reason(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Invalid response from server"));
- return NULL;
+ *msg = _("Invalid response from server");
+ return JABBER_SASL_STATE_FAIL;
}
dec_in = (char *)purple_base64_decode(enc_in, NULL);
@@ -191,9 +193,8 @@ static xmlnode *digest_md5_handle_challe
reply = xmlnode_new("response");
xmlnode_set_namespace(reply, NS_XMPP_SASL);
} else {
- purple_connection_error_reason(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Invalid challenge from server"));
+ *msg = _("Invalid challenge from server");
+ state = JABBER_SASL_STATE_FAIL;
}
g_free(js->expected_rspauth);
js->expected_rspauth = NULL;
@@ -216,11 +217,10 @@ static xmlnode *digest_md5_handle_challe
if(!realm)
realm = js->user->domain;
- if (nonce == NULL || realm == NULL)
- purple_connection_error_reason(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Invalid challenge from server"));
- else {
+ if (nonce == NULL || realm == NULL) {
+ *msg = _("Invalid challenge from server");
+ state = JABBER_SASL_STATE_FAIL;
+ } else {
GString *response = g_string_new("");
char *a2;
char *auth_resp;
@@ -272,7 +272,8 @@ static xmlnode *digest_md5_handle_challe
g_free(dec_in);
g_hash_table_destroy(parts);
- return reply;
+ *response = reply;
+ return state;
}
static JabberSaslMech digest_md5_mech = {
============================================================
--- libpurple/protocols/jabber/auth_plain.c c86a14b6b296440a33e7495d4435eaf0df0ec61f
+++ libpurple/protocols/jabber/auth_plain.c 2bd068ef26d51259ac7adaed2443539c16753890
@@ -80,13 +80,16 @@ static void disallow_plaintext_auth(Purp
_("Server requires plaintext authentication over an unencrypted stream"));
}
-static xmlnode *jabber_plain_start(JabberStream *js, xmlnode *packet)
+static JabberSaslState
+jabber_plain_start(JabberStream *js, xmlnode *packet, xmlnode **response, const char **error)
{
PurpleAccount *account = purple_connection_get_account(js->gc);
char *msg;
- if (jabber_stream_is_ssl(js) || purple_account_get_bool(account, "auth_plain_in_clear", FALSE))
- return finish_plaintext_authentication(js);
+ if (jabber_stream_is_ssl(js) || purple_account_get_bool(account, "auth_plain_in_clear", FALSE)) {
+ *response = finish_plaintext_authentication(js);
+ return JABBER_SASL_STATE_OK;
+ }
msg = g_strdup_printf(_("%s requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"),
purple_account_get_username(account));
@@ -97,7 +100,7 @@ static xmlnode *jabber_plain_start(Jabbe
account, NULL, NULL,
account, allow_plaintext_auth, disallow_plaintext_auth);
g_free(msg);
- return NULL;
+ return JABBER_SASL_STATE_CONTINUE;
}
static JabberSaslMech plain_mech = {
============================================================
--- libpurple/protocols/jabber/auth_scram.c 022ddbb448c0ab860c4ad5ea1551018715877f05
+++ libpurple/protocols/jabber/auth_scram.c 403db21f131a6114fab65b6d0cf9b96cfc883ae3
@@ -341,7 +341,8 @@ static gchar *escape_username(const gcha
return tmp2;
}
-static xmlnode *scram_start(JabberStream *js, xmlnode *mechanisms)
+static JabberSaslState
+scram_start(JabberStream *js, xmlnode *mechanisms, xmlnode **out, const char **error)
{
xmlnode *reply;
JabberScramData *data;
@@ -355,8 +356,8 @@ static xmlnode *scram_start(JabberStream
prepped_node = jabber_saslprep(js->user->node);
if (!prepped_node) {
- /* TODO: Error handling in the response value from scram_start */
- return NULL;
+ *error = _("Unable to canonicalize username");
+ return JABBER_SASL_STATE_FAIL;
}
tmp = escape_username(prepped_node);
@@ -366,7 +367,8 @@ static xmlnode *scram_start(JabberStream
prepped_pass = jabber_saslprep(purple_connection_get_password(js->gc));
if (!prepped_pass) {
g_free(prepped_node);
- return NULL;
+ *error = _("Unable to canonicalize password");
+ return JABBER_SASL_STATE_FAIL;
}
data = js->auth_mech_data = g_new0(JabberScramData, 1);
@@ -401,22 +403,26 @@ static xmlnode *scram_start(JabberStream
g_free(enc_out);
g_free(dec_out);
- return reply;
+ *out = reply;
+ return JABBER_SASL_STATE_CONTINUE;
}
-static xmlnode *scram_handle_challenge(JabberStream *js, xmlnode *challenge)
+static JabberSaslState
+scram_handle_challenge(JabberStream *js, xmlnode *challenge, xmlnode **out, const char **error)
{
JabberScramData *data = js->auth_mech_data;
xmlnode *reply;
gchar *enc_in, *dec_in;
gchar *enc_out = NULL, *dec_out = NULL;
gsize len;
+ JabberSaslState state = JABBER_SASL_STATE_FAIL;
enc_in = xmlnode_get_data(challenge);
if (!enc_in || *enc_in == '\0') {
reply = xmlnode_new("abort");
xmlnode_set_namespace(reply, NS_XMPP_SASL);
data->step = -1;
+ *error = _("Invalid challenge from server");
goto out;
}
@@ -427,6 +433,7 @@ static xmlnode *scram_handle_challenge(J
reply = xmlnode_new("abort");
xmlnode_set_namespace(reply, NS_XMPP_SASL);
data->step = -1;
+ *error = _("Malicious challenge from server");
goto out;
}
@@ -436,6 +443,7 @@ static xmlnode *scram_handle_challenge(J
reply = xmlnode_new("abort");
xmlnode_set_namespace(reply, NS_XMPP_SASL);
data->step = -1;
+ *error = _("Invalid challenge from server");
goto out;
}
@@ -450,14 +458,18 @@ static xmlnode *scram_handle_challenge(J
xmlnode_insert_data(reply, enc_out, -1);
}
+ state = JABBER_SASL_STATE_CONTINUE;
+
out:
g_free(enc_out);
g_free(dec_out);
- return reply;
+ *out = reply;
+ return state;
}
-static gboolean scram_handle_success(JabberStream *js, xmlnode *packet)
+static JabberSaslState
+scram_handle_success(JabberStream *js, xmlnode *packet, const char **error)
{
JabberScramData *data = js->auth_mech_data;
char *enc_in, *dec_in;
@@ -468,28 +480,32 @@ static gboolean scram_handle_success(Jab
g_return_val_if_fail(enc_in != NULL && *enc_in != '\0', FALSE);
if (data->step == 3)
- return TRUE;
+ return JABBER_SASL_STATE_OK;
- if (data->step != 2)
- return FALSE;
+ if (data->step != 2) {
+ *error = _("Unexpected response from server");
+ return JABBER_SASL_STATE_FAIL;
+ }
dec_in = (gchar *)purple_base64_decode(enc_in, &len);
g_free(enc_in);
if (!dec_in || len != strlen(dec_in)) {
/* Danger afoot; SCRAM shouldn't contain NUL bytes */
g_free(dec_in);
- return FALSE;
+ *error = _("Invalid challenge from server");
+ return JABBER_SASL_STATE_FAIL;
}
purple_debug_misc("jabber", "decoded success: %s\n", dec_in);
if (!jabber_scram_feed_parser(data, dec_in, &dec_out) || dec_out != NULL) {
g_free(dec_out);
- return FALSE;
+ *error = _("Invalid challenge from server");
+ return JABBER_SASL_STATE_FAIL;
}
/* Hooray */
- return TRUE;
+ return JABBER_SASL_STATE_OK;
}
void jabber_scram_data_destroy(JabberScramData *data)
More information about the Commits
mailing list