Fix #3: broken DIGEST-MD5 auth with ejabberd.

This commit is contained in:
Jack Moffitt
2008-08-22 16:33:30 +00:00
parent 5856ecbacc
commit 661d6571ba

View File

@@ -128,11 +128,10 @@ static hash_t *_parse_digest_challenge(xmpp_ctx_t *ctx, const char *msg)
t++; t++;
while ((*t != *s) && (*t != '\0')) while ((*t != *s) && (*t != '\0'))
t++; t++;
value = _make_string(ctx, (char *)s+1, (t-s-1));
if (*t == *s) { if (*t == *s) {
value = _make_string(ctx, (char *)s+1, (t-s-2));
s = t + 1; s = t + 1;
} else { } else {
value = _make_string(ctx, (char *)s+1, (t-s-1));
s = t; s = t;
} }
/* otherwise, accumulate a value ending in ',' or '\0' */ /* otherwise, accumulate a value ending in ',' or '\0' */
@@ -189,7 +188,7 @@ static char *_add_key(xmpp_ctx_t *ctx, hash_t *table, const char *key,
value = hash_get(table, key); value = hash_get(table, key);
if (value == NULL) { if (value == NULL) {
xmpp_error(ctx, "SASL", "couldn't retrieve value for '%s'", key); xmpp_error(ctx, "SASL", "couldn't retrieve value for '%s'", key);
value = "\"\""; value = "";
} }
if (quote) { if (quote) {
qvalue = _make_quoted(ctx, value); qvalue = _make_quoted(ctx, value);
@@ -222,13 +221,12 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
const char *jid, const char *password) { const char *jid, const char *password) {
hash_t *table; hash_t *table;
char *result = NULL; char *result = NULL;
char *node, *domain; char *node, *domain, *realm;
char *value; char *value;
unsigned char *A1, *A2; /* MD5 hashed versions */
char *response; char *response;
int rlen; int rlen;
struct MD5Context MD5; struct MD5Context MD5;
unsigned char digest[16]; unsigned char digest[16], HA1[16], HA2[16];
char hex[32]; char hex[32];
/* our digest response is /* our digest response is
@@ -237,7 +235,7 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
)) ))
where KD(k, s) = MD5(k ':' s), where KD(k, s) = MD5(k ':' s),
A1 = MD5( node ':' domain ':' password ) ':' nonce ':' cnonce A1 = MD5( node ':' realm ':' password ) ':' nonce ':' cnonce
A2 = "AUTHENTICATE" ':' "xmpp/" domain A2 = "AUTHENTICATE" ':' "xmpp/" domain
If there is an authzid it is ':'-appended to A1 */ If there is an authzid it is ':'-appended to A1 */
@@ -252,6 +250,14 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
node = xmpp_jid_node(ctx, jid); node = xmpp_jid_node(ctx, jid);
domain = xmpp_jid_domain(ctx, jid); domain = xmpp_jid_domain(ctx, jid);
/* generate default realm of domain if one didn't come from the
server */
realm = hash_get(table, "realm");
if (realm == NULL || strlen(realm) == 0) {
hash_add(table, "realm", xmpp_strdup(ctx, domain));
realm = hash_get(table, "realm");
}
/* add our response fields */ /* add our response fields */
hash_add(table, "username", xmpp_strdup(ctx, node)); hash_add(table, "username", xmpp_strdup(ctx, node));
/* TODO: generate a random cnonce */ /* TODO: generate a random cnonce */
@@ -266,17 +272,19 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
/* generate response */ /* generate response */
/* construct MD5(A1) */ /* construct MD5(node : realm : password) */
MD5Init(&MD5); MD5Init(&MD5);
MD5Update(&MD5, (unsigned char *)node, strlen(node)); MD5Update(&MD5, (unsigned char *)node, strlen(node));
MD5Update(&MD5, (unsigned char *)":", 1); MD5Update(&MD5, (unsigned char *)":", 1);
MD5Update(&MD5, (unsigned char *)domain, strlen(domain)); MD5Update(&MD5, (unsigned char *)realm, strlen(realm));
MD5Update(&MD5, (unsigned char *)":", 1); MD5Update(&MD5, (unsigned char *)":", 1);
MD5Update(&MD5, (unsigned char *)password, strlen(password)); MD5Update(&MD5, (unsigned char *)password, strlen(password));
MD5Final(digest, &MD5); MD5Final(digest, &MD5);
/* digest now contains the first field of A1 */
MD5Init(&MD5); MD5Init(&MD5);
MD5Update(&MD5, (unsigned char *)digest, 16); MD5Update(&MD5, digest, 16);
MD5Update(&MD5, (unsigned char *)":", 1); MD5Update(&MD5, (unsigned char *)":", 1);
value = hash_get(table, "nonce"); value = hash_get(table, "nonce");
MD5Update(&MD5, (unsigned char *)value, strlen(value)); MD5Update(&MD5, (unsigned char *)value, strlen(value));
@@ -285,28 +293,32 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
MD5Update(&MD5, (unsigned char *)value, strlen(value)); MD5Update(&MD5, (unsigned char *)value, strlen(value));
MD5Final(digest, &MD5); MD5Final(digest, &MD5);
A1 = xmpp_alloc(ctx, 16); /* now digest is MD5(A1) */
memcpy(A1, digest, 16); memcpy(HA1, digest, 16);
/* construct MD5(A2) */ /* construct MD5(A2) */
MD5Init(&MD5); MD5Init(&MD5);
MD5Update(&MD5, (unsigned char *)"AUTHENTICATE:", 13); MD5Update(&MD5, (unsigned char *)"AUTHENTICATE:", 13);
value = hash_get(table, "digest-uri"); value = hash_get(table, "digest-uri");
MD5Update(&MD5, (unsigned char *)value, strlen(value)); MD5Update(&MD5, (unsigned char *)value, strlen(value));
if (strcmp(hash_get(table, "qop"), "auth") != 0) {
MD5Update(&MD5, (unsigned char *)":00000000000000000000000000000000",
33);
}
MD5Final(digest, &MD5); MD5Final(digest, &MD5);
A2 = xmpp_alloc(ctx, 16); memcpy(HA2, digest, 16);
memcpy(A2, digest, 16);
/* construct response */ /* construct response */
MD5Init(&MD5); MD5Init(&MD5);
_digest_to_hex((char *)A1, hex); _digest_to_hex((char *)HA1, hex);
MD5Update(&MD5, (unsigned char *)hex, 32); MD5Update(&MD5, (unsigned char *)hex, 32);
MD5Update(&MD5, (unsigned char *)":", 1); MD5Update(&MD5, (unsigned char *)":", 1);
value = hash_get(table, "nonce"); value = hash_get(table, "nonce");
MD5Update(&MD5, (unsigned char *)value, strlen(value)); MD5Update(&MD5, (unsigned char *)value, strlen(value));
MD5Update(&MD5, (unsigned char *)":", 1); MD5Update(&MD5, (unsigned char *)":", 1);
MD5Update(&MD5, (unsigned char *)"00000001", 8); value = hash_get(table, "nc");
MD5Update(&MD5, (unsigned char *)value, strlen(value));
MD5Update(&MD5, (unsigned char *)":", 1); MD5Update(&MD5, (unsigned char *)":", 1);
value = hash_get(table, "cnonce"); value = hash_get(table, "cnonce");
MD5Update(&MD5, (unsigned char *)value, strlen(value)); MD5Update(&MD5, (unsigned char *)value, strlen(value));
@@ -314,7 +326,7 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
value = hash_get(table, "qop"); value = hash_get(table, "qop");
MD5Update(&MD5, (unsigned char *)value, strlen(value)); MD5Update(&MD5, (unsigned char *)value, strlen(value));
MD5Update(&MD5, (unsigned char *)":", 1); MD5Update(&MD5, (unsigned char *)":", 1);
_digest_to_hex((char *)A2, hex); _digest_to_hex((char *)HA2, hex);
MD5Update(&MD5, (unsigned char *)hex, 32); MD5Update(&MD5, (unsigned char *)hex, 32);
MD5Final(digest, &MD5); MD5Final(digest, &MD5);
@@ -324,9 +336,6 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
response[32] = '\0'; response[32] = '\0';
hash_add(table, "response", response); hash_add(table, "response", response);
xmpp_free(ctx, A1);
xmpp_free(ctx, A2);
/* construct reply */ /* construct reply */
result = NULL; result = NULL;
rlen = 0; rlen = 0;