|
|
|
@ -1038,6 +1038,9 @@ static void mod_auth_digest_www_authenticate(buffer *b, time_t cur_ts, const str
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute_noinline__
|
|
|
|
|
static handler_t mod_auth_send_401_unauthorized_digest(request_st *r, const struct http_auth_require_t *require, int nonce_stale);
|
|
|
|
|
|
|
|
|
|
static void mod_auth_digest_authentication_info(buffer *b, time_t cur_ts, const struct http_auth_require_t *require, int dalgo) {
|
|
|
|
|
buffer_clear(b);
|
|
|
|
|
buffer_append_string_len(b, CONST_STR_LEN("nextnonce=\""));
|
|
|
|
@ -1045,15 +1048,61 @@ static void mod_auth_digest_authentication_info(buffer *b, time_t cur_ts, const
|
|
|
|
|
buffer_append_string_len(b, CONST_STR_LEN("\""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static handler_t
|
|
|
|
|
mod_auth_digest_get (request_st * const r, void *p_d, const struct http_auth_require_t * const require, const struct http_auth_backend_t * const backend, http_auth_info_t * const ai)
|
|
|
|
|
{
|
|
|
|
|
plugin_data * const p = p_d;
|
|
|
|
|
splay_tree **sptree = p->conf.auth_cache
|
|
|
|
|
? &p->conf.auth_cache->sptree
|
|
|
|
|
: NULL;
|
|
|
|
|
http_auth_cache_entry *ae = NULL;
|
|
|
|
|
handler_t rc = HANDLER_GO_ON;
|
|
|
|
|
int ndx = -1;
|
|
|
|
|
if (sptree) {
|
|
|
|
|
ndx = http_auth_cache_hash(require, ai->username, ai->ulen);
|
|
|
|
|
ae = http_auth_cache_query(sptree, ndx);
|
|
|
|
|
if (ae && ae->require == require
|
|
|
|
|
&& ae->dalgo == ai->dalgo
|
|
|
|
|
&& ae->dlen == ai->dlen
|
|
|
|
|
&& ae->ulen == ai->ulen
|
|
|
|
|
&& 0 == memcmp(ae->username, ai->username, ai->ulen)) {
|
|
|
|
|
memcpy(ai->digest, ae->pwdigest, ai->dlen);
|
|
|
|
|
}
|
|
|
|
|
else /*(not found or hash collision)*/
|
|
|
|
|
ae = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL == ae)
|
|
|
|
|
rc = backend->digest(r, backend->p_d, ai);
|
|
|
|
|
|
|
|
|
|
switch (rc) {
|
|
|
|
|
case HANDLER_GO_ON:
|
|
|
|
|
break;
|
|
|
|
|
case HANDLER_WAIT_FOR_EVENT:
|
|
|
|
|
return HANDLER_WAIT_FOR_EVENT;
|
|
|
|
|
case HANDLER_FINISHED:
|
|
|
|
|
return HANDLER_FINISHED;
|
|
|
|
|
case HANDLER_ERROR:
|
|
|
|
|
default:
|
|
|
|
|
r->keep_alive = -1; /*(disable keep-alive if unknown user)*/
|
|
|
|
|
return mod_auth_send_401_unauthorized_digest(r, require, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sptree && NULL == ae) { /*(cache digest from backend)*/
|
|
|
|
|
ae = http_auth_cache_entry_init(require, ai->dalgo, ai->username,
|
|
|
|
|
ai->ulen, (char *)ai->digest, ai->dlen);
|
|
|
|
|
http_auth_cache_insert(sptree, ndx, ae, http_auth_cache_entry_free);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const char *key;
|
|
|
|
|
int key_len;
|
|
|
|
|
char **ptr;
|
|
|
|
|
} digest_kv;
|
|
|
|
|
|
|
|
|
|
__attribute_noinline__
|
|
|
|
|
static handler_t mod_auth_send_401_unauthorized_digest(request_st *r, const struct http_auth_require_t *require, int nonce_stale);
|
|
|
|
|
|
|
|
|
|
static handler_t mod_auth_check_digest(request_st * const r, void *p_d, const struct http_auth_require_t * const require, const struct http_auth_backend_t * const backend) {
|
|
|
|
|
char *username = NULL;
|
|
|
|
|
char *realm = NULL;
|
|
|
|
@ -1307,51 +1356,11 @@ static handler_t mod_auth_check_digest(request_st * const r, void *p_d, const st
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
plugin_data * const p = p_d;
|
|
|
|
|
splay_tree ** sptree = p->conf.auth_cache
|
|
|
|
|
? &p->conf.auth_cache->sptree
|
|
|
|
|
: NULL;
|
|
|
|
|
http_auth_cache_entry *ae = NULL;
|
|
|
|
|
handler_t rc = HANDLER_ERROR;
|
|
|
|
|
int ndx = -1;
|
|
|
|
|
if (sptree) {
|
|
|
|
|
ndx = http_auth_cache_hash(require, ai.username, ai.ulen);
|
|
|
|
|
ae = http_auth_cache_query(sptree, ndx);
|
|
|
|
|
if (ae && ae->require == require
|
|
|
|
|
&& ae->dalgo == ai.dalgo
|
|
|
|
|
&& ae->dlen == ai.dlen
|
|
|
|
|
&& ae->ulen == ai.ulen
|
|
|
|
|
&& 0 == memcmp(ae->username, ai.username, ai.ulen)) {
|
|
|
|
|
rc = HANDLER_GO_ON;
|
|
|
|
|
memcpy(ai.digest, ae->pwdigest, ai.dlen);
|
|
|
|
|
}
|
|
|
|
|
else /*(not found or hash collision)*/
|
|
|
|
|
ae = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL == ae)
|
|
|
|
|
rc = backend->digest(r, backend->p_d, &ai);
|
|
|
|
|
|
|
|
|
|
switch (rc) {
|
|
|
|
|
case HANDLER_GO_ON:
|
|
|
|
|
break;
|
|
|
|
|
case HANDLER_WAIT_FOR_EVENT:
|
|
|
|
|
buffer_free(b);
|
|
|
|
|
return HANDLER_WAIT_FOR_EVENT;
|
|
|
|
|
case HANDLER_FINISHED:
|
|
|
|
|
buffer_free(b);
|
|
|
|
|
return HANDLER_FINISHED;
|
|
|
|
|
case HANDLER_ERROR:
|
|
|
|
|
default:
|
|
|
|
|
r->keep_alive = -1; /*(disable keep-alive if unknown user)*/
|
|
|
|
|
handler_t rc;
|
|
|
|
|
rc = mod_auth_digest_get(r, p_d, require, backend, &ai);
|
|
|
|
|
if (__builtin_expect( (HANDLER_GO_ON != rc), 0)) {
|
|
|
|
|
buffer_free(b);
|
|
|
|
|
return mod_auth_send_401_unauthorized_digest(r, require, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sptree && NULL == ae) { /*(cache digest from backend)*/
|
|
|
|
|
ae = http_auth_cache_entry_init(require, ai.dalgo, ai.username, ai.ulen,
|
|
|
|
|
(char *)ai.digest, ai.dlen);
|
|
|
|
|
http_auth_cache_insert(sptree, ndx, ae, http_auth_cache_entry_free);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *m = get_http_method_name(r->http_method);
|
|
|
|
|