#include "apr_sha1.h"#include "apr_base64.h"#include "apr_lib.h"#include "apr_time.h"#include "apr_errno.h"#include "apr_global_mutex.h"#include "apr_strings.h"#include "apr_want.h"#include "ap_config.h"#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_request.h"#include "http_log.h"#include "http_protocol.h"#include "apr_uri.h"#include "util_md5.h"#include "apr_shm.h"#include "apr_rmm.h"#include "ap_provider.h"#include "mod_auth.h"Go to the source code of this file.
Classes | |
| struct | digest_config_struct |
| struct | hash_entry |
| struct | hash_table |
| struct | digest_header_struct |
| union | time_union |
Defines | |
| #define | APR_WANT_STRFUNC |
| #define | APR_HAS_SHARED_MEMORY 0 |
| #define | DFLT_ALGORITHM "MD5" |
| #define | DFLT_NONCE_LIFE apr_time_from_sec(300) |
| #define | NEXTNONCE_DELTA apr_time_from_sec(30) |
| #define | NONCE_TIME_LEN (((sizeof(apr_time_t)+2)/3)*4) |
| #define | NONCE_HASH_LEN (2*APR_SHA1_DIGESTSIZE) |
| #define | NONCE_LEN (int )(NONCE_TIME_LEN + NONCE_HASH_LEN) |
| #define | SECRET_LEN 20 |
| #define | DEF_SHMEM_SIZE 1000L |
| #define | DEF_NUM_BUCKETS 15L |
| #define | HASH_DEPTH 5 |
Typedefs | |
| typedef digest_config_struct | digest_config_rec |
| typedef hash_entry | client_entry |
| typedef digest_header_struct | digest_header_rec |
| typedef time_union | time_rec |
Enumerations | |
| enum | hdr_sts { NO_HEADER, NOT_DIGEST, INVALID, VALID } |
Functions | |
| static apr_status_t | cleanup_tables (void *not_used) |
| static apr_status_t | initialize_secret (server_rec *s) |
| static void | log_error_and_cleanup (char *msg, apr_status_t sts, server_rec *s) |
| static int | initialize_module (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) |
| static void | initialize_child (apr_pool_t *p, server_rec *s) |
| static void * | create_digest_dir_config (apr_pool_t *p, char *dir) |
| static const char * | set_realm (cmd_parms *cmd, void *config, const char *realm) |
| static const char * | add_authn_provider (cmd_parms *cmd, void *config, const char *arg) |
| static const char * | set_qop (cmd_parms *cmd, void *config, const char *op) |
| static const char * | set_nonce_lifetime (cmd_parms *cmd, void *config, const char *t) |
| static const char * | set_nonce_format (cmd_parms *cmd, void *config, const char *fmt) |
| static const char * | set_nc_check (cmd_parms *cmd, void *config, int flag) |
| static const char * | set_algorithm (cmd_parms *cmd, void *config, const char *alg) |
| static const char * | set_uri_list (cmd_parms *cmd, void *config, const char *uri) |
| static const char * | set_shmem_size (cmd_parms *cmd, void *config, const char *size_str) |
| static client_entry * | get_client (unsigned long key, const request_rec *r) |
| static long | gc (void) |
| static client_entry * | add_client (unsigned long key, client_entry *info, server_rec *s) |
| static int | get_digest_rec (request_rec *r, digest_header_rec *resp) |
| static int | parse_hdr_and_update_nc (request_rec *r) |
| static void | gen_nonce_hash (char *hash, const char *timestr, const char *opaque, const server_rec *server, const digest_config_rec *conf) |
| static const char * | gen_nonce (apr_pool_t *p, apr_time_t now, const char *opaque, const server_rec *server, const digest_config_rec *conf) |
| static client_entry * | gen_client (const request_rec *r) |
| static const char * | get_userpw_hash (const request_rec *r, const digest_header_rec *resp, const digest_config_rec *conf) |
| static const char * | get_session_HA1 (const request_rec *r, digest_header_rec *resp, const digest_config_rec *conf, int generate) |
| static void | clear_session (const digest_header_rec *resp) |
| static const char * | ltox (apr_pool_t *p, unsigned long num) |
| static void | note_digest_auth_failure (request_rec *r, const digest_config_rec *conf, digest_header_rec *resp, int stale) |
| static authn_status | get_hash (request_rec *r, const char *user, digest_config_rec *conf) |
| static int | check_nc (const request_rec *r, const digest_header_rec *resp, const digest_config_rec *conf) |
| static int | check_nonce (request_rec *r, digest_header_rec *resp, const digest_config_rec *conf) |
| static const char * | old_digest (const request_rec *r, const digest_header_rec *resp, const char *ha1) |
| static const char * | new_digest (const request_rec *r, digest_header_rec *resp, const digest_config_rec *conf) |
| static void | copy_uri_components (apr_uri_t *dst, apr_uri_t *src, request_rec *r) |
| static int | authenticate_digest_user (request_rec *r) |
| static int | add_auth_info (request_rec *r) |
| static void | register_hooks (apr_pool_t *p) |
Variables | |
| static struct hash_table * | client_list |
| static unsigned char | secret [SECRET_LEN] |
| static apr_shm_t * | client_shm = NULL |
| static apr_rmm_t * | client_rmm = NULL |
| static unsigned long * | opaque_cntr |
| static apr_time_t * | otn_counter |
| static apr_global_mutex_t * | client_lock = NULL |
| static apr_global_mutex_t * | opaque_lock = NULL |
| static char | client_lock_name [L_tmpnam] |
| static char | opaque_lock_name [L_tmpnam] |
| static long | shmem_size = DEF_SHMEM_SIZE |
| static long | num_buckets = DEF_NUM_BUCKETS |
| module AP_MODULE_DECLARE_DATA | auth_digest_module |
| static const command_rec | digest_cmds [] |
|
|
Definition at line 87 of file mod_auth_digest.c. Referenced by testshm(). |
|
|
Definition at line 65 of file mod_auth_digest.c. |
|
|
Definition at line 188 of file mod_auth_digest.c. |
|
|
Definition at line 187 of file mod_auth_digest.c. |
|
|
Definition at line 106 of file mod_auth_digest.c. Referenced by create_digest_dir_config(). |
|
|
Definition at line 108 of file mod_auth_digest.c. Referenced by create_digest_dir_config(). |
|
|
Definition at line 189 of file mod_auth_digest.c. Referenced by set_shmem_size(). |
|
|
Definition at line 109 of file mod_auth_digest.c. Referenced by add_auth_info(). |
|
|
Definition at line 113 of file mod_auth_digest.c. Referenced by check_nonce(). |
|
|
Definition at line 114 of file mod_auth_digest.c. Referenced by add_auth_info(), check_nonce(), gen_nonce(), and note_digest_auth_failure(). |
|
|
Definition at line 112 of file mod_auth_digest.c. Referenced by check_nonce(), and gen_nonce(). |
|
|
Definition at line 116 of file mod_auth_digest.c. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Definition at line 141 of file mod_auth_digest.c. 00141 { NO_HEADER, NOT_DIGEST, INVALID, VALID };
|
|
|
Definition at line 1866 of file mod_auth_digest.c. References digest_header_struct::algorithm, ap_get_module_config, APLOG_ERR, APLOG_MARK, apr_rfc822_date(), APR_RFC822_DATE_LEN, auth_digest_module, digest_header_struct::client, digest_header_struct::cnonce, conf, request_rec::content_encoding, request_rec::content_type, digest, gen_nonce(), get_session_HA1(), digest_config_struct::ha1, hdr, request_rec::headers_out, hash_entry::last_nonce, digest_header_struct::message_qop, request_rec::method, digest_header_struct::needed_auth, NEXTNONCE_DELTA, request_rec::no_cache, digest_header_struct::nonce, digest_header_struct::nonce_count, hash_entry::nonce_count, NONCE_LEN, digest_config_struct::nonce_lifetime, digest_header_struct::nonce_time, NULL, OK, digest_header_struct::opaque, request_rec::per_dir_config, request_rec::pool, request_rec::proxyreq, PROXYREQ_PROXY, digest_config_struct::qop_list, digest_header_struct::raw_request_uri, request_rec::request_config, request_rec::request_time, request_rec::server, strcasecmp(), digest_header_struct::uri, and digest_header_struct::username. Referenced by register_hooks(). 01867 { 01868 const digest_config_rec *conf = 01869 (digest_config_rec *) ap_get_module_config(r->per_dir_config, 01870 &auth_digest_module); 01871 digest_header_rec *resp = 01872 (digest_header_rec *) ap_get_module_config(r->request_config, 01873 &auth_digest_module); 01874 const char *ai = NULL, *digest = NULL, *nextnonce = ""; 01875 01876 if (resp == NULL || !resp->needed_auth || conf == NULL) { 01877 return OK; 01878 } 01879 01880 01881 /* rfc-2069 digest 01882 */ 01883 if (resp->message_qop == NULL) { 01884 /* old client, so calc rfc-2069 digest */ 01885 01886 #ifdef SEND_DIGEST 01887 /* most of this totally bogus because the handlers don't set the 01888 * headers until the final handler phase (I wonder why this phase 01889 * is called fixup when there's almost nothing you can fix up...) 01890 * 01891 * Because it's basically impossible to get this right (e.g. the 01892 * Content-length is never set yet when we get here, and we can't 01893 * calc the entity hash) it's best to just leave this #def'd out. 01894 */ 01895 char date[APR_RFC822_DATE_LEN]; 01896 apr_rfc822_date(date, r->request_time); 01897 char *entity_info = 01898 ap_md5(r->pool, 01899 (unsigned char *) apr_pstrcat(r->pool, resp->raw_request_uri, 01900 ":", 01901 r->content_type ? r->content_type : ap_default_type(r), ":", 01902 hdr(r->headers_out, "Content-Length"), ":", 01903 r->content_encoding ? r->content_encoding : "", ":", 01904 hdr(r->headers_out, "Last-Modified"), ":", 01905 r->no_cache && !apr_table_get(r->headers_out, "Expires") ? 01906 date : 01907 hdr(r->headers_out, "Expires"), 01908 NULL)); 01909 digest = 01910 ap_md5(r->pool, 01911 (unsigned char *)apr_pstrcat(r->pool, conf->ha1, ":", 01912 resp->nonce, ":", 01913 r->method, ":", 01914 date, ":", 01915 entity_info, ":", 01916 ap_md5(r->pool, (unsigned char *) ""), /* H(entity) - TBD */ 01917 NULL)); 01918 #endif 01919 } 01920 01921 01922 /* setup nextnonce 01923 */ 01924 if (conf->nonce_lifetime > 0) { 01925 /* send nextnonce if current nonce will expire in less than 30 secs */ 01926 if ((r->request_time - resp->nonce_time) > (conf->nonce_lifetime-NEXTNONCE_DELTA)) { 01927 nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"", 01928 gen_nonce(r->pool, r->request_time, 01929 resp->opaque, r->server, conf), 01930 "\"", NULL); 01931 if (resp->client) 01932 resp->client->nonce_count = 0; 01933 } 01934 } 01935 else if (conf->nonce_lifetime == 0 && resp->client) { 01936 const char *nonce = gen_nonce(r->pool, 0, resp->opaque, r->server, 01937 conf); 01938 nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"", nonce, "\"", NULL); 01939 memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1); 01940 } 01941 /* else nonce never expires, hence no nextnonce */ 01942 01943 01944 /* do rfc-2069 digest 01945 */ 01946 if (conf->qop_list[0] && !strcasecmp(conf->qop_list[0], "none") 01947 && resp->message_qop == NULL) { 01948 /* use only RFC-2069 format */ 01949 if (digest) { 01950 ai = apr_pstrcat(r->pool, "digest=\"", digest, "\"", nextnonce,NULL); 01951 } 01952 else { 01953 ai = nextnonce; 01954 } 01955 } 01956 else { 01957 const char *resp_dig, *ha1, *a2, *ha2; 01958 01959 /* calculate rspauth attribute 01960 */ 01961 if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) { 01962 ha1 = get_session_HA1(r, resp, conf, 0); 01963 if (!ha1) { 01964 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01965 "Digest: internal error: couldn't find session " 01966 "info for user %s", resp->username); 01967 return !OK; 01968 } 01969 } 01970 else { 01971 ha1 = conf->ha1; 01972 } 01973 01974 if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int")) { 01975 a2 = apr_pstrcat(r->pool, ":", resp->uri, ":", 01976 ap_md5(r->pool,(const unsigned char *) ""), NULL); 01977 /* TBD */ 01978 } 01979 else { 01980 a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL); 01981 } 01982 ha2 = ap_md5(r->pool, (const unsigned char *)a2); 01983 01984 resp_dig = ap_md5(r->pool, 01985 (unsigned char *)apr_pstrcat(r->pool, ha1, ":", 01986 resp->nonce, ":", 01987 resp->nonce_count, ":", 01988 resp->cnonce, ":", 01989 resp->message_qop ? 01990 resp->message_qop : "", 01991 ":", ha2, NULL)); 01992 01993 /* assemble Authentication-Info header 01994 */ 01995 ai = apr_pstrcat(r->pool, 01996 "rspauth=\"", resp_dig, "\"", 01997 nextnonce, 01998 resp->cnonce ? ", cnonce=\"" : "", 01999 resp->cnonce 02000 ? ap_escape_quotes(r->pool, resp->cnonce) 02001 : "", 02002 resp->cnonce ? "\"" : "", 02003 resp->nonce_count ? ", nc=" : "", 02004 resp->nonce_count ? resp->nonce_count : "", 02005 resp->message_qop ? ", qop=" : "", 02006 resp->message_qop ? resp->message_qop : "", 02007 digest ? "digest=\"" : "", 02008 digest ? digest : "", 02009 digest ? "\"" : "", 02010 NULL); 02011 } 02012 02013 if (ai && ai[0]) { 02014 apr_table_mergen(r->headers_out, 02015 (PROXYREQ_PROXY == r->proxyreq) 02016 ? "Proxy-Authentication-Info" 02017 : "Authentication-Info", 02018 ai); 02019 } 02020 02021 return OK; 02022 }
|
|
||||||||||||||||
|
Definition at line 444 of file mod_auth_digest.c. References apr_pcalloc, AUTHN_PROVIDER_GROUP, conf, authn_provider::get_realm_hash, last, authn_provider_list::next, NULL, cmd_parms_struct::pool, authn_provider_list::provider, authn_provider_list::provider_name, and digest_config_struct::providers. 00446 { 00447 digest_config_rec *conf = (digest_config_rec*)config; 00448 authn_provider_list *newp; 00449 00450 newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list)); 00451 newp->provider_name = apr_pstrdup(cmd->pool, arg); 00452 00453 /* lookup and cache the actual provider now */ 00454 newp->provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, 00455 newp->provider_name, "0"); 00456 00457 if (newp->provider == NULL) { 00458 /* by the time they use it, the provider should be loaded and 00459 registered with us. */ 00460 return apr_psprintf(cmd->pool, 00461 "Unknown Authn provider: %s", 00462 newp->provider_name); 00463 } 00464 00465 if (!newp->provider->get_realm_hash) { 00466 /* if it doesn't provide the appropriate function, reject it */ 00467 return apr_psprintf(cmd->pool, 00468 "The '%s' Authn provider doesn't support " 00469 "Digest Authentication", newp->provider_name); 00470 } 00471 00472 /* Add it to the list now. */ 00473 if (!conf->providers) { 00474 conf->providers = newp; 00475 } 00476 else { 00477 authn_provider_list *last = conf->providers; 00478 00479 while (last->next) { 00480 last = last->next; 00481 } 00482 last->next = newp; 00483 } 00484 00485 return NULL; 00486 }
|
|
||||||||||||||||
|
Definition at line 795 of file mod_auth_digest.c. References APLOG_DEBUG, APLOG_INFO, APLOG_MARK, bucket, entry, gc(), hash_entry::key, hash_entry::next, and NULL. Referenced by gen_client(). 00797 { 00798 int bucket; 00799 client_entry *entry; 00800 00801 00802 if (!key || !client_shm) { 00803 return NULL; 00804 } 00805 00806 bucket = key % client_list->tbl_len; 00807 entry = client_list->table[bucket]; 00808 00809 apr_global_mutex_lock(client_lock); 00810 00811 /* try to allocate a new entry */ 00812 00813 entry = (client_entry *)apr_rmm_malloc(client_rmm, sizeof(client_entry)); 00814 if (!entry) { 00815 long num_removed = gc(); 00816 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 00817 "Digest: gc'd %ld client entries. Total new clients: " 00818 "%ld; Total removed clients: %ld; Total renewed clients: " 00819 "%ld", num_removed, 00820 client_list->num_created - client_list->num_renewed, 00821 client_list->num_removed, client_list->num_renewed); 00822 entry = (client_entry *)apr_rmm_malloc(client_rmm, sizeof(client_entry)); 00823 if (!entry) { 00824 return NULL; /* give up */ 00825 } 00826 } 00827 00828 /* now add the entry */ 00829 00830 memcpy(entry, info, sizeof(client_entry)); 00831 entry->key = key; 00832 entry->next = client_list->table[bucket]; 00833 client_list->table[bucket] = entry; 00834 client_list->num_created++; 00835 client_list->num_entries++; 00836 00837 apr_global_mutex_unlock(client_lock); 00838 00839 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 00840 "allocated new client %lu", key); 00841 00842 return entry; 00843 }
|
|
|
Definition at line 1583 of file mod_auth_digest.c. References digest_header_struct::algorithm, request_rec::ap_auth_type, ap_default_port, ap_get_module_config, APLOG_ERR, APLOG_INFO, APLOG_MARK, APR_SUCCESS, AUTH_DENIED, auth_digest_module, digest_header_struct::auth_hdr_sts, AUTH_USER_FOUND, AUTH_USER_NOT_FOUND, check_nc(), check_nonce(), conf, copy_uri_components(), DECLINED, digest_header_struct::digest, get_hash(), digest_config_struct::ha1, apr_uri_t::hostinfo, apr_uri_t::hostname, HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR, HTTP_UNAUTHORIZED, INVALID, M_CONNECT, request_rec::main, match(), digest_header_struct::message_qop, request_rec::method_number, digest_header_struct::needed_auth, new_digest(), NOT_DIGEST, note_digest_auth_failure(), NULL, OK, old_digest(), digest_header_struct::opaque, digest_header_struct::opaque_num, apr_uri_t::path, request_rec::per_dir_config, request_rec::pool, apr_uri_t::port, apr_uri_t::port_str, request_rec::prev, digest_header_struct::psd_request_uri, digest_config_struct::qop_list, apr_uri_t::query, digest_header_struct::raw_request_uri, digest_config_struct::realm, digest_header_struct::realm, request_rec::request_config, res, digest_header_struct::scheme, strcasecmp(), request_rec::subprocess_env, t, digest_header_struct::uri, request_rec::uri, request_rec::user, digest_header_struct::username, and VALID. Referenced by register_hooks(). 01584 { 01585 digest_config_rec *conf; 01586 digest_header_rec *resp; 01587 request_rec *mainreq; 01588 const char *t; 01589 int res; 01590 authn_status return_code; 01591 01592 /* do we require Digest auth for this URI? */ 01593 01594 if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest")) { 01595 return DECLINED; 01596 } 01597 01598 if (!ap_auth_name(r)) { 01599 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01600 "Digest: need AuthName: %s", r->uri); 01601 return HTTP_INTERNAL_SERVER_ERROR; 01602 } 01603 01604 01605 /* get the client response and mark */ 01606 01607 mainreq = r; 01608 while (mainreq->main != NULL) { 01609 mainreq = mainreq->main; 01610 } 01611 while (mainreq->prev != NULL) { 01612 mainreq = mainreq->prev; 01613 } 01614 resp = (digest_header_rec *) ap_get_module_config(mainreq->request_config, 01615 &auth_digest_module); 01616 resp->needed_auth = 1; 01617 01618 01619 /* get our conf */ 01620 01621 conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config, 01622 &auth_digest_module); 01623 01624 01625 /* check for existence and syntax of Auth header */ 01626 01627 if (resp->auth_hdr_sts != VALID) { 01628 if (resp->auth_hdr_sts == NOT_DIGEST) { 01629 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01630 "Digest: client used wrong authentication scheme " 01631 "`%s': %s", resp->scheme, r->uri); 01632 } 01633 else if (resp->auth_hdr_sts == INVALID) { 01634 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01635 "Digest: missing user, realm, nonce, uri, digest, " 01636 "cnonce, or nonce_count in authorization header: %s", 01637 r->uri); 01638 } 01639 /* else (resp->auth_hdr_sts == NO_HEADER) */ 01640 note_digest_auth_failure(r, conf, resp, 0); 01641 return HTTP_UNAUTHORIZED; 01642 } 01643 01644 r->user = (char *) resp->username; 01645 r->ap_auth_type = (char *) "Digest"; 01646 01647 /* check the auth attributes */ 01648 01649 if (strcmp(resp->uri, resp->raw_request_uri)) { 01650 /* Hmm, the simple match didn't work (probably a proxy modified the 01651 * request-uri), so lets do a more sophisticated match 01652 */ 01653 apr_uri_t r_uri, d_uri; 01654 01655 copy_uri_components(&r_uri, resp->psd_request_uri, r); 01656 if (apr_uri_parse(r->pool, resp->uri, &d_uri) != APR_SUCCESS) { 01657 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01658 "Digest: invalid uri <%s> in Authorization header", 01659 resp->uri); 01660 return HTTP_BAD_REQUEST; 01661 } 01662 01663 if (d_uri.hostname) { 01664 ap_unescape_url(d_uri.hostname); 01665 } 01666 if (d_uri.path) { 01667 ap_unescape_url(d_uri.path); 01668 } 01669 01670 if (d_uri.query) { 01671 ap_unescape_url(d_uri.query); 01672 } 01673 else if (r_uri.query) { 01674 /* MSIE compatibility hack. MSIE has some RFC issues - doesn't 01675 * include the query string in the uri Authorization component 01676 * or when computing the response component. the second part 01677 * works out ok, since we can hash the header and get the same 01678 * result. however, the uri from the request line won't match 01679 * the uri Authorization component since the header lacks the 01680 * query string, leaving us incompatable with a (broken) MSIE. 01681 * 01682 * the workaround is to fake a query string match if in the proper 01683 * environment - BrowserMatch MSIE, for example. the cool thing 01684 * is that if MSIE ever fixes itself the simple match ought to 01685 * work and this code won't be reached anyway, even if the 01686 * environment is set. 01687 */ 01688 01689 if (apr_table_get(r->subprocess_env, 01690 "AuthDigestEnableQueryStringHack")) { 01691 01692 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "Digest: " 01693 "applying AuthDigestEnableQueryStringHack " 01694 "to uri <%s>", resp->raw_request_uri); 01695 01696 d_uri.query = r_uri.query; 01697 } 01698 } 01699 01700 if (r->method_number == M_CONNECT) { 01701 if (!r_uri.hostinfo || strcmp(resp->uri, r_uri.hostinfo)) { 01702 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01703 "Digest: uri mismatch - <%s> does not match " 01704 "request-uri <%s>", resp->uri, r_uri.hostinfo); 01705 return HTTP_BAD_REQUEST; 01706 } 01707 } 01708 else if ( 01709 /* check hostname matches, if present */ 01710 (d_uri.hostname && d_uri.hostname[0] != '\0' 01711 && strcasecmp(d_uri.hostname, r_uri.hostname)) 01712 /* check port matches, if present */ 01713 || (d_uri.port_str && d_uri.port != r_uri.port) 01714 /* check that server-port is default port if no port present */ 01715 || (d_uri.hostname && d_uri.hostname[0] != '\0' 01716 && !d_uri.port_str && r_uri.port != ap_default_port(r)) 01717 /* check that path matches */ 01718 || (d_uri.path != r_uri.path 01719 /* either exact match */ 01720 && (!d_uri.path || !r_uri.path 01721 || strcmp(d_uri.path, r_uri.path)) 01722 /* or '*' matches empty path in scheme://host */ 01723 && !(d_uri.path && !r_uri.path && resp->psd_request_uri->hostname 01724 && d_uri.path[0] == '*' && d_uri.path[1] == '\0')) 01725 /* check that query matches */ 01726 || (d_uri.query != r_uri.query 01727 && (!d_uri.query || !r_uri.query 01728 || strcmp(d_uri.query, r_uri.query))) 01729 ) { 01730 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01731 "Digest: uri mismatch - <%s> does not match " 01732 "request-uri <%s>", resp->uri, resp->raw_request_uri); 01733 return HTTP_BAD_REQUEST; 01734 } 01735 } 01736 01737 if (resp->opaque && resp->opaque_num == 0) { 01738 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01739 "Digest: received invalid opaque - got `%s'", 01740 resp->opaque); 01741 note_digest_auth_failure(r, conf, resp, 0); 01742 return HTTP_UNAUTHORIZED; 01743 } 01744 01745 if (strcmp(resp->realm, conf->realm)) { 01746 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01747 "Digest: realm mismatch - got `%s' but expected `%s'", 01748 resp->realm, conf->realm); 01749 note_digest_auth_failure(r, conf, resp, 0); 01750 return HTTP_UNAUTHORIZED; 01751 } 01752 01753 if (resp->algorithm != NULL 01754 && strcasecmp(resp->algorithm, "MD5") 01755 && strcasecmp(resp->algorithm, "MD5-sess")) { 01756 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01757 "Digest: unknown algorithm `%s' received: %s", 01758 resp->algorithm, r->uri); 01759 note_digest_auth_failure(r, conf, resp, 0); 01760 return HTTP_UNAUTHORIZED; 01761 } 01762 01763 return_code = get_hash(r, r->user, conf); 01764 01765 if (return_code == AUTH_USER_NOT_FOUND) { 01766 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01767 "Digest: user `%s' in realm `%s' not found: %s", 01768 r->user, conf->realm, r->uri); 01769 note_digest_auth_failure(r, conf, resp, 0); 01770 return HTTP_UNAUTHORIZED; 01771 } 01772 else if (return_code == AUTH_USER_FOUND) { 01773 /* we have a password, so continue */ 01774 } 01775 else if (return_code == AUTH_DENIED) { 01776 /* authentication denied in the provider before attempting a match */ 01777 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01778 "Digest: user `%s' in realm `%s' denied by provider: %s", 01779 r->user, conf->realm, r->uri); 01780 note_digest_auth_failure(r, conf, resp, 0); 01781 return HTTP_UNAUTHORIZED; 01782 } 01783 else { 01784 /* AUTH_GENERAL_ERROR (or worse) 01785 * We'll assume that the module has already said what its error 01786 * was in the logs. 01787 */ 01788 return HTTP_INTERNAL_SERVER_ERROR; 01789 } 01790 01791 if (resp->message_qop == NULL) { 01792 /* old (rfc-2069) style digest */ 01793 if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) { 01794 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01795 "Digest: user %s: password mismatch: %s", r->user, 01796 r->uri); 01797 note_digest_auth_failure(r, conf, resp, 0); 01798 return HTTP_UNAUTHORIZED; 01799 } 01800 } 01801 else { 01802 const char *exp_digest; 01803 int match = 0, idx; 01804 for (idx = 0; conf->qop_list[idx] != NULL; idx++) { 01805 if (!strcasecmp(conf->qop_list[idx], resp->message_qop)) { 01806 match = 1; 01807 break; 01808 } 01809 } 01810 01811 if (!match 01812 && !(conf->qop_list[0] == NULL 01813 && !strcasecmp(resp->message_qop, "auth"))) { 01814 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01815 "Digest: invalid qop `%s' received: %s", 01816 resp->message_qop, r->uri); 01817 note_digest_auth_failure(r, conf, resp, 0); 01818 return HTTP_UNAUTHORIZED; 01819 } 01820 01821 exp_digest = new_digest(r, resp, conf); 01822 if (!exp_digest) { 01823 /* we failed to allocate a client struct */ 01824 return HTTP_INTERNAL_SERVER_ERROR; 01825 } 01826 if (strcmp(resp->digest, exp_digest)) { 01827 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 01828 "Digest: user %s: password mismatch: %s", r->user, 01829 r->uri); 01830 note_digest_auth_failure(r, conf, resp, 0); 01831 return HTTP_UNAUTHORIZED; 01832 } 01833 } 01834 01835 if (check_nc(r, resp, conf) != OK) { 01836 note_digest_auth_failure(r, conf, resp, 0); 01837 return HTTP_UNAUTHORIZED; 01838 } 01839 01840 /* Note: this check is done last so that a "stale=true" can be 01841 generated if the nonce is old */ 01842 if ((res = check_nonce(r, resp, conf))) { 01843 return res; 01844 } 01845 01846 return OK; 01847 }
|
|
||||||||||||||||
|
Definition at line 1377 of file mod_auth_digest.c. References APLOG_ERR, APLOG_MARK, apr_isspace, digest_c |