cpw.darkrain42.xmpp.scram: a6243850: jabber: Add SASLprep and the username su...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Mon Nov 30 15:41:23 EST 2009
-----------------------------------------------------------------
Revision: a6243850821f40a77b12227baeb436de03896abe
Ancestor: 1f735ffef4b424fdc647312c81fea5a83dc22cad
Author: darkrain42 at pidgin.im
Date: 2009-11-30T20:34:54
Branch: im.pidgin.cpw.darkrain42.xmpp.scram
URL: http://d.pidgin.im/viewmtn/revision/info/a6243850821f40a77b12227baeb436de03896abe
Modified files:
libpurple/protocols/jabber/auth_scram.c
libpurple/protocols/jabber/auth_scram.h
libpurple/protocols/jabber/jutil.c
libpurple/protocols/jabber/jutil.h
libpurple/tests/test_jabber_scram.c
ChangeLog:
jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
The non-libidn code has not been tested.
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/auth_scram.c 58cb4d7993882757edb91d259b05f2fb44bcff51
+++ libpurple/protocols/jabber/auth_scram.c 3e6bf8ce68e3778cc331cdcb4aa75483001fa53d
@@ -181,7 +181,10 @@ jabber_scram_calc_proofs(JabberScramData
data->server_signature->len = hash_len;
salted_password = jabber_scram_hi(data->hash, pass, salt, iterations);
+
+ memset(pass->str, 0, pass->allocated_len);
g_string_free(pass, TRUE);
+
if (!salted_password)
return FALSE;
@@ -358,6 +361,25 @@ jabber_scram_feed_parser(JabberScramData
return TRUE;
}
+static gchar *escape_username(const gchar *in)
+{
+ GString *s = g_string_new(in);
+ gchar *c;
+ gsize i = 0;
+
+ c = s->str;
+ while (*c) {
+ if (*c == ',' || *c == '=') {
+ g_string_erase(s, i, 1);
+ g_string_insert(s, i, *c == ',' ? "=2C" : "=3D");
+ }
+
+ ++c; ++i;
+ }
+
+ return g_string_free(s, FALSE);
+}
+
static xmlnode *scram_start(JabberStream *js, xmlnode *mechanisms)
{
xmlnode *reply;
@@ -367,10 +389,28 @@ static xmlnode *scram_start(JabberStream
gboolean binding_supported = TRUE;
#endif
gchar *dec_out, *enc_out;
+ gchar *prepped_node, *tmp;
+ gchar *prepped_pass;
+ prepped_node = jabber_saslprep(js->user->node);
+ if (!prepped_node) {
+ /* TODO: Error handling in the response value from scram_start */
+ return NULL;
+ }
+
+ tmp = escape_username(prepped_node);
+ g_free(prepped_node);
+ prepped_node = tmp;
+
+ prepped_pass = jabber_saslprep(purple_connection_get_password(js->gc));
+ if (!prepped_pass) {
+ g_free(prepped_node);
+ return NULL;
+ }
+
data = js->auth_mech_data = g_new0(JabberScramData, 1);
data->hash = mech_to_hash(js->auth_mech->name);
- data->password = purple_connection_get_password(js->gc);
+ data->password = prepped_pass;
#ifdef CHANNEL_BINDING
if (strstr(js->auth_mech_name, "-PLUS"))
@@ -381,8 +421,8 @@ static xmlnode *scram_start(JabberStream
data->auth_message = g_string_new(NULL);
g_string_printf(data->auth_message, "n=%s,r=%s",
- js->user->node /* TODO: SaslPrep */,
- data->cnonce);
+ prepped_node, data->cnonce);
+ g_free(prepped_node);
data->step = 1;
@@ -500,6 +540,11 @@ void jabber_scram_data_destroy(JabberScr
g_string_free(data->client_proof, TRUE);
if (data->server_signature)
g_string_free(data->server_signature, TRUE);
+ if (data->password) {
+ memset(data->password, 0, strlen(data->password));
+ g_free(data->password);
+ }
+
g_free(data);
}
============================================================
--- libpurple/protocols/jabber/auth_scram.h 527089bfbf85ffb55506fe4ca292e1bf230bf40c
+++ libpurple/protocols/jabber/auth_scram.h 2ca54ce4052318fbc65cd3802f7fa089c88ba01a
@@ -40,8 +40,8 @@ typedef struct {
GString *client_proof;
GString *server_signature;
-
- const gchar *password;
+
+ gchar *password;
gboolean channel_binding;
int step;
} JabberScramData;
============================================================
--- libpurple/protocols/jabber/jutil.c 603120abe6629d5e8f9e79d5198134bb252b0875
+++ libpurple/protocols/jabber/jutil.c d8bcbe586e0ac7c3b8c610001d9641680083a227
@@ -276,6 +276,42 @@ gboolean jabber_resourceprep_validate(co
#endif /* USE_IDN */
}
+char *jabber_saslprep(const char *in)
+{
+#ifdef USE_IDN
+ char *out;
+
+ g_return_val_if_fail(in != NULL, NULL);
+ g_return_val_if_fail(strlen(in) <= sizeof(idn_buffer) - 1, NULL);
+
+ strncpy(idn_buffer, in, sizeof(idn_buffer) - 1);
+ idn_buffer[sizeof(idn_buffer) - 1] = '\0';
+
+ if (STRINGPREP_OK != stringprep(idn_buffer, sizeof(idn_buffer), 0,
+ stringprep_saslprep)) {
+ memset(idn_buffer, 0, sizeof(idn_buffer));
+ return NULL;
+ }
+
+ out = g_strdup(idn_buffer);
+ memset(idn_buffer, 0, sizeof(idn_buffer));
+ return out;
+#else /* USE_IDN */
+ /* TODO: Something better than disallowing all non-ASCII characters */
+ /* TODO: Is this even correct? */
+ const guchar *c;
+
+ c = (const guchar *)in;
+ while (*c) {
+ if (*c > 0x7f ||
+ (*c < 0x20 && *c != '\t' && *c != '\n' && *c != '\r'))
+ return NULL;
+ }
+
+ return g_strdup(in);
+#endif /* USE_IDN */
+}
+
static JabberID*
jabber_id_new_internal(const char *str, gboolean allow_terminating_slash)
{
============================================================
--- libpurple/protocols/jabber/jutil.h 02b6b2dd78e434bf836d385baa5748633b7885d3
+++ libpurple/protocols/jabber/jutil.h c9030d77d6bf1616a6b8476dd7788ae08e8d9279
@@ -51,6 +51,15 @@ gboolean jabber_resourceprep_validate(co
gboolean jabber_domain_validate(const char *);
gboolean jabber_resourceprep_validate(const char *);
+/**
+ * Apply the SASLprep profile of stringprep to the string passed in.
+ *
+ * @returns A newly allocated string containing the normalized version
+ * of the input, or NULL if an error occurred (the string could
+ * not be normalized)
+ */
+char *jabber_saslprep(const char *);
+
PurpleConversation *jabber_find_unnormalized_conv(const char *name, PurpleAccount *account);
char *jabber_calculate_data_sha1sum(gconstpointer data, size_t len);
============================================================
--- libpurple/tests/test_jabber_scram.c 59502303261ce1097beec660446709ea04013546
+++ libpurple/tests/test_jabber_scram.c bdb6aa6515f209808bb118bf243f91d23ab50cb9
@@ -36,7 +36,7 @@ START_TEST(test_proofs)
/* const char *server_signature; */
data->hash = "sha1";
- data->password = "password";
+ data->password = g_strdup("password");
data->auth_message = g_string_new("n=username at jabber.org,r=8jLxB5515dhFxBil5A0xSXMH,"
"r=8jLxB5515dhFxBil5A0xSXMHabc,s=c2FsdA==,i=1,"
"c=biws,r=8jLxB5515dhFxBil5A0xSXMHabc");
@@ -48,8 +48,8 @@ START_TEST(test_proofs)
fail_unless(0 == memcmp(client_proof, data->client_proof->str, 20));
g_string_free(salt, TRUE);
- g_string_free(data->auth_message, TRUE);
- g_free(data);
+
+ jabber_scram_data_destroy(data);
}
END_TEST
@@ -61,7 +61,7 @@ START_TEST(test_mech)
data->step = 1;
data->hash = "sha1";
- data->password = "password";
+ data->password = g_strdup("password");
data->cnonce = g_strdup("H7yDYKAWBCrM2Fa5SxGa4iez");
data->auth_message = g_string_new("n=paul,r=H7yDYKAWBCrM2Fa5SxGa4iez");
More information about the Commits
mailing list