ronald 99/12/08 21:21:02
Modified: src CHANGES src/modules/experimental mod_auth_digest.c Log: mod_auth_digest fixes: - better comparing of request-uri with uri parameter in Authorization header - added a check for a MUST condition in the spec - fixed SEGV Revision Changes Path 1.1475 +7 -0 apache-1.3/src/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.1474 retrieving revision 1.1475 diff -u -r1.1474 -r1.1475 --- CHANGES 1999/12/08 23:01:46 1.1474 +++ CHANGES 1999/12/09 05:20:52 1.1475 @@ -1,5 +1,12 @@ Changes with Apache 1.3.10 + *) more fixes to mod_auth_digest: + - better comparing of request-uri with uri parameter in Authorization + header + - added a check for a MUST condition in the spec + - fixed SEGV + [Ronald Tschalär] + *) mod_proxy now works on TPF. [Joe Moenich <[EMAIL PROTECTED]>] 1.12 +81 -28 apache-1.3/src/modules/experimental/mod_auth_digest.c Index: mod_auth_digest.c =================================================================== RCS file: /home/cvs/apache-1.3/src/modules/experimental/mod_auth_digest.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- mod_auth_digest.c 1999/11/28 12:41:59 1.11 +++ mod_auth_digest.c 1999/12/09 05:21:00 1.12 @@ -212,7 +212,8 @@ /* the following fields are not (directly) from the header */ time_t nonce_time; enum hdr_sts auth_hdr_sts; - uri_components *request_uri; + const char *raw_request_uri; + uri_components *psd_request_uri; int needed_auth; client_entry *client; } digest_header_rec; @@ -498,9 +499,9 @@ * and directives outside a virtual host section) */ ap_SHA1Init(&conf->nonce_ctx); + ap_SHA1Update_binary(&conf->nonce_ctx, secret, sizeof(secret)); ap_SHA1Update_binary(&conf->nonce_ctx, (const unsigned char *) realm, strlen(realm)); - ap_SHA1Update_binary(&conf->nonce_ctx, secret, sizeof(secret)); return DECLINE_CMD; } @@ -911,7 +912,8 @@ } if (!resp->username || !resp->realm || !resp->nonce || !resp->uri - || !resp->digest) { + || !resp->digest + || (resp->message_qop && (!resp->cnonce || !resp->nonce_count))) { resp->auth_hdr_sts = INVALID; return !OK; } @@ -944,7 +946,8 @@ return DECLINED; resp = ap_pcalloc(r->pool, sizeof(digest_header_rec)); - resp->request_uri = &r->parsed_uri; + resp->raw_request_uri = r->unparsed_uri; + resp->psd_request_uri = &r->parsed_uri; resp->needed_auth = 0; ap_set_module_config(r->request_config, &digest_auth_module, resp); @@ -1273,7 +1276,7 @@ domain = conf->uri_list; else { /* They didn't specify any domain, so let's guess at it */ - domain = guess_domain(r->pool, resp->request_uri->path, r->filename, + domain = guess_domain(r->pool, resp->psd_request_uri->path, r->filename, conf->dir_name); if (domain[0] == '/' && domain[1] == '\0') domain = NULL; /* "/" is the default, so no need to send it */ @@ -1460,6 +1463,36 @@ } +static void copy_uri_components(uri_components *dst, uri_components *src, + request_rec *r) { + if (src->scheme && src->scheme[0] != '\0') + dst->scheme = src->scheme; + else + dst->scheme = (char *) "http"; + + if (src->hostname && src->hostname[0] != '\0') { + dst->hostname = ap_pstrdup(r->pool, src->hostname); + ap_unescape_url(dst->hostname); + } + else + dst->hostname = (char *) ap_get_server_name(r); + + if (src->port_str && src->port_str[0] != '\0') + dst->port = src->port; + else + dst->port = ap_get_server_port(r); + + if (src->path && src->path[0] != '\0') { + dst->path = ap_pstrdup(r->pool, src->path); + ap_unescape_url(dst->path); + } + + if (src->query && src->query[0] != '\0') { + dst->query = ap_pstrdup(r->pool, src->query); + ap_unescape_url(dst->query); + } +} + /* These functions return 0 if client is OK, and proper error status * if not... either AUTH_REQUIRED, if we made a check, and it failed, or * SERVER_ERROR, if things are so totally confused that we couldn't @@ -1521,8 +1554,9 @@ "`%s': %s", resp->scheme, r->uri); else if (resp->auth_hdr_sts == INVALID) ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Digest: missing user, realm, nonce, uri, or digest " - "in authorization header: %s", r->uri); + "Digest: missing user, realm, nonce, uri, digest, " + "cnonce, or nonce_count in authorization header: %s", + r->uri); /* else (resp->auth_hdr_sts == NO_HEADER) */ note_digest_auth_failure(r, conf, resp, 0); return AUTH_REQUIRED; @@ -1534,10 +1568,13 @@ /* check the auth attributes */ - if (strcmp(resp->uri, resp->request_uri->path)) { - uri_components *r_uri = resp->request_uri, d_uri; - int port; + if (strcmp(resp->uri, resp->raw_request_uri)) { + /* Hmm, the simple match didn't work (probably a proxy modified the + * request-uri), so lets do a more sophisticated match + */ + uri_components r_uri, d_uri; + copy_uri_components(&r_uri, resp->psd_request_uri, r); if (ap_parse_uri_components(r->pool, resp->uri, &d_uri) != HTTP_OK) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Digest: invalid uri <%s> in Authorization header", @@ -1551,24 +1588,40 @@ ap_unescape_url(d_uri.path); if (d_uri.query) ap_unescape_url(d_uri.query); - if (r_uri->query) - ap_unescape_url(r_uri->query); - port = ap_get_server_port(r); - - if ((d_uri.hostname && d_uri.hostname[0] != '\0' - && strcasecmp(d_uri.hostname, ap_get_server_name(r))) - || (d_uri.port_str && d_uri.port != port) + + if (r->method_number == M_CONNECT) { + if (strcmp(resp->uri, r_uri.hostinfo)) { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, + "Digest: uri mismatch - <%s> does not match " + "request-uri <%s>", resp->uri, r_uri.hostinfo); + return BAD_REQUEST; + } + } + else if ( + /* check hostname matches, if present */ + (d_uri.hostname && d_uri.hostname[0] != '\0' + && strcasecmp(d_uri.hostname, r_uri.hostname)) + /* check port matches, if present */ + || (d_uri.port_str && d_uri.port != r_uri.port) + /* check that server-port is default port if no port present */ || (d_uri.hostname && d_uri.hostname[0] != '\0' - && !d_uri.port_str && port != ap_default_port(r)) - || !d_uri.path || strcmp(d_uri.path, r_uri->path) - || (d_uri.query != r_uri->query - && (!d_uri.query || !r_uri->query - || strcmp(d_uri.query, r_uri->query))) + && !d_uri.port_str && r_uri.port != ap_default_port(r)) + /* check that path matches */ + || (d_uri.path != r_uri.path + /* either exact match */ + && (!d_uri.path || !r_uri.path + || strcmp(d_uri.path, r_uri.path)) + /* or '*' matches empty path in scheme://host */ + && !(d_uri.path && !r_uri.path && resp->psd_request_uri->hostname + && d_uri.path[0] == '*' && d_uri.path[1] == '\0')) + /* check that query matches */ + || (d_uri.query != r_uri.query + && (!d_uri.query || !r_uri.query + || strcmp(d_uri.query, r_uri.query))) ) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Digest: uri mismatch - <%s> does not match " - "request-uri <%s>", resp->uri, - ap_unparse_uri_components(r->pool, r_uri, 0)); + "request-uri <%s>", resp->uri, resp->raw_request_uri); return BAD_REQUEST; } } @@ -1831,9 +1884,8 @@ */ char *entity_info = ap_md5(r->pool, - (unsigned char *) ap_pstrcat(r->pool, - ap_unparse_uri_components(r->pool, - resp->request_uri, 0), ":", + (unsigned char *) ap_pstrcat(r->pool, resp->raw_request_uri, + ":", r->content_type ? r->content_type : ap_default_type(r), ":", hdr(r->headers_out, "Content-Length"), ":", r->content_encoding ? r->content_encoding : "", ":", @@ -1864,7 +1916,8 @@ gen_nonce(r->pool, r->request_time, resp->opaque, r->server, conf), "\"", NULL); - resp->client->nonce_count = 0; + if (resp->client) + resp->client->nonce_count = 0; } } else if (conf->nonce_lifetime == 0 && resp->client) {