From b60ff61b754ab9d8a72c0eb9df6ec305d3686564 Mon Sep 17 00:00:00 2001 From: Tim Ruehsen Date: Mon, 3 Sep 2012 15:02:41 +0200 Subject: [PATCH] Added support for MD5-sess authentication --- NEWS | 2 ++ src/ChangeLog | 7 +++++++ src/http.c | 55 ++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 0a4efd7a..93a74f31 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ Please send GNU Wget bug reports to . ** Support shorthand URLs in an input file. ** Fix -c with servers that don't specify a content-length. + +** Add support for MD5-SESS * Changes in Wget 1.14 diff --git a/src/ChangeLog b/src/ChangeLog index 7673778b..0755541d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,4 +1,11 @@ +2012-09-03 Tim Ruehsen + + * http.c (digest_authentication_encode): Add support for RFC 2617 + MD5-sess authentication algorithm. + Feature request and testing by: Avinash + 2012-11-14 Ángel González + * warc.c (warc_sha1_stream_with_payload): Fix compilation under gcc -std=c89. diff --git a/src/http.c b/src/http.c index 58884748..fdb0d7e4 100644 --- a/src/http.c +++ b/src/http.c @@ -3662,7 +3662,7 @@ digest_authentication_encode (const char *au, const char *user, const char *passwd, const char *method, const char *path) { - static char *realm, *opaque, *nonce, *qop; + static char *realm, *opaque, *nonce, *qop, *algorithm; static struct { const char *name; char **variable; @@ -3670,15 +3670,17 @@ digest_authentication_encode (const char *au, const char *user, { "realm", &realm }, { "opaque", &opaque }, { "nonce", &nonce }, - { "qop", &qop } + { "qop", &qop }, + { "algorithm", &algorithm } }; char cnonce[16] = ""; char *res; + int res_len; size_t res_size; param_token name, value; - realm = opaque = nonce = qop = NULL; + realm = opaque = nonce = qop = algorithm = NULL; au += 6; /* skip over `Digest' */ while (extract_param (&au, &name, &value, ',')) @@ -3701,12 +3703,19 @@ digest_authentication_encode (const char *au, const char *user, user = NULL; /* force freeing mem and return */ } + if (algorithm != NULL && strcmp (algorithm,"MD5") && strcmp (algorithm,"MD5-sess")) + { + logprintf (LOG_NOTQUIET, _("Unsupported algorithm '%s'.\n"), algorithm); + user = NULL; /* force freeing mem and return */ + } + if (!realm || !nonce || !user || !passwd || !path || !method) { xfree_null (realm); xfree_null (opaque); xfree_null (nonce); xfree_null (qop); + xfree_null (algorithm); return NULL; } @@ -3725,8 +3734,26 @@ digest_authentication_encode (const char *au, const char *user, md5_process_bytes ((unsigned char *)":", 1, &ctx); md5_process_bytes ((unsigned char *)passwd, strlen (passwd), &ctx); md5_finish_ctx (&ctx, hash); + dump_hash (a1buf, hash); + if (! strcmp (algorithm, "MD5-sess")) + { + /* A1BUF = H( H(user ":" realm ":" password) ":" nonce ":" cnonce ) */ + snprintf (cnonce, sizeof (cnonce), "%08x", random_number(INT_MAX)); + + md5_init_ctx (&ctx); + // md5_process_bytes (hash, MD5_DIGEST_SIZE, &ctx); + md5_process_bytes (a1buf, MD5_DIGEST_SIZE * 2, &ctx); + md5_process_bytes ((unsigned char *)":", 1, &ctx); + md5_process_bytes ((unsigned char *)nonce, strlen (nonce), &ctx); + md5_process_bytes ((unsigned char *)":", 1, &ctx); + md5_process_bytes ((unsigned char *)cnonce, strlen (cnonce), &ctx); + md5_finish_ctx (&ctx, hash); + + dump_hash (a1buf, hash); + } + /* A2BUF = H(method ":" path) */ md5_init_ctx (&ctx); md5_process_bytes ((unsigned char *)method, strlen (method), &ctx); @@ -3735,11 +3762,12 @@ digest_authentication_encode (const char *au, const char *user, md5_finish_ctx (&ctx, hash); dump_hash (a2buf, hash); - if (!strcmp(qop,"auth")) + if (!strcmp(qop, "auth") || !strcmp (qop, "auth-int")) { /* RFC 2617 Digest Access Authentication */ /* generate random hex string */ - snprintf(cnonce, sizeof(cnonce), "%08x", random_number(INT_MAX)); + if (!*cnonce) + snprintf(cnonce, sizeof(cnonce), "%08x", random_number(INT_MAX)); /* RESPONSE_DIGEST = H(A1BUF ":" nonce ":" noncecount ":" clientnonce ":" qop ": " A2BUF) */ md5_init_ctx (&ctx); @@ -3772,20 +3800,21 @@ digest_authentication_encode (const char *au, const char *user, dump_hash (response_digest, hash); res_size = strlen (user) - + strlen (user) + strlen (realm) + strlen (nonce) + strlen (path) + 2 * MD5_DIGEST_SIZE /*strlen (response_digest)*/ + (opaque ? strlen (opaque) : 0) + + (algorithm ? strlen (algorithm) : 0) + (qop ? 128: 0) + + strlen (cnonce) + 128; res = xmalloc (res_size); if (!strcmp(qop,"auth")) { - snprintf (res, res_size, "Digest "\ + res_len = snprintf (res, res_size, "Digest "\ "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\""\ ", qop=auth, nc=00000001, cnonce=\"%s\"", user, realm, nonce, path, response_digest, cnonce); @@ -3793,17 +3822,19 @@ digest_authentication_encode (const char *au, const char *user, } else { - snprintf (res, res_size, "Digest "\ + res_len = snprintf (res, res_size, "Digest "\ "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"", user, realm, nonce, path, response_digest); } if (opaque) { - char *p = res + strlen (res); - strcat (p, ", opaque=\""); - strcat (p, opaque); - strcat (p, "\""); + res_len += snprintf(res + res_len, res_size - res_len, ", opaque=\"%s\"", opaque); + } + + if (algorithm) + { + snprintf(res + res_len, res_size - res_len, ", algorithm=\"%s\"", algorithm); } } return res;