summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--configure.in4
-rw-r--r--daemon/bd.c2
-rw-r--r--daemon/digest.c35
-rw-r--r--daemon/digest.h2
-rw-r--r--daemon/httpauthd.c10
-rw-r--r--daemon/httpauthd.h1
-rw-r--r--daemon/ldap.c4
-rw-r--r--daemon/simple.c2
-rw-r--r--doc/httpauthd.conf.511
10 files changed, 64 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 9e94376..196ba4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+0.8
+ - Support ignoring of HTTP method in digest. Useful for pass-through
+ authentication between SOAP services and websites.
+
0.7 [28-05-2007]
- Use my real name 'Stef Walter'
See: http://memberwebs.com/nielsen/
diff --git a/configure.in b/configure.in
index ee8b6db..cc350e7 100644
--- a/configure.in
+++ b/configure.in
@@ -36,8 +36,8 @@ dnl Stef Walter <stef@memberwebs.com>
dnl
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(httpauth, 0.7, stef@memberwebs.com)
-AM_INIT_AUTOMAKE(httpauth, 0.7)
+AC_INIT(httpauth, 0.7.90, stef@memberwebs.com)
+AM_INIT_AUTOMAKE(httpauth, 0.7.90)
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CFLAGS="$CFLAGS -I/usr/local/include -g -O0"
diff --git a/daemon/bd.c b/daemon/bd.c
index 6383801..e11a56b 100644
--- a/daemon/bd.c
+++ b/daemon/bd.c
@@ -405,7 +405,7 @@ static int do_digest_response(ha_request_t* rq, bd_context_t* ctx, const char* h
/* And do the validation ourselves */
memcpy(dg.ha1, rec->ha1, MD5_LEN);
- ret = digest_complete_check(&dg, rq->buf);
+ ret = digest_complete_check(&dg, rq->context, rq->buf);
if(ret != HA_OK)
{
diff --git a/daemon/digest.c b/daemon/digest.c
index dc0cfb9..1c68366 100644
--- a/daemon/digest.c
+++ b/daemon/digest.c
@@ -32,6 +32,11 @@
/* A globally unique counter used to guarantee uniqueness of nonces */
static unsigned int g_digest_unique = 0;
+/* All the various HTTP methods to try when ignoring the method */
+static const char* g_http_methods[] = {
+ "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", NULL
+};
+
typedef struct internal_nonce
{
unsigned char hash[MD5_LEN];
@@ -242,7 +247,7 @@ int digest_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t* bu
r = digest_pre_check(dg, opts, buf);
if(r == HA_OK)
- r = digest_complete_check(dg, buf);
+ r = digest_complete_check(dg, opts, buf);
return r;
}
@@ -396,7 +401,7 @@ int digest_pre_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t
}
-int digest_complete_check(digest_context_t* dg, ha_buffer_t* buf)
+static int internal_check(digest_context_t* dg, const char* http_method, ha_buffer_t* buf)
{
unsigned char hash[MD5_LEN];
md5_ctx_t md5;
@@ -419,7 +424,7 @@ int digest_complete_check(digest_context_t* dg, ha_buffer_t* buf)
/* Encode ha2 */
md5_init(&md5);
- md5_update(&md5, dg->server_method, strlen(dg->server_method));
+ md5_update(&md5, http_method, strlen(http_method));
md5_update(&md5, ":", 1);
md5_update(&md5, dg->client.uri, strlen(dg->client.uri));
md5_final(hash, &md5);
@@ -479,6 +484,30 @@ int digest_complete_check(digest_context_t* dg, ha_buffer_t* buf)
return HA_OK;
}
+int digest_complete_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t* buf)
+{
+ const char** m;
+ int ret;
+
+ if(opts->digest_ignoremethod)
+ {
+ /* Try out each and every method in HTTP */
+ for(m = g_http_methods; *m; ++m)
+ {
+ ret = internal_check (dg, *m, buf);
+ if(ret != HA_FALSE)
+ break;
+ }
+ }
+ else
+ {
+ /* Use the method sent to us */
+ ret = internal_check (dg, dg->server_method, buf);
+ }
+
+ return ret;
+}
+
const char* digest_respond(digest_context_t* dg, ha_buffer_t* buf,
unsigned char* next)
{
diff --git a/daemon/digest.h b/daemon/digest.h
index 86360c7..af8a1d7 100644
--- a/daemon/digest.h
+++ b/daemon/digest.h
@@ -73,7 +73,7 @@ int digest_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t* bu
int digest_pre_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t* buf);
/* This assumes a digest_context that's been prechecked successfully */
-int digest_complete_check(digest_context_t* dg, ha_buffer_t* buf);
+int digest_complete_check(digest_context_t* dg, const ha_context_t* opts, ha_buffer_t* buf);
/* This assumes a digest_context that's been checked and validated successfully */
const char* digest_respond(digest_context_t* dg, ha_buffer_t* buf, unsigned char* next);
diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c
index 68c0e46..b77abcb 100644
--- a/daemon/httpauthd.c
+++ b/daemon/httpauthd.c
@@ -1514,6 +1514,16 @@ static int config_parse(const char* file, ha_buffer_t* buf)
recog = 1;
}
+ else if(strcmp(name, "digestignoremethod") == 0)
+ {
+ int v;
+ if(ha_confbool(name, value, &v) < 0)
+ exit(1); /* Message already printed */
+
+ opts->digest_ignoremethod = v;
+ recog = 1;
+ }
+
#ifdef _DEBUG
else if(strcmp(name, "digestdebugnonce") == 0)
{
diff --git a/daemon/httpauthd.h b/daemon/httpauthd.h
index 4c7c8d6..36c8449 100644
--- a/daemon/httpauthd.h
+++ b/daemon/httpauthd.h
@@ -118,6 +118,7 @@ typedef struct ha_context
const char* realm;
/* For digest auth: */
+ unsigned int digest_ignoremethod : 1;
unsigned int digest_ignoreuri : 1;
unsigned int digest_ignorenc : 1;
const char* digest_debugnonce;
diff --git a/daemon/ldap.c b/daemon/ldap.c
index b3d88fc..59e9912 100644
--- a/daemon/ldap.c
+++ b/daemon/ldap.c
@@ -695,7 +695,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
foundany = 1;
/* Run the actual check */
- ret = digest_complete_check(dg, rq->buf);
+ ret = digest_complete_check(dg, rq->context, rq->buf);
if(ret != HA_FALSE)
RETURN(ret);
@@ -724,7 +724,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
digest_makeha1(dg->ha1, user, rq->context->realm, *p);
/* Run the actual check */
- ret = digest_complete_check(dg, rq->buf);
+ ret = digest_complete_check(dg, rq->context, rq->buf);
if(ret != HA_FALSE)
RETURN(ret);
diff --git a/daemon/simple.c b/daemon/simple.c
index 46b1cf1..1c37c23 100644
--- a/daemon/simple.c
+++ b/daemon/simple.c
@@ -146,7 +146,7 @@ static int validate_digest(ha_request_t* rq, const char* user, digest_context_t*
foundgood = 1;
/* Try to do the validation */
- ret = digest_complete_check(dg, rq->buf);
+ ret = digest_complete_check(dg, rq->context, rq->buf);
/* If invalid then continue search */
if(ret == HA_FALSE)
diff --git a/doc/httpauthd.conf.5 b/doc/httpauthd.conf.5
index 8d967c3..bae1d2d 100644
--- a/doc/httpauthd.conf.5
+++ b/doc/httpauthd.conf.5
@@ -148,6 +148,14 @@ How this exactly works depends on the method it applies to.
[ Default:
.Em 900
]
+.It Cd DigestIgnoreMethod
+When set to
+.Em True
+allows the HTTP method value in
+.Em Digest
+authentication to be mismatched with the actual request. This opens
+up a variety of replay attacks, but is useful for pass-through
+authentication (eg: a website using a SOAP service).
.It Cd DigestIgnoreNC
When set to
.Em True
@@ -164,7 +172,8 @@ When set to
allows the URI value in
.Em Digest
authentication to be mismatched with the URI requested. This opens up
-a variety of replay attacks, but may be necessary in some cases.
+a variety of replay attacks, but is useful for pass-through
+authentication (eg: a website using a SOAP service).
.Pp
[ Default:
.Em False