summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2007-01-06 14:27:18 +0000
committerjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2007-01-06 14:27:18 +0000
commit3242cbb80711ac5083a00f838396995e81678d93 (patch)
tree2a6308556d72ea8fb55fb734954d67554496de8e
parent6bdfd6d6608ea6a5c339a0529938ed68a0f7f450 (diff)
downloadneon-3242cbb80711ac5083a00f838396995e81678d93.tar.gz
* src/ne_auth.c (digest_challenge): Fix to fail correctly for invalid
case where stale=true is given with an initial challenge; fix to not leak sess->nonce for a valid stale challenge. * test/auth.c (struct digest_parms): Add stale field, enum value. (make_digest_header): Send stale=true as appropriate. (serve_digest): Adjust to serve challenges with stale=true. (digest): Add test for stale=true handling. (digest_failures): Add test for error stale=true failure case. git-svn-id: http://svn.webdav.org/repos/projects/neon/trunk@1129 61a7d7f5-40b7-0310-9c16-bb0ea8cb1845
-rw-r--r--src/ne_auth.c46
-rw-r--r--test/auth.c59
2 files changed, 75 insertions, 30 deletions
diff --git a/src/ne_auth.c b/src/ne_auth.c
index c2ee89f..4e0bb72 100644
--- a/src/ne_auth.c
+++ b/src/ne_auth.c
@@ -1,6 +1,6 @@
/*
HTTP Authentication routines
- Copyright (C) 1999-2006, Joe Orton <joe@manyfish.co.uk>
+ Copyright (C) 1999-2007, Joe Orton <joe@manyfish.co.uk>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -625,25 +625,40 @@ static int digest_challenge(auth_session *sess, int attempt,
challenge_error(errmsg, _("missing parameter in Digest challenge"));
return -1;
}
+ else if (parms->stale && sess->nonce_count == 0) {
+ challenge_error(errmsg, _("initial Digest challenge was stale"));
+ return -1;
+ }
+ else if (parms->stale && (sess->alg != parms->alg
+ || strcmp(sess->realm, parms->realm))) {
+ /* With stale=true the realm and algorithm cannot change since these
+ * require re-hashing H(A1) which defeats the point. */
+ challenge_error(errmsg, _("stale Digest challenge with new algorithm or realm"));
+ return -1;
+ }
if (!parms->stale) {
- /* Forget the old session details */
- clean_session(sess);
+ /* Non-stale challenge: clear session and request credentials. */
+ clean_session(sess);
- sess->realm = ne_strdup(parms->realm);
+ sess->realm = ne_strdup(parms->realm);
+ sess->alg = parms->alg;
+ sess->cnonce = get_cnonce();
- /* Not a stale response: really need user authentication */
- if (get_credentials(sess, errmsg, attempt, parms, password)) {
- /* Failed to get credentials */
- return -1;
- }
+ if (get_credentials(sess, errmsg, attempt, parms, password)) {
+ /* Failed to get credentials */
+ return -1;
+ }
}
- sess->alg = parms->alg;
+ else {
+ /* Stale challenge: accept a new nonce or opa */
+ if (sess->nonce) ne_free(sess->nonce);
+ if (sess->opaque && parms->opaque) ne_free(sess->opaque);
+ }
+
sess->nonce = ne_strdup(parms->nonce);
- sess->cnonce = get_cnonce();
- /* TODO: add domain handling. */
- if (parms->opaque != NULL) {
- sess->opaque = ne_strdup(parms->opaque); /* don't strip the quotes */
+ if (parms->opaque) {
+ sess->opaque = ne_strdup(parms->opaque);
}
if (parms->got_qop) {
@@ -967,8 +982,7 @@ static int verify_digest_response(struct auth_request *req, auth_session *sess,
/* Check for a nextnonce */
if (nextnonce != NULL) {
NE_DEBUG(NE_DBG_HTTPAUTH, "auth: Found nextnonce of [%s].\n", nextnonce);
- if (sess->nonce != NULL)
- ne_free(sess->nonce);
+ ne_free(sess->nonce);
sess->nonce = ne_strdup(nextnonce);
sess->nonce_count = 0;
}
diff --git a/test/auth.c b/test/auth.c
index 50dde35..39146e6 100644
--- a/test/auth.c
+++ b/test/auth.c
@@ -375,9 +375,11 @@ struct digest_parms {
int proxy;
int send_nextnonce;
int num_requests;
+ int stale;
enum digest_failure {
fail_not,
fail_bogus_alg,
+ fail_req0_stale,
fail_omit_qop,
fail_omit_realm,
fail_omit_nonce,
@@ -645,6 +647,11 @@ static char *make_digest_header(struct digest_state *state,
ne_buffer_concat(buf, "opaque=\"", parms->opaque, "\", ", NULL);
}
+ if (parms->failure == fail_req0_stale
+ || parms->stale == parms->num_requests) {
+ ne_buffer_concat(buf, "stale='true', ", NULL);
+ }
+
ne_buffer_concat(buf, "nonce=\"", state->nonce, "\"", NULL);
return ne_buffer_finish(buf);
@@ -670,6 +677,11 @@ static int serve_digest(ne_socket *sock, void *userdata)
state.cnonce = state.digest = state.ncval = NULL;
+ parms->num_requests += parms->stale ? 1 : 0;
+
+ NE_DEBUG(NE_DBG_HTTP, ">>>> Response sequence begins, %d requests.\n",
+ parms->num_requests);
+
want_header = parms->proxy ? "Proxy-Authorization" : "Authorization";
digest_hdr = NULL;
got_header = dup_header;
@@ -694,8 +706,19 @@ static int serve_digest(ne_socket *sock, void *userdata)
ONN("no Authorization header sent", digest_hdr == NULL);
CALL(verify_digest_header(&state, parms, digest_hdr));
-
- if (parms->send_ainfo) {
+
+ if (parms->num_requests == parms->stale) {
+ state.nonce = ne_concat("stale-", state.nonce, NULL);
+ state.nc = 1;
+
+ ne_snprintf(resp, sizeof resp,
+ "HTTP/1.1 %d Auth Denied\r\n"
+ "%s\r\n"
+ "Content-Length: 0\r\n" "\r\n",
+ parms->proxy ? 407 : 401,
+ make_digest_header(&state, parms));
+ }
+ else if (parms->send_ainfo) {
char *ai = make_authinfo_header(&state, parms);
ne_snprintf(resp, sizeof resp,
@@ -714,7 +737,7 @@ static int serve_digest(ne_socket *sock, void *userdata)
SEND_STRING(sock, resp);
NE_DEBUG(NE_DBG_HTTP, "Handled request; %d requests remain.\n",
- parms->num_requests);
+ parms->num_requests - 1);
} while (--parms->num_requests);
return OK;
@@ -724,6 +747,8 @@ static int test_digest(struct digest_parms *parms)
{
ne_session *sess;
+ NE_DEBUG(NE_DBG_HTTP, ">>>> Request sequence begins.\n");
+
if (parms->proxy) {
sess = ne_session_create("http", "www.example.com", 80);
ne_session_proxy(sess, "localhost", 7777);
@@ -749,24 +774,27 @@ static int digest(void)
{
struct digest_parms parms[] = {
/* RFC 2617-style */
- { "WallyWorld", "this-is-a-nonce", NULL, 1, 0, 0, 0, 0, 1, fail_not },
- { "WallyWorld", "this-is-also-a-nonce", "opaque-string", 1, 0, 0, 0, 0, 1, fail_not },
+ { "WallyWorld", "this-is-a-nonce", NULL, 1, 0, 0, 0, 0, 1, 0, fail_not },
+ { "WallyWorld", "this-is-also-a-nonce", "opaque-string", 1, 0, 0, 0, 0, 1, 0, fail_not },
/* ... with A-I */
- { "WallyWorld", "nonce-nonce-nonce", "opaque-string", 1, 1, 0, 0, 0, 1, fail_not },
+ { "WallyWorld", "nonce-nonce-nonce", "opaque-string", 1, 1, 0, 0, 0, 1, 0, fail_not },
/* ... with md5-sess. */
- { "WallyWorld", "nonce-nonce-nonce", "opaque-string", 1, 1, 1, 0, 0, 1, fail_not },
+ { "WallyWorld", "nonce-nonce-nonce", "opaque-string", 1, 1, 1, 0, 0, 1, 0, fail_not },
/* many requests, with changing nonces; tests for next-nonce handling bug. */
- { "WallyWorld", "this-is-a-nonce", "opaque-thingy", 1, 1, 0, 0, 1, 20, fail_not },
+ { "WallyWorld", "this-is-a-nonce", "opaque-thingy", 1, 1, 0, 0, 1, 20, 0, fail_not },
+ /* staleness. */
+ { "WallyWorld", "this-is-a-nonce", "opaque-thingy", 1, 1, 0, 0, 0, 3, 2, fail_not },
+
/* RFC 2069-style */
- { "WallyWorld", "lah-di-da-di-dah", NULL, 0, 0, 0, 0, 0, 1, fail_not },
- { "WallyWorld", "fee-fi-fo-fum", "opaque-string", 0, 0, 0, 0, 0, 1, fail_not },
- { "WallyWorld", "fee-fi-fo-fum", "opaque-string", 0, 1, 0, 0, 0, 1, fail_not },
+ { "WallyWorld", "lah-di-da-di-dah", NULL, 0, 0, 0, 0, 0, 1, 0, fail_not },
+ { "WallyWorld", "fee-fi-fo-fum", "opaque-string", 0, 0, 0, 0, 0, 1, 0, fail_not },
+ { "WallyWorld", "fee-fi-fo-fum", "opaque-string", 0, 1, 0, 0, 0, 1, 0, fail_not },
/* Proxy auth */
- { "WallyWorld", "this-is-also-a-nonce", "opaque-string", 1, 1, 0, 0, 0, 1, fail_not },
+ { "WallyWorld", "this-is-also-a-nonce", "opaque-string", 1, 1, 0, 0, 0, 1, 0, fail_not },
/* Proxy + A-I */
- { "WallyWorld", "this-is-also-a-nonce", "opaque-string", 1, 1, 0, 1, 0, 1, fail_not },
+ { "WallyWorld", "this-is-also-a-nonce", "opaque-string", 1, 1, 0, 1, 0, 1, 0, fail_not },
{ NULL }
};
@@ -795,6 +823,7 @@ static int digest_failures(void)
{ fail_ai_omit_digest, "missing parameters" },
{ fail_ai_omit_cnonce, "missing parameters" },
{ fail_bogus_alg, "unknown algorithm" },
+ { fail_req0_stale, "initial Digest challenge was stale" },
{ fail_not, NULL }
};
size_t n;
@@ -808,6 +837,7 @@ static int digest_failures(void)
parms.proxy = 0;
parms.send_nextnonce = 0;
parms.num_requests = 1;
+ parms.stale = 0;
for (n = 0; fails[n].message; n++) {
ne_session *sess = ne_session_create("http", "localhost", 7777);
@@ -829,7 +859,8 @@ static int digest_failures(void)
ne_session_destroy(sess);
- if (fails[n].mode == fail_bogus_alg) {
+ if (fails[n].mode == fail_bogus_alg
+ || fails[n].mode == fail_req0_stale) {
reap_server();
} else {
CALL(await_server());