static int authenticate_digest_user(request_rec *r) { digest_config_rec *sec = (digest_config_rec *) ap_get_module_config(r->per_dir_config, &digest_module); digest_header_rec *response = ap_pcalloc(r->pool, sizeof(digest_header_rec)); conn_rec *c = r->connection; char *a1; int res; if ((res = get_digest_rec(r, response))) return res; if (!sec->pwfile) return DECLINED; if (!(a1 = get_hash(r, c->user, sec->pwfile))) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "user %s not found: %s", c->user, r->uri); ap_note_digest_auth_failure(r); return AUTH_REQUIRED; } if (strcmp(response->digest, find_digest(r, response, a1))) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "user %s: password mismatch: %s", c->user, r->uri); ap_note_digest_auth_failure(r); return AUTH_REQUIRED; } return OK; }
CAMLprim value netcgi2_apache_request_note_digest_auth_failure (value rv) { CAMLparam1 (rv); request_rec *r = Request_rec_val (rv); ap_note_digest_auth_failure (r); CAMLreturn (Val_unit); }
static int digest_check_auth(request_rec *r) { char *user = r->connection->user; int m = r->method_number; int method_restricted = 0; register int x; const char *t; char *w; array_header *reqs_arr; require_line *reqs; if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest")) return DECLINED; reqs_arr = ap_requires(r); /* If there is no "requires" directive, * then any user will do. */ if (!reqs_arr) return OK; reqs = (require_line *) reqs_arr->elts; for (x = 0; x < reqs_arr->nelts; x++) { if (!(reqs[x].method_mask & (1 << m))) continue; method_restricted = 1; t = reqs[x].requirement; w = ap_getword(r->pool, &t, ' '); if (!strcmp(w, "valid-user")) return OK; else if (!strcmp(w, "user")) { while (t[0]) { w = ap_getword_conf(r->pool, &t); if (!strcmp(user, w)) return OK; } } else return DECLINED; } if (!method_restricted) return OK; ap_note_digest_auth_failure(r); return AUTH_REQUIRED; }
static int get_digest_rec(request_rec *r, digest_header_rec * response) { const char *auth_line = ap_table_get(r->headers_in, r->proxyreq ? "Proxy-Authorization" : "Authorization"); int l; int s, vk = 0, vv = 0; char *t, *key, *value; if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest")) return DECLINED; if (!ap_auth_name(r)) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "need AuthName: %s", r->uri); return SERVER_ERROR; } if (!auth_line) { ap_note_digest_auth_failure(r); return AUTH_REQUIRED; } if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Digest")) { /* Client tried to authenticate using wrong auth scheme */ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "client used wrong authentication scheme: %s", r->uri); ap_note_digest_auth_failure(r); return AUTH_REQUIRED; } l = strlen(auth_line); /* Note we don't allocate l + 1 bytes for these deliberately, because * there has to be at least one '=' character for either of these two * new strings to be terminated. That takes care of the need for +1. */ key = ap_palloc(r->pool, l); value = ap_palloc(r->pool, l); /* There's probably a better way to do this, but for the time being... */ #define D_KEY 0 #define D_VALUE 1 #define D_STRING 2 #define D_EXIT -1 s = D_KEY; while (s != D_EXIT) { switch (s) { case D_STRING: if (auth_line[0] == '\"') { s = D_VALUE; } else { value[vv] = auth_line[0]; vv++; } auth_line++; break; case D_VALUE: if (isalnum(auth_line[0])) { value[vv] = auth_line[0]; vv++; } else if (auth_line[0] == '\"') { s = D_STRING; } else { value[vv] = '\0'; if (!strcasecmp(key, "username")) response->username = ap_pstrdup(r->pool, value); else if (!strcasecmp(key, "realm")) response->realm = ap_pstrdup(r->pool, value); else if (!strcasecmp(key, "nonce")) response->nonce = ap_pstrdup(r->pool, value); else if (!strcasecmp(key, "uri")) response->requested_uri = ap_pstrdup(r->pool, value); else if (!strcasecmp(key, "response")) response->digest = ap_pstrdup(r->pool, value); vv = 0; s = D_KEY; } auth_line++; break; case D_KEY: if (isalnum(auth_line[0])) { key[vk] = auth_line[0]; vk++; } else if (auth_line[0] == '=') { key[vk] = '\0'; vk = 0; s = D_VALUE; } auth_line++; break; } if (auth_line[-1] == '\0') s = D_EXIT; } if (!response->username || !response->realm || !response->nonce || !response->requested_uri || !response->digest) { ap_note_digest_auth_failure(r); return AUTH_REQUIRED; } r->connection->user = response->username; r->connection->ap_auth_type = "Digest"; return OK; }