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++;
while ((*t != *s) && (*t != '\0'))
t++;
value = _make_string(ctx, (char *)s+1, (t-s-1));
if (*t == *s) {
value = _make_string(ctx, (char *)s+1, (t-s-2));
s = t + 1;
} else {
value = _make_string(ctx, (char *)s+1, (t-s-1));
s = t;
}
/* 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);
if (value == NULL) {
xmpp_error(ctx, "SASL", "couldn't retrieve value for '%s'", key);
value = "\"\"";
value = "";
}
if (quote) {
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) {
hash_t *table;
char *result = NULL;
char *node, *domain;
char *node, *domain, *realm;
char *value;
unsigned char *A1, *A2; /* MD5 hashed versions */
char *response;
int rlen;
struct MD5Context MD5;
unsigned char digest[16];
unsigned char digest[16], HA1[16], HA2[16];
char hex[32];
/* 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),
A1 = MD5( node ':' domain ':' password ) ':' nonce ':' cnonce
A1 = MD5( node ':' realm ':' password ) ':' nonce ':' cnonce
A2 = "AUTHENTICATE" ':' "xmpp/" domain
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);
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 */
hash_add(table, "username", xmpp_strdup(ctx, node));
/* TODO: generate a random cnonce */
@@ -266,17 +272,19 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
/* generate response */
/* construct MD5(A1) */
/* construct MD5(node : realm : password) */
MD5Init(&MD5);
MD5Update(&MD5, (unsigned char *)node, strlen(node));
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 *)password, strlen(password));
MD5Final(digest, &MD5);
/* digest now contains the first field of A1 */
MD5Init(&MD5);
MD5Update(&MD5, (unsigned char *)digest, 16);
MD5Update(&MD5, digest, 16);
MD5Update(&MD5, (unsigned char *)":", 1);
value = hash_get(table, "nonce");
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));
MD5Final(digest, &MD5);
A1 = xmpp_alloc(ctx, 16);
memcpy(A1, digest, 16);
/* now digest is MD5(A1) */
memcpy(HA1, digest, 16);
/* construct MD5(A2) */
MD5Init(&MD5);
MD5Update(&MD5, (unsigned char *)"AUTHENTICATE:", 13);
value = hash_get(table, "digest-uri");
MD5Update(&MD5, (unsigned char *)value, strlen(value));
if (strcmp(hash_get(table, "qop"), "auth") != 0) {
MD5Update(&MD5, (unsigned char *)":00000000000000000000000000000000",
33);
}
MD5Final(digest, &MD5);
A2 = xmpp_alloc(ctx, 16);
memcpy(A2, digest, 16);
memcpy(HA2, digest, 16);
/* construct response */
MD5Init(&MD5);
_digest_to_hex((char *)A1, hex);
_digest_to_hex((char *)HA1, hex);
MD5Update(&MD5, (unsigned char *)hex, 32);
MD5Update(&MD5, (unsigned char *)":", 1);
value = hash_get(table, "nonce");
MD5Update(&MD5, (unsigned char *)value, strlen(value));
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);
value = hash_get(table, "cnonce");
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");
MD5Update(&MD5, (unsigned char *)value, strlen(value));
MD5Update(&MD5, (unsigned char *)":", 1);
_digest_to_hex((char *)A2, hex);
_digest_to_hex((char *)HA2, hex);
MD5Update(&MD5, (unsigned char *)hex, 32);
MD5Final(digest, &MD5);
@@ -324,9 +336,6 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
response[32] = '\0';
hash_add(table, "response", response);
xmpp_free(ctx, A1);
xmpp_free(ctx, A2);
/* construct reply */
result = NULL;
rlen = 0;