annotate libpurple/protocols/jabber/auth_scram.c @ 29414:9e735d7e2f1d

Oops, just realized that caps can be reset in certain situations, and we only want that to happen for the specific resource, not the entire buddy caps.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Thu, 11 Feb 2010 04:15:00 +0000
parents b94fd073187c
children 9134be6baaef
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
1 /*
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
2 * purple - Jabber Protocol Plugin
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
3 *
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
4 * Purple is the legal property of its developers, whose names are too numerous
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
5 * to list here. Please refer to the COPYRIGHT file distributed with this
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
6 * source distribution.
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
7 *
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
8 * This program is free software; you can redistribute it and/or modify
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
9 * it under the terms of the GNU General Public License as published by
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
10 * the Free Software Foundation; either version 2 of the License, or
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
11 * (at your option) any later version.
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
12 *
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
13 * This program is distributed in the hope that it will be useful,
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
16 * GNU General Public License for more details.
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
17 *
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
18 * You should have received a copy of the GNU General Public License
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
19 * along with this program; if not, write to the Free Software
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
21 *
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
22 */
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
23 #include "internal.h"
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
24
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
25 #include "auth.h"
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
26 #include "auth_scram.h"
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
27
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
28 #include "cipher.h"
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
29 #include "debug.h"
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
30
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
31 static const JabberScramHash hashes[] = {
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
32 { "-SHA-1", "sha1", 20 },
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
33 };
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
34
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
35 static const JabberScramHash *mech_to_hash(const char *mech)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
36 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
37 int i;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
38
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
39 g_return_val_if_fail(mech != NULL && *mech != '\0', NULL);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
40
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
41 for (i = 0; i < G_N_ELEMENTS(hashes); ++i) {
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
42 if (strstr(mech, hashes[i].mech_substr))
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
43 return &(hashes[i]);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
44 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
45
29094
40a46992c728 jabber: Interop with Prosody (via Tobias' code). Hooray!
Paul Aurich <paul@darkrain42.org>
parents: 29093
diff changeset
46 purple_debug_error("jabber", "Unknown SCRAM mechanism %s\n", mech);
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
47 g_return_val_if_reached(NULL);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
48 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
49
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
50 guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str,
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
51 GString *salt, guint iterations)
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
52 {
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
53 PurpleCipherContext *context;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
54 guchar *result;
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
55 guint i;
29087
ec843b380a1d How is it that there's no programmatic way to get the output size of the hash functions without resorting to a hardcoded table? Or did I miss something?
Paul Aurich <paul@darkrain42.org>
parents: 29086
diff changeset
56 guchar *prev, *tmp;
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
57
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
58 g_return_val_if_fail(hash != NULL, NULL);
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
59 g_return_val_if_fail(str != NULL && str->len > 0, NULL);
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
60 g_return_val_if_fail(salt != NULL && salt->len > 0, NULL);
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
61 g_return_val_if_fail(iterations > 0, NULL);
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
62
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
63 prev = g_new0(guint8, hash->size);
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
64 tmp = g_new0(guint8, hash->size);
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
65 result = g_new0(guint8, hash->size);
29087
ec843b380a1d How is it that there's no programmatic way to get the output size of the hash functions without resorting to a hardcoded table? Or did I miss something?
Paul Aurich <paul@darkrain42.org>
parents: 29086
diff changeset
66
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
67 context = purple_cipher_context_new_by_name("hmac", NULL);
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
68
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
69 /* Append INT(1), a four-octet encoding of the integer 1, most significant
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
70 * octet first. */
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
71 g_string_append_len(salt, "\0\0\0\1", 4);
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
72
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
73 /* Compute U0 */
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
74 purple_cipher_context_set_option(context, "hash", (gpointer)hash->name);
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
75 purple_cipher_context_set_key_with_len(context, (guchar *)str->str, str->len);
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
76 purple_cipher_context_append(context, (guchar *)salt->str, salt->len);
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
77 purple_cipher_context_digest(context, hash->size, result, NULL);
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
78
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
79 memcpy(prev, result, hash->size);
29086
398ff52e7d62 Fix the Hi() function and actually 'mtn add' the test file.
Paul Aurich <paul@darkrain42.org>
parents: 29085
diff changeset
80
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
81 /* Compute U1...Ui */
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
82 for (i = 1; i < iterations; ++i) {
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
83 guint j;
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
84 purple_cipher_context_set_option(context, "hash", (gpointer)hash->name);
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
85 purple_cipher_context_set_key_with_len(context, (guchar *)str->str, str->len);
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
86 purple_cipher_context_append(context, prev, hash->size);
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
87 purple_cipher_context_digest(context, hash->size, tmp, NULL);
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
88
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
89 for (j = 0; j < hash->size; ++j)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
90 result[j] ^= tmp[j];
29086
398ff52e7d62 Fix the Hi() function and actually 'mtn add' the test file.
Paul Aurich <paul@darkrain42.org>
parents: 29085
diff changeset
91
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
92 memcpy(prev, tmp, hash->size);
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
93 }
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
94
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
95 purple_cipher_context_destroy(context);
29088
2b4465db73f1 Clean up the two temporary buffers.
Paul Aurich <paul@darkrain42.org>
parents: 29087
diff changeset
96 g_free(tmp);
2b4465db73f1 Clean up the two temporary buffers.
Paul Aurich <paul@darkrain42.org>
parents: 29087
diff changeset
97 g_free(prev);
29085
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
98 return result;
338eeaf371e2 jabber: Add the Hi() function (PBKDF2).
Paul Aurich <paul@darkrain42.org>
parents:
diff changeset
99 }
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
100
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
101 /*
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
102 * Helper functions for doing the SCRAM calculations. The first argument
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
103 * is the hash algorithm. All buffers must be of the appropriate size
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
104 * according to the JabberScramHash.
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
105 *
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
106 * "str" is a NULL-terminated string for hmac().
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
107 *
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
108 * Needless to say, these are fragile.
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
109 */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
110 static void
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
111 hmac(const JabberScramHash *hash, guchar *out, const guchar *key, const gchar *str)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
112 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
113 PurpleCipherContext *context;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
114
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
115 context = purple_cipher_context_new_by_name("hmac", NULL);
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
116 purple_cipher_context_set_option(context, "hash", (gpointer)hash->name);
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
117 purple_cipher_context_set_key_with_len(context, key, hash->size);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
118 purple_cipher_context_append(context, (guchar *)str, strlen(str));
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
119 purple_cipher_context_digest(context, hash->size, out, NULL);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
120 purple_cipher_context_destroy(context);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
121 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
122
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
123 static void
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
124 hash(const JabberScramHash *hash, guchar *out, const guchar *data)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
125 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
126 PurpleCipherContext *context;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
127
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
128 context = purple_cipher_context_new_by_name(hash->name, NULL);
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
129 purple_cipher_context_append(context, data, hash->size);
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
130 purple_cipher_context_digest(context, hash->size, out, NULL);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
131 purple_cipher_context_destroy(context);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
132 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
133
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
134 gboolean
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
135 jabber_scram_calc_proofs(JabberScramData *data, GString *salt, guint iterations)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
136 {
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
137 guint hash_len = data->hash->size;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
138 guint i;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
139
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
140 GString *pass = g_string_new(data->password);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
141
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
142 guchar *salted_password;
29134
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
143 guchar *client_key, *stored_key, *client_signature, *server_key;
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
144
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
145 client_key = g_new0(guchar, hash_len);
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
146 stored_key = g_new0(guchar, hash_len);
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
147 client_signature = g_new0(guchar, hash_len);
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
148 server_key = g_new0(guchar, hash_len);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
149
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
150 data->client_proof = g_string_sized_new(hash_len);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
151 data->client_proof->len = hash_len;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
152 data->server_signature = g_string_sized_new(hash_len);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
153 data->server_signature->len = hash_len;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
154
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
155 salted_password = jabber_scram_hi(data->hash, pass, salt, iterations);
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
156
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
157 memset(pass->str, 0, pass->allocated_len);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
158 g_string_free(pass, TRUE);
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
159
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
160 if (!salted_password)
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
161 return FALSE;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
162
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
163 /* client_key = HMAC(salted_password, "Client Key") */
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
164 hmac(data->hash, client_key, salted_password, "Client Key");
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
165 /* server_key = HMAC(salted_password, "Server Key") */
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
166 hmac(data->hash, server_key, salted_password, "Server Key");
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
167 g_free(salted_password);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
168
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
169 /* stored_key = HASH(client_key) */
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
170 hash(data->hash, stored_key, client_key);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
171
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
172 /* client_signature = HMAC(stored_key, auth_message) */
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
173 hmac(data->hash, client_signature, stored_key, data->auth_message->str);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
174 /* server_signature = HMAC(server_key, auth_message) */
29104
1c1910b17ae5 jabber: Clean up the SCRAM code a little.
Paul Aurich <paul@darkrain42.org>
parents: 29103
diff changeset
175 hmac(data->hash, (guchar *)data->server_signature->str, server_key, data->auth_message->str);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
176
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
177 /* client_proof = client_key XOR client_signature */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
178 for (i = 0; i < hash_len; ++i)
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
179 data->client_proof->str[i] = client_key[i] ^ client_signature[i];
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
180
29134
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
181 g_free(server_key);
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
182 g_free(client_signature);
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
183 g_free(stored_key);
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
184 g_free(client_key);
a6cd1db77aee jabber: Ugh, make this C89-compliant. Bah.
Paul Aurich <paul@darkrain42.org>
parents: 29107
diff changeset
185
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
186 return TRUE;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
187 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
188
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
189 static gboolean
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
190 parse_server_step1(JabberScramData *data, const char *challenge,
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
191 gchar **out_nonce, GString **out_salt, guint *out_iterations)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
192 {
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
193 char **tokens;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
194 char *token, *decoded, *tmp;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
195 gsize len;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
196 char *nonce = NULL;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
197 GString *salt = NULL;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
198 guint iterations;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
199
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
200 tokens = g_strsplit(challenge, ",", -1);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
201 if (tokens == NULL)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
202 return FALSE;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
203
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
204 token = tokens[0];
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
205 if (token[0] != 'r' || token[1] != '=')
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
206 goto err;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
207
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
208 /* Ensure that the first cnonce_len bytes of the nonce are the original
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
209 * cnonce we sent to the server.
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
210 */
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
211 if (0 != strncmp(data->cnonce, token + 2, strlen(data->cnonce)))
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
212 goto err;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
213
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
214 nonce = g_strdup(token + 2);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
215
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
216 /* The Salt, base64-encoded */
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
217 token = tokens[1];
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
218 if (token[0] != 's' || token[1] != '=')
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
219 goto err;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
220
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
221 decoded = (gchar *)purple_base64_decode(token + 2, &len);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
222 if (!decoded || *decoded == '\0') {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
223 g_free(decoded);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
224 goto err;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
225 }
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
226 salt = g_string_new_len(decoded, len);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
227 g_free(decoded);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
228
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
229 /* The iteration count */
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
230 token = tokens[2];
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
231 if (token[0] != 'i' || token[1] != '=' || token[2] == '\0')
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
232 goto err;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
233
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
234 /* Validate the string */
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
235 for (tmp = token + 2; *tmp; ++tmp)
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
236 if (!g_ascii_isdigit(*tmp))
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
237 goto err;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
238
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
239 iterations = strtoul(token + 2, NULL, 10);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
240
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
241 g_strfreev(tokens);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
242 *out_nonce = nonce;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
243 *out_salt = salt;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
244 *out_iterations = iterations;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
245 return TRUE;
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
246
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
247 err:
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
248 g_free(nonce);
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
249 if (salt)
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
250 g_string_free(salt, TRUE);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
251 g_strfreev(tokens);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
252 return FALSE;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
253 }
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
254
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
255 static gboolean
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
256 parse_server_step2(JabberScramData *data, const char *challenge, gchar **out_verifier)
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
257 {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
258 char **tokens;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
259 char *token;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
260
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
261 tokens = g_strsplit(challenge, ",", -1);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
262 if (tokens == NULL)
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
263 return FALSE;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
264
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
265 token = tokens[0];
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
266 if (token[0] != 'v' || token[1] != '=' || token[2] == '\0') {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
267 g_strfreev(tokens);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
268 return FALSE;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
269 }
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
270
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
271 *out_verifier = g_strdup(token + 2);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
272 g_strfreev(tokens);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
273 return TRUE;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
274 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
275
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
276 gboolean
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
277 jabber_scram_feed_parser(JabberScramData *data, gchar *in, gchar **out)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
278 {
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
279 gboolean ret;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
280
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
281 g_return_val_if_fail(data != NULL, FALSE);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
282
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
283 g_string_append_c(data->auth_message, ',');
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
284 g_string_append(data->auth_message, in);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
285
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
286 if (data->step == 1) {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
287 gchar *nonce, *proof;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
288 GString *salt;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
289 guint iterations;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
290
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
291 ret = parse_server_step1(data, in, &nonce, &salt, &iterations);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
292 if (!ret)
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
293 return FALSE;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
294
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
295 g_string_append_c(data->auth_message, ',');
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
296
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
297 /* "biws" is the base64 encoding of "n,,". I promise. */
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
298 g_string_append_printf(data->auth_message, "c=%s,r=%s", "biws", nonce);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
299 #ifdef CHANNEL_BINDING
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
300 #error fix this
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
301 #endif
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
302
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
303 ret = jabber_scram_calc_proofs(data, salt, iterations);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
304 if (!ret)
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
305 return FALSE;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
306
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
307 proof = purple_base64_encode((guchar *)data->client_proof->str, data->client_proof->len);
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
308 *out = g_strdup_printf("c=%s,r=%s,p=%s", "biws", nonce, proof);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
309 g_free(proof);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
310 } else if (data->step == 2) {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
311 gchar *server_sig, *enc_server_sig;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
312 gsize len;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
313
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
314 ret = parse_server_step2(data, in, &enc_server_sig);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
315 if (!ret)
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
316 return FALSE;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
317
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
318 server_sig = (gchar *)purple_base64_decode(enc_server_sig, &len);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
319 g_free(enc_server_sig);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
320
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
321 if (server_sig == NULL || len != data->server_signature->len) {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
322 g_free(server_sig);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
323 return FALSE;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
324 }
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
325
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
326 if (0 != memcmp(server_sig, data->server_signature->str, len)) {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
327 g_free(server_sig);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
328 return FALSE;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
329 }
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
330 g_free(server_sig);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
331
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
332 *out = NULL;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
333 } else {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
334 purple_debug_error("jabber", "SCRAM: There is no step %d\n", data->step);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
335 return FALSE;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
336 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
337
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
338 return TRUE;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
339 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
340
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
341 static gchar *escape_username(const gchar *in)
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
342 {
29103
f10741a709a9 jabber: Should have looked for this function earlier.
Paul Aurich <paul@darkrain42.org>
parents: 29099
diff changeset
343 gchar *tmp, *tmp2;
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
344
29103
f10741a709a9 jabber: Should have looked for this function earlier.
Paul Aurich <paul@darkrain42.org>
parents: 29099
diff changeset
345 tmp = purple_strreplace(in, "=", "=3D");
f10741a709a9 jabber: Should have looked for this function earlier.
Paul Aurich <paul@darkrain42.org>
parents: 29099
diff changeset
346 tmp2 = purple_strreplace(tmp, ",", "=2D");
f10741a709a9 jabber: Should have looked for this function earlier.
Paul Aurich <paul@darkrain42.org>
parents: 29099
diff changeset
347 g_free(tmp);
f10741a709a9 jabber: Should have looked for this function earlier.
Paul Aurich <paul@darkrain42.org>
parents: 29099
diff changeset
348 return tmp2;
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
349 }
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
350
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
351 static JabberSaslState
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
352 scram_start(JabberStream *js, xmlnode *mechanisms, xmlnode **out, char **error)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
353 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
354 xmlnode *reply;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
355 JabberScramData *data;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
356 guint64 cnonce;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
357 #ifdef CHANNEL_BINDING
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
358 gboolean binding_supported = TRUE;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
359 #endif
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
360 gchar *dec_out, *enc_out;
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
361 gchar *prepped_node, *tmp;
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
362 gchar *prepped_pass;
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
363
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
364 prepped_node = jabber_saslprep(js->user->node);
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
365 if (!prepped_node) {
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
366 *error = g_strdup(_("Unable to canonicalize username"));
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
367 return JABBER_SASL_STATE_FAIL;
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
368 }
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
369
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
370 tmp = escape_username(prepped_node);
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
371 g_free(prepped_node);
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
372 prepped_node = tmp;
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
373
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
374 prepped_pass = jabber_saslprep(purple_connection_get_password(js->gc));
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
375 if (!prepped_pass) {
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
376 g_free(prepped_node);
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
377 *error = g_strdup(_("Unable to canonicalize password"));
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
378 return JABBER_SASL_STATE_FAIL;
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
379 }
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
380
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
381 data = js->auth_mech_data = g_new0(JabberScramData, 1);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
382 data->hash = mech_to_hash(js->auth_mech->name);
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
383 data->password = prepped_pass;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
384
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
385 #ifdef CHANNEL_BINDING
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
386 if (strstr(js->auth_mech_name, "-PLUS"))
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
387 data->channel_binding = TRUE;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
388 #endif
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
389 cnonce = ((guint64)g_random_int() << 32) | g_random_int();
29094
40a46992c728 jabber: Interop with Prosody (via Tobias' code). Hooray!
Paul Aurich <paul@darkrain42.org>
parents: 29093
diff changeset
390 data->cnonce = purple_base64_encode((guchar *)&cnonce, sizeof(cnonce));
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
391
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
392 data->auth_message = g_string_new(NULL);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
393 g_string_printf(data->auth_message, "n=%s,r=%s",
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
394 prepped_node, data->cnonce);
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
395 g_free(prepped_node);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
396
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
397 data->step = 1;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
398
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
399 reply = xmlnode_new("auth");
29097
cea22db36ffc jabber: Use NS_XMPP_SASL
Paul Aurich <paul@darkrain42.org>
parents: 29094
diff changeset
400 xmlnode_set_namespace(reply, NS_XMPP_SASL);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
401 xmlnode_set_attrib(reply, "mechanism", js->auth_mech->name);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
402
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
403 /* TODO: Channel binding */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
404 dec_out = g_strdup_printf("%c,,%s", 'n', data->auth_message->str);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
405 enc_out = purple_base64_encode((guchar *)dec_out, strlen(dec_out));
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
406 purple_debug_misc("jabber", "initial SCRAM message '%s'\n", dec_out);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
407
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
408 xmlnode_insert_data(reply, enc_out, -1);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
409
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
410 g_free(enc_out);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
411 g_free(dec_out);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
412
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
413 *out = reply;
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
414 return JABBER_SASL_STATE_CONTINUE;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
415 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
416
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
417 static JabberSaslState
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
418 scram_handle_challenge(JabberStream *js, xmlnode *challenge, xmlnode **out, char **error)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
419 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
420 JabberScramData *data = js->auth_mech_data;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
421 xmlnode *reply;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
422 gchar *enc_in, *dec_in;
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
423 gchar *enc_out = NULL, *dec_out = NULL;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
424 gsize len;
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
425 JabberSaslState state = JABBER_SASL_STATE_FAIL;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
426
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
427 enc_in = xmlnode_get_data(challenge);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
428 if (!enc_in || *enc_in == '\0') {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
429 reply = xmlnode_new("abort");
29097
cea22db36ffc jabber: Use NS_XMPP_SASL
Paul Aurich <paul@darkrain42.org>
parents: 29094
diff changeset
430 xmlnode_set_namespace(reply, NS_XMPP_SASL);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
431 data->step = -1;
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
432 *error = g_strdup(_("Invalid challenge from server"));
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
433 goto out;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
434 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
435
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
436 dec_in = (gchar *)purple_base64_decode(enc_in, &len);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
437 g_free(enc_in);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
438 if (!dec_in || len != strlen(dec_in)) {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
439 /* Danger afoot; SCRAM shouldn't contain NUL bytes */
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
440 reply = xmlnode_new("abort");
29097
cea22db36ffc jabber: Use NS_XMPP_SASL
Paul Aurich <paul@darkrain42.org>
parents: 29094
diff changeset
441 xmlnode_set_namespace(reply, NS_XMPP_SASL);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
442 data->step = -1;
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
443 *error = g_strdup(_("Malicious challenge from server"));
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
444 goto out;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
445 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
446
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
447 purple_debug_misc("jabber", "decoded challenge: %s\n", dec_in);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
448
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
449 if (!jabber_scram_feed_parser(data, dec_in, &dec_out)) {
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
450 reply = xmlnode_new("abort");
29097
cea22db36ffc jabber: Use NS_XMPP_SASL
Paul Aurich <paul@darkrain42.org>
parents: 29094
diff changeset
451 xmlnode_set_namespace(reply, NS_XMPP_SASL);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
452 data->step = -1;
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
453 *error = g_strdup(_("Invalid challenge from server"));
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
454 goto out;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
455 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
456
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
457 data->step += 1;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
458
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
459 reply = xmlnode_new("response");
29097
cea22db36ffc jabber: Use NS_XMPP_SASL
Paul Aurich <paul@darkrain42.org>
parents: 29094
diff changeset
460 xmlnode_set_namespace(reply, NS_XMPP_SASL);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
461
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
462 purple_debug_misc("jabber", "decoded response: %s\n", dec_out ? dec_out : "(null)");
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
463 if (dec_out) {
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
464 enc_out = purple_base64_encode((guchar *)dec_out, strlen(dec_out));
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
465 xmlnode_insert_data(reply, enc_out, -1);
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
466 }
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
467
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
468 state = JABBER_SASL_STATE_CONTINUE;
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
469
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
470 out:
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
471 g_free(enc_out);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
472 g_free(dec_out);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
473
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
474 *out = reply;
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
475 return state;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
476 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
477
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
478 static JabberSaslState
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
479 scram_handle_success(JabberStream *js, xmlnode *packet, char **error)
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
480 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
481 JabberScramData *data = js->auth_mech_data;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
482 char *enc_in, *dec_in;
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
483 char *dec_out = NULL;
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
484 gsize len;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
485
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
486 enc_in = xmlnode_get_data(packet);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
487 g_return_val_if_fail(enc_in != NULL && *enc_in != '\0', FALSE);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
488
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
489 if (data->step == 3)
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
490 return JABBER_SASL_STATE_OK;
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
491
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
492 if (data->step != 2) {
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
493 *error = g_strdup(_("Unexpected response from server"));
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
494 return JABBER_SASL_STATE_FAIL;
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
495 }
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
496
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
497 dec_in = (gchar *)purple_base64_decode(enc_in, &len);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
498 g_free(enc_in);
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
499 if (!dec_in || len != strlen(dec_in)) {
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
500 /* Danger afoot; SCRAM shouldn't contain NUL bytes */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
501 g_free(dec_in);
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
502 *error = g_strdup(_("Invalid challenge from server"));
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
503 return JABBER_SASL_STATE_FAIL;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
504 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
505
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
506 purple_debug_misc("jabber", "decoded success: %s\n", dec_in);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
507
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
508 if (!jabber_scram_feed_parser(data, dec_in, &dec_out) || dec_out != NULL) {
29091
b0fb53868142 jabber: Handle the case where the server success-with-data is sent as a challenge/response pair.
Paul Aurich <paul@darkrain42.org>
parents: 29089
diff changeset
509 g_free(dec_out);
29136
b94fd073187c jabber: Fix that leak I mentioned (and fix a mistake where error/response weren't NULL-initialized)
Paul Aurich <paul@darkrain42.org>
parents: 29134
diff changeset
510 *error = g_strdup(_("Invalid challenge from server"));
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
511 return JABBER_SASL_STATE_FAIL;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
512 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
513
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
514 /* Hooray */
29107
4f45aae3ace1 Let's try a more complex set of return states / values for auth mechs.
Paul Aurich <paul@darkrain42.org>
parents: 29104
diff changeset
515 return JABBER_SASL_STATE_OK;
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
516 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
517
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
518 void jabber_scram_data_destroy(JabberScramData *data)
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
519 {
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
520 g_free(data->cnonce);
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
521 if (data->auth_message)
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
522 g_string_free(data->auth_message, TRUE);
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
523 if (data->client_proof)
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
524 g_string_free(data->client_proof, TRUE);
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
525 if (data->server_signature)
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
526 g_string_free(data->server_signature, TRUE);
29099
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
527 if (data->password) {
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
528 memset(data->password, 0, strlen(data->password));
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
529 g_free(data->password);
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
530 }
464d022d7d6e jabber: Add SASLprep and the username substitution called for in draft-ietf-sasl-scram-10 5.1.
Paul Aurich <paul@darkrain42.org>
parents: 29097
diff changeset
531
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
532 g_free(data);
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
533 }
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
534
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
535 static void scram_dispose(JabberStream *js)
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
536 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
537 if (js->auth_mech_data) {
29093
65a34cce02e3 jabber: Fix up the remaining issues and add a test case that interoperates with gsasl. Woot.
Paul Aurich <paul@darkrain42.org>
parents: 29091
diff changeset
538 jabber_scram_data_destroy(js->auth_mech_data);
29089
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
539 js->auth_mech_data = NULL;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
540 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
541 }
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
542
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
543 static JabberSaslMech scram_sha1_mech = {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
544 50, /* priority */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
545 "SCRAM-SHA-1", /* name */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
546 scram_start,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
547 scram_handle_challenge,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
548 scram_handle_success,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
549 NULL, /* handle_failure */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
550 scram_dispose
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
551 };
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
552
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
553 #ifdef CHANNEL_BINDING
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
554 /* With channel binding */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
555 static JabberSaslMech scram_sha1_plus_mech = {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
556 scram_sha1_mech.priority + 1, /* priority */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
557 "SCRAM-SHA-1-PLUS", /* name */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
558 scram_start,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
559 scram_handle_challenge,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
560 scram_handle_success,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
561 NULL, /* handle_failure */
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
562 scram_dispose
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
563 };
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
564 #endif
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
565
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
566 JabberSaslMech **jabber_auth_get_scram_mechs(gint *count)
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
567 {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
568 static JabberSaslMech *mechs[] = {
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
569 &scram_sha1_mech,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
570 #ifdef CHANNEL_BINDING
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
571 &scram_sha1_plus_mech,
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
572 #endif
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
573 };
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
574
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
575 *count = G_N_ELEMENTS(mechs);
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
576 return mechs;
c1d41b7484ff jabber: Complete (though untested) SCRAM implementation.
Paul Aurich <paul@darkrain42.org>
parents: 29088
diff changeset
577 }