Return-Path:
Delivered-To: apmail-httpd-dev-archive@www.apache.org
Received: (qmail 51631 invoked from network); 18 Dec 2003 21:38:38 -0000
Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12)
by minotaur-2.apache.org with SMTP; 18 Dec 2003 21:38:38 -0000
Received: (qmail 77366 invoked by uid 500); 18 Dec 2003 21:38:20 -0000
Delivered-To: apmail-httpd-dev-archive@httpd.apache.org
Received: (qmail 77332 invoked by uid 500); 18 Dec 2003 21:38:20 -0000
Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm
Precedence: bulk
Reply-To: dev@httpd.apache.org
list-help:
list-unsubscribe:
list-post:
Delivered-To: mailing list dev@httpd.apache.org
Received: (qmail 77318 invoked from network); 18 Dec 2003 21:38:20 -0000
Received: from unknown (HELO skutsje.san.webweaving.org) (209.132.96.45)
by daedalus.apache.org with SMTP; 18 Dec 2003 21:38:20 -0000
Received: from skutsje.san.webweaving.org (localhost [127.0.0.1])
by skutsje.san.webweaving.org (8.12.9/8.12.9) with ESMTP id hBILZfEJ022483
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
for ; Thu, 18 Dec 2003 13:35:41 -0800 (PST)
(envelope-from dirkx@webweaving.org)
Received: from localhost (dirkx@localhost)
by skutsje.san.webweaving.org (8.12.9/8.12.9/Submit) with ESMTP id
hBILZfGs022478
for ; Thu, 18 Dec 2003 13:35:41 -0800 (PST)
(envelope-from dirkx@webweaving.org)
X-Authentication-Warning: skutsje.san.webweaving.org: dirkx owned process
doing -bs
Date: Thu, 18 Dec 2003 13:35:41 -0800 (PST)
From: Dirk-Willem van Gulik
X-X-Sender: dirkx@skutsje.san.webweaving.org
To: dev@httpd.apache.org
Subject: [patch] - digest nonce including MM bump, doc and changes.
Message-ID: <20031218132438.K21394@skutsje.san.webweaving.org>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=ISO-8859-1
Content-Transfer-Encoding: 8BIT
X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N
X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N
More complete patch, thanks for the feedback. Other options
include
-> kill mod_digest.c
and/or
-> move mod_auth_digest.c from exp. into standard
as this fix requires a MM bump _or_ so much rewriting that
it may be easier to spend some cycles on mod_auth_digest.c.
Dw
Index: src/ApacheCore.def
===================================================================
RCS file: /home/cvs/apache-1.3/src/ApacheCore.def,v
retrieving revision 1.35
diff -u -r1.35 ApacheCore.def
--- src/ApacheCore.def 18 Jun 2002 04:19:46 -0000 1.35
+++ src/ApacheCore.def 18 Dec 2003 21:25:49 -0000
@@ -447,3 +447,4 @@
ap_getline @439
ap_get_chunk_size @440
ap_escape_logitem @441
+ ap_auth_nonce @442
Index: src/ApacheCoreOS2.def
===================================================================
RCS file: /home/cvs/apache-1.3/src/ApacheCoreOS2.def,v
retrieving revision 1.13
diff -u -r1.13 ApacheCoreOS2.def
--- src/ApacheCoreOS2.def 22 May 2003 09:45:28 -0000 1.13
+++ src/ApacheCoreOS2.def 18 Dec 2003 21:25:50 -0000
@@ -430,3 +430,4 @@
ap_escape_logitem @441
ap_popenf_ex @442
ap_psocket_ex @443
+ ap_auth_nonce @444
Index: src/CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1914
diff -u -r1.1914 CHANGES
--- src/CHANGES 14 Dec 2003 18:16:49 -0000 1.1914
+++ src/CHANGES 18 Dec 2003 21:25:56 -0000
@@ -1,5 +1,11 @@
Changes with Apache 1.3.30
+ *) SECURITY - verification as to wether the nonce returned in the
+ client response is one we issued ourselves by means of a
+ AuthNonce secret exposed as an md5(). See mod_digest documentation
+ for more details. The experimental/mod_auth_digest.c does not
+ have this issue. [Dirk-Willem van Gulik]
+
*) SECURITY [CAN-2003-0020]: Escape arbitrary data before writing
into the errorlog. [Andr� Malo]
Index: src/include/ap_mmn.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/ap_mmn.h,v
retrieving revision 1.65
diff -u -r1.65 ap_mmn.h
--- src/include/ap_mmn.h 14 Dec 2003 18:16:49 -0000 1.65
+++ src/include/ap_mmn.h 18 Dec 2003 21:25:56 -0000
@@ -244,6 +244,8 @@
* ap_popenf_ex() and ap_psocket_ex().
* 19990320.15 - ap_is_recursion_limit_exceeded()
* 19990320.16 - ap_escape_errorlog_item()
+ * 20031212 1.3.30-dev - ap_auth_nonce() and auth_nonce added
+ * in the request_rec.
*/
#define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */
Index: src/include/http_core.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/http_core.h,v
retrieving revision 1.71
diff -u -r1.71 http_core.h
--- src/include/http_core.h 7 Jul 2003 00:34:09 -0000 1.71
+++ src/include/http_core.h 18 Dec 2003 21:25:56 -0000
@@ -162,6 +162,7 @@
API_EXPORT(const char *) ap_auth_type (request_rec *);
API_EXPORT(const char *) ap_auth_name (request_rec *);
+API_EXPORT(const char *) ap_auth_nonce (request_rec *);
API_EXPORT(int) ap_satisfies (request_rec *r);
API_EXPORT(const array_header *) ap_requires (request_rec *);
@@ -244,6 +245,7 @@
int satisfy;
char *ap_auth_type;
char *ap_auth_name;
+ char *ap_auth_nonce; /* digest auth */
array_header *ap_requires;
/* Custom response config. These can contain text or a URL to redirect to.
Index: src/main/http_core.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v
retrieving revision 1.327
diff -u -r1.327 http_core.c
--- src/main/http_core.c 17 Nov 2003 17:14:53 -0000 1.327
+++ src/main/http_core.c 18 Dec 2003 21:25:58 -0000
@@ -236,6 +236,9 @@
if (new->ap_auth_name) {
conf->ap_auth_name = new->ap_auth_name;
}
+ if (new->ap_auth_nonce) {
+ conf->ap_auth_nonce= new->ap_auth_nonce;
+ }
if (new->ap_requires) {
conf->ap_requires = new->ap_requires;
}
@@ -577,6 +580,29 @@
return conf->ap_auth_name;
}
+API_EXPORT(const char *) ap_auth_nonce(request_rec *r)
+{
+ core_dir_config *conf;
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ if (conf->ap_auth_nonce)
+ return conf->ap_auth_nonce;
+
+ /* Ideally we'd want to mix in some per-directory style
+ * information; as we are likely to want to detect replay
+ * across those boundaries and some randomness. But that
+ * is harder due to the adhoc nature of .htaccess memory
+ * structures, restarts and forks.
+ *
+ * But then again - you should use AuthNonce in your config
+ * file if you care. So the adhoc value should do.
+ */
+ return ap_psprintf(r->pool,"%lu%lu%lu%lu%lu%s",
+ *(unsigned long *)&((r->connection->local_addr).sin_addr ),
+ ap_user_name, ap_listeners, ap_server_argv0, ap_pid_fname
+ );
+}
+
API_EXPORT(const char *) ap_default_type(request_rec *r)
{
core_dir_config *conf;
@@ -2797,6 +2823,28 @@
return NULL;
}
+/*
+ * Load an authorisation nonce into our location configuration, and
+ * force it to be in the 0-9/A-Z realm.
+ */
+static const char *set_authnonce (cmd_parms *cmd, void *mconfig, char *word1)
+{
+ core_dir_config *aconfig = (core_dir_config *)mconfig;
+ int i;
+
+ aconfig->ap_auth_nonce = ap_escape_quotes(cmd->pool, word1);
+
+ if (strlen(aconfig->ap_auth_nonce) > 510)
+ return "AuthNonce length limited to 510 chars for browser compatibility";
+
+ for(i=0;iap_auth_nonce );i++)
+ if (!ap_isalnum(aconfig->ap_auth_nonce [i]))
+ return "AuthNonce limited to 0-9 and A-Z range for browser compatibility";
+
+ return NULL;
+}
+
+
#ifdef _OSD_POSIX /* BS2000 Logon Passwd file */
static const char *set_bs2000_account(cmd_parms *cmd, void *dummy, char *name)
{
@@ -3411,6 +3459,9 @@
"An HTTP authorization type (e.g., \"Basic\")" },
{ "AuthName", set_authname, NULL, OR_AUTHCFG, TAKE1,
"The authentication realm (e.g. \"Members Only\")" },
+{ "AuthNonce", set_authnonce, NULL, OR_AUTHCFG, TAKE1,
+ "An authentication token which should be different for each logical realm. "\
+ "A random value or the servers IP may be a good choise.\n" },
{ "Require", require, NULL, OR_AUTHCFG, RAW_ARGS,
"Selects which authenticated users or groups may access a protected space" },
{ "Satisfy", satisfy, NULL, OR_AUTHCFG, TAKE1,
Index: src/main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.330
diff -u -r1.330 http_protocol.c
--- src/main/http_protocol.c 3 Feb 2003 17:13:22 -0000 1.330
+++ src/main/http_protocol.c 18 Dec 2003 21:26:00 -0000
@@ -76,6 +76,7 @@
#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
#include
#include "http_conf_globals.h"
+#include "util_md5.h" /* For digestAuth */
#define SET_BYTES_SENT(r) \
do { if (r->sent_bodyct) \
@@ -1391,11 +1392,24 @@
API_EXPORT(void) ap_note_digest_auth_failure(request_rec *r)
{
+ /* We need to create a nonce which:
+ * a) changes all the time (see r->request_time)
+ * below and
+ * b) of which we can verify that it is our own
+ * fairly easily when it comes to veryfing
+ * the digest coming back in the response.
+ * c) and which as a whole should not
+ * be unlikely to be in use anywhere else.
+ */
+ char * nonce_prefix = ap_md5(r->pool,
+ ap_psprintf(r->pool, "%s%lu",
+ ap_auth_nonce(r), r->request_time));
+
ap_table_setn(r->err_headers_out,
r->proxyreq == STD_PROXY ? "Proxy-Authenticate"
: "WWW-Authenticate",
- ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%lu\"",
- ap_auth_name(r), r->request_time));
+ ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%s%lu\"",
+ ap_auth_name(r), nonce_prefix, r->request_time));
}
API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw)
Index: src/modules/standard/mod_digest.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_digest.c,v
retrieving revision 1.52
diff -u -r1.52 mod_digest.c
--- src/modules/standard/mod_digest.c 3 Feb 2003 17:13:27 -0000 1.52
+++ src/modules/standard/mod_digest.c 18 Dec 2003 21:26:00 -0000
@@ -316,6 +316,23 @@
/* The actual MD5 code... whee */
+/* Check that a given nonce is actually one which was
+ * issued by this server in the right context.
+ */
+static int check_nonce(pool *p, char * prefix, const char * nonce) {
+ char * timestamp = (char *)nonce + 2 * MD5_DIGESTSIZE;
+ char * md5;
+
+ if (strlen(nonce) < MD5_DIGESTSIZE)
+ return AUTH_REQUIRED;
+
+ md5 = ap_md5(p, ap_pstrcat(p, prefix, timestamp, NULL));
+
+ return strncmp(md5, nonce, 2 * MD5_DIGESTSIZE);
+}
+
+/* Check the digest itself.
+ */
static char *find_digest(request_rec *r, digest_header_rec * h, char *a1)
{
return ap_md5(r->pool,
@@ -339,7 +356,6 @@
/* Determine user ID, and check if it really is that user, for HTTP
* basic authentication...
*/
-
static int authenticate_digest_user(request_rec *r)
{
digest_config_rec *sec =
@@ -355,7 +371,16 @@
if (!sec->pwfile)
return DECLINED;
-
+
+ /* Check that the nonce was one we actually issued. */
+ if (check_nonce(r->pool, ap_auth_nonce(r), response->nonce)) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
+ "Client is using a nonce which was not issued by "
+ "this server for this context: %s", r->uri);
+ ap_note_digest_auth_failure(r);
+ return AUTH_REQUIRED;
+ }
+
if (!(a1 = get_hash(r, c->user, sec->pwfile))) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
"user %s not found: %s", c->user, r->uri);
Index: htdocs/manual/mod/mod_digest.html
===================================================================
RCS file: /home/cvs/httpd-docs-1.3/htdocs/manual/mod/mod_digest.html,v
retrieving revision 1.14
diff -u -r1.14 mod_digest.html
--- htdocs/manual/mod/mod_digest.html 23 Jan 2002 02:51:03 -0000 1.14
+++ htdocs/manual/mod/mod_digest.html 18 Dec 2003 21:26:51 -0000
@@ -48,17 +48,28 @@
Using MD5 Digest authentication is very simple. Simply set
up authentication normally. However, use "AuthType Digest" and
"AuthDigestFile" instead of the normal "AuthType Basic" and
- "AuthUserFile". Everything else should remain the same.
+ "AuthUserFile".
+
+ As to make sure that replay is not possible across
+ sections of the site, or across sites (assuming a realm,
+ userid and password are valid in that wider context) a
+ secret nonce prefix can be configured with the
+ core directive AuthNonce.
+
+ If none if configured a sensible, but not particular
+ secure, default is used. When used in load balancing
+ situations the prefix should be shared across servers.
+
+ The experimental mod_auth_digest
+ module offers a number of additinal protections against replay.
+
+
+ Everything else should remain the same.
MD5 authentication provides a more secure password system,
but only works with supporting browsers. As of this writing
- (January 2002), the only major browsers which support digest
- authentication are Opera 4.0,
- MS Internet
- Explorer 5.0 and Amaya.
- Therefore, we do not recommend using this feature on a large
- Internet site. However, for personal and intra-net use, where
- browser users can be controlled, it is ideal.
+ (December 2003), most major browsers support digest authentication.
+
See also mod_auth_digest,
which is an updated version of this module, in order to determine
Index: htdocs/manual/mod/core.html.en
===================================================================
RCS file: /home/cvs/httpd-docs-1.3/htdocs/manual/mod/core.html.en,v
retrieving revision 1.257
diff -u -r1.257 core.html.en
--- htdocs/manual/mod/core.html.en 3 Dec 2003 10:35:24 -0000
1.257
+++ htdocs/manual/mod/core.html.en 18 Dec 2003 21:36:14 -0000
@@ -37,6 +37,8 @@
AuthName
+ AuthNonce
+
AuthType
BindAddress
@@ -498,6 +500,7 @@
href="mod_auth_dbm.html#authdbmuserfile">AuthDBMUserFile,
AuthGroupFile, AuthName, AuthNonce, AuthType, AuthUserFile, Require, etc.).
@@ -593,6 +596,42 @@
Access Control
+
+
+ Syntax: AuthNonce
+ secret-real-string
+ Context: directory,
+ .htaccess
+ Override: AuthConfig
+ Status: core
+
+ This directive sets a per realm secret nonce prefix
+ which is used to ensure that a captured username, password
+ and realm string during a Digest exchange cannot
+ be replayed at other places.
+
+ It only applies to mod_digest.html,
+ the experimental mod_auth_digest.html
+ implements its own (more advanced and also time sensitive) replay
protection.
+
+
+ It must be accompanied by AuthType of
+ type Digest, one or more
+ Require directives, and directives such
+ as AuthUserFile and AuthGroupFile to
+ work.
+
+ See also: Authentication, Authorization, and
+ Access Control
+
+
@@ -616,6 +655,9 @@
as AuthUserFile and AuthGroupFile to
work.
+
+ When AuthDigest is used an AuthNonce
+ should also be set.
See also: Authentication, Authorization, and