mod_auth_digest.c revision 032b8a34c3911bbc5ad5385ca40af65af273bff9
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering/* ====================================================================
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * The Apache Software License, Version 1.1
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * Copyright (c) 2000 The Apache Software Foundation. All rights
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * Redistribution and use in source and binary forms, with or without
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * modification, are permitted provided that the following conditions
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * 1. Redistributions of source code must retain the above copyright
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * notice, this list of conditions and the following disclaimer.
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * 2. Redistributions in binary form must reproduce the above copyright
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * notice, this list of conditions and the following disclaimer in
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * the documentation and/or other materials provided with the
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * distribution.
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * 3. The end-user documentation included with the redistribution,
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * if any, must include the following acknowledgment:
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * "This product includes software developed by the
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * Apache Software Foundation (http://www.apache.org/)."
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * Alternately, this acknowledgment may appear in the software itself,
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * if and wherever such third-party acknowledgments normally appear.
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * 4. The names "Apache" and "Apache Software Foundation" must
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * not be used to endorse or promote products derived from this
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * software without prior written permission. For written
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * permission, please contact apache@apache.org.
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * 5. Products derived from this software may not be called "Apache",
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * nor may "Apache" appear in their name, without prior written
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * permission of the Apache Software Foundation.
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering * SUCH DAMAGE.
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * ====================================================================
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * This software consists of voluntary contributions made by many
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * individuals on behalf of the Apache Software Foundation. For more
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * information on the Apache Software Foundation, please see
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * Portions of this software are based upon public domain software
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering * originally written at the National Center for Supercomputing Applications,
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * University of Illinois, Urbana-Champaign.
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering * mod_auth_digest: MD5 digest authentication
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering * Originally by Alexei Kosut <akosut@nueva.pvt.k12.ca.us>
c75f27ea2b483f91d437ebaf8494457dc76f3fd6Lennart Poettering * Updated to RFC-2617 by Ronald Tschal�r <ronald@innovation.ch>
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * based on mod_auth, by Rob McCool and Robert S. Thau
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * This module an updated version of modules/standard/mod_digest.c
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * It is still fairly new and problems may turn up - submit problem
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * reports to the Apache bug-database, or send them directly to me
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * at ronald@innovation.ch.
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * Requires either /dev/random (or equivalent) or the truerand library,
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * available for instance from
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * ftp://research.att.com/dist/mab/librand.shar
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * Open Issues:
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - qop=auth-int (when streams and trailer support available)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - nonce-format configurability
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - Proxy-Authorization-Info header is set by this module, but is
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * currently ignored by mod_proxy (needs patch to mod_proxy)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - generating the secret takes a while (~ 8 seconds) if using the
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * truerand library
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - The source of the secret should be run-time directive (with server
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * scope: RSRC_CONF). However, that could be tricky when trying to
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * choose truerand vs. file...
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - shared-mem not completely tested yet. Seems to work ok for me,
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * but... (definitely won't work on Windoze)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - Sharing a realm among multiple servers has following problems:
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * o Server name and port can't be included in nonce-hash
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * (we need two nonce formats, which must be configured explicitly)
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * o Nonce-count check can't be for equal, or then nonce-count checking
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * must be disabled. What we could do is the following:
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * (expected < received) ? set expected = received : issue error
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * The only problem is that it allows replay attacks when somebody
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * captures a packet sent to one server and sends it to another
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * one. Should we add "AuthDigestNcCheck Strict"?
d7c7c334f56edab8cfc102b657366277a65738cfLennart Poettering * - expired nonces give amaya fits.
#include "http_request.h"
#include "http_log.h"
#include "http_protocol.h"
#include "ap_ctype.h"
#include "util_uri.h"
#include "util_md5.h"
#include "ap_sha1.h"
#include "ap_base64.h"
#include "apr_time.h"
#include "apr_errno.h"
#include "apr_lock.h"
#include "apr_strings.h"
#include "apr_shmem.h"
typedef void ap_shmem_t;
typedef void ap_shm_name_t;
return APR_ENOTIMPL;
return APR_ENOTIMPL;
return NULL;
return NULL;
return APR_ENOTIMPL;
return APR_ENOTIMPL;
return APR_ENOTIMPL;
return APR_ENOTIMPL;
return APR_ENOTIMPL;
typedef struct digest_config_struct {
const char *dir_name;
const char *pwfile;
const char *grpfile;
const char *realm;
const char **qop_list;
const char *nonce_format;
int check_nc;
const char *algorithm;
char *uri_list;
const char *ha1;
typedef struct hash_entry {
} client_entry;
static struct hash_table {
unsigned long tbl_len;
unsigned long num_entries;
unsigned long num_created;
unsigned long num_removed;
unsigned long num_renewed;
} *client_list;
typedef struct digest_header_struct {
const char *scheme;
const char *realm;
const char *username;
char *nonce;
const char *uri;
const char *digest;
const char *algorithm;
const char *cnonce;
const char *opaque;
unsigned long opaque_num;
const char *message_qop;
const char *nonce_count;
const char *raw_request_uri;
int needed_auth;
typedef union time_union {
} time_rec;
static int call_cnt = 0;
static unsigned long *opaque_cntr;
if (client_shm) {
if (client_lock) {
if (opaque_lock) {
return APR_SUCCESS;
unsigned long idx;
if (!client_list) {
*otn_counter = 0;
#define APR_HAS_SHARED_MEMORY 0
initialize_tables(s, p);
if (!client_shm)
!= APR_SUCCESS
!= APR_SUCCESS) {
if (conf) {
return conf;
return DECLINE_CMD;
const char *file)
return NULL;
const char *file)
return NULL;
char **tmp;
int cnt;
return NULL;
return NULL;
char *endptr;
long lifetime;
return NULL;
const char *fmt)
return NULL;
if (!client_shm) {
return NULL;
if (c->uri_list) {
return NULL;
const char *size_str)
char *endptr;
if (num_buckets == 0)
return NULL;
{NULL}
int bucket;
if (entry)
return entry;
static long gc(void)
num_removed++;
return num_removed;
server_rec *s)
int bucket;
if (!entry) {
return entry;
const char *auth_line;
size_t l;
if (!auth_line) {
return !OK;
return !OK;
vk = 0;
auth_line++;
vv = 0;
auth_line++;
return !OK;
return OK;
int res;
if (!ap_is_initial_req(r))
return DECLINED;
return DECLINED;
int idx;
if (opaque)
int len;
time_rec t;
else if (otn_counter)
return nonce;
unsigned long op;
return NULL;
return entry;
* people need not modify mod_auth_digest.c each time they install a new
int generate)
else if (!generate)
return NULL;
if (ha1)
return ha1;
return dir;
return "http://0.0.0.0/";
return dir;
return tmp;
if (num != 0)
int cnt;
if (opaque[0])
if (r->proxyreq)
configfile_t *f;
char l[MAX_STRING_LEN];
const char *rpw;
return NULL;
rpw = l;
ap_cfg_closefile(f);
ap_cfg_closefile(f);
return NULL;
unsigned long nc;
char *endptr;
return OK;
return !OK;
return !OK;
return !OK;
return OK;
double dt;
int len;
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
return OK;
const char *ha2;
if (!ha1)
return NULL;
NULL));
request_rec *r) {
int res;
return DECLINED;
if (!ap_auth_name(r)) {
return HTTP_INTERNAL_SERVER_ERROR;
mainreq = r;
r->uri);
return HTTP_UNAUTHORIZED;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
return DECLINED;
return HTTP_UNAUTHORIZED;
r->uri);
return HTTP_UNAUTHORIZED;
const char *exp_digest;
if (!match
return HTTP_UNAUTHORIZED;
if (!exp_digest) {
return HTTP_INTERNAL_SERVER_ERROR;
r->uri);
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
return res;
return OK;
const char *grpfile)
configfile_t *f;
char l[MAX_STRING_LEN];
return NULL;
return NULL;
ll = l;
while (ll[0]) {
ap_cfg_closefile(f);
return grps;
int m = r->method_number;
int method_restricted = 0;
return DECLINED;
if (!reqs_arr)
return OK;
return OK;
return OK;
if (!grpstatus)
return DECLINED;
return OK;
return DECLINED;
if (!method_restricted)
return OK;
return HTTP_UNAUTHORIZED;
#ifdef SEND_DIGEST
if (val)
return val;
return OK;
#ifdef SEND_DIGEST
char *entity_info =
date :
NULL));
digest =
NULL));
conf);
if (digest)
if (!ha1) {
return !OK;
NULL);
ai);
return OK;
static void register_hooks(void)