summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
Diffstat (limited to 'daemon')
-rw-r--r--daemon/defaults.h2
-rw-r--r--daemon/digest.c87
-rw-r--r--daemon/digest.h4
-rw-r--r--daemon/httpauthd.c10
-rw-r--r--daemon/httpauthd.h3
-rw-r--r--daemon/ldap.c20
-rw-r--r--daemon/simple.c14
7 files changed, 85 insertions, 55 deletions
diff --git a/daemon/defaults.h b/daemon/defaults.h
index 828bec1..b3c6fcf 100644
--- a/daemon/defaults.h
+++ b/daemon/defaults.h
@@ -3,7 +3,7 @@
#define __DEFAULTS_H__
#define DEFAULT_PENDING_MAX 16
-#define DEFAULT_PENDING_TIMEOUT 60
+#define DEFAULT_PENDING_TIMEOUT 20
#define DEFAULT_TIMEOUT 900
#define DEFAULT_CACHEMAX 1024
#define DEFAULT_PORT 8020
diff --git a/daemon/digest.c b/daemon/digest.c
index 0bd6398..5c53191 100644
--- a/daemon/digest.c
+++ b/daemon/digest.c
@@ -242,7 +242,7 @@ int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec,
if(rec->nonce)
{
size_t len = DIGEST_NONCE_LEN;
- void* d = ha_bufdec64(buf, rec->nonce, &len);
+ void* d = ha_bufdechex(buf, rec->nonce, &len);
if(d && len == DIGEST_NONCE_LEN)
memcpy(nonce, d, DIGEST_NONCE_LEN);
@@ -252,15 +252,15 @@ int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec,
return HA_OK;
}
-int digest_check(const char* realm, const char* method, const char* uri,
- ha_buffer_t* buf, digest_header_t* dg, digest_record_t* rec)
+int digest_check(digest_header_t* dg, digest_record_t* rec, ha_options_t* opts,
+ ha_buffer_t* buf, const char* method, const char* uri)
{
unsigned char hash[MD5_LEN];
md5_ctx_t md5;
const char* digest;
const char* t;
- ASSERT(realm && method && uri && buf && dg && rec);
+ ASSERT(opts && method && buf && dg && rec);
/* TODO: Many of these should somehow communicate BAD REQ back to the client */
@@ -272,21 +272,31 @@ int digest_check(const char* realm, const char* method, const char* uri,
}
/* Username */
- if(!dg->username || !dg->username[0] ||
- md5_strcmp(rec->userhash, dg->username) != 0)
+ if(!dg->username || !dg->username[0])
{
ha_messagex(LOG_WARNING, "digest response missing username");
return HA_BADREQ;
}
+ if(md5_strcmp(rec->userhash, dg->username) != 0)
+ {
+ ha_messagex(LOG_ERR, "digest response contains invalid username");
+ return HA_FALSE;
+ }
+
/* The realm */
- if(!dg->realm || strcmp(dg->realm, realm) != 0)
+ if(!dg->realm)
{
- ha_messagex(LOG_WARNING, "digest response contains invalid realm: '%s'",
- dg->realm ? dg->realm : "");
+ ha_messagex(LOG_WARNING, "digest response contains missing realm");
return HA_BADREQ;
}
+ if(strcmp(dg->realm, opts->realm) != 0)
+ {
+ ha_messagex(LOG_ERR, "digest response contains invalid realm: %s", dg->realm);
+ return HA_FALSE;
+ }
+
/* Components in the new RFC */
if(dg->qop)
{
@@ -308,25 +318,38 @@ int digest_check(const char* realm, const char* method, const char* uri,
return HA_BADREQ;
}
- /* The nonce count */
- if(!dg->nc || !dg->nc[0])
+ if(!opts->digest_ignorenc)
{
- ha_messagex(LOG_WARNING, "digest response is missing nc value");
- return HA_BADREQ;
- }
-
- /* Validate the nc */
- else
- {
- char* e;
- long nc = strtol(dg->nc, &e, 10);
-
- if(*e || nc != rec->nc)
+ /* The nonce count */
+ if(!dg->nc || !dg->nc[0])
{
- ha_messagex(LOG_WARNING, "digest response has invalid nc value: %s",
- dg->nc);
+ ha_messagex(LOG_WARNING, "digest response is missing nc value");
return HA_BADREQ;
}
+
+ /* Validate the nc */
+ else
+ {
+ char* e;
+ long nc = strtol(dg->nc, &e, 16);
+
+ if(*e)
+ {
+ ha_messagex(LOG_ERR, "digest response has invalid nc value: %s", dg->nc);
+ return HA_BADREQ;
+ }
+
+ /* If we didn't a nc then save it away */
+ if(!*e && rec->nc == 0)
+ rec->nc = nc;
+
+ if(*e || nc != rec->nc)
+ {
+ ha_messagex(LOG_WARNING, "digest response has wrong nc value. "
+ "possible replay attack: %s", dg->nc);
+ return HA_FALSE;
+ }
+ }
}
}
@@ -345,7 +368,7 @@ int digest_check(const char* realm, const char* method, const char* uri,
return HA_BADREQ;
}
- if(strcmp(dg->uri, uri) != 0)
+ if(!opts->digest_ignoreuri && strcmp(dg->uri, uri) != 0)
{
ha_uri_t d_uri;
ha_uri_t s_uri;
@@ -370,9 +393,9 @@ int digest_check(const char* realm, const char* method, const char* uri,
if(ha_uricmp(&d_uri, &s_uri) != 0)
{
- ha_messagex(LOG_WARNING, "digest response contains wrong uri: %s "
- "(should be %s)", dg->uri, uri);
- return HA_BADREQ;
+ ha_messagex(LOG_ERR, "digest response contains wrong uri: %s "
+ "(should be %s)", dg->uri, uri);
+ return HA_FALSE;
}
}
@@ -523,14 +546,14 @@ const char* digest_respond(ha_buffer_t* buf, digest_header_t* dg,
return NULL;
ha_bufmcat(buf, "rspauth=\"", t, "\"",
- " qop=", dg->qop,
- " nc=", dg->nc,
- " cnonce=\"", dg->cnonce, "\"", NULL);
+ ", qop=", dg->qop,
+ ", nc=", dg->nc,
+ ", cnonce=\"", dg->cnonce, "\"", NULL);
if(nextnonce)
{
ha_bufjoin(buf);
- ha_bufmcat(buf, " nextnonce=\"", nextnonce, "\"", NULL);
+ ha_bufmcat(buf, ", nextnonce=\"", nextnonce, "\"", NULL);
}
return ha_bufdata(buf);
diff --git a/daemon/digest.h b/daemon/digest.h
index 0f5e6b2..8eec901 100644
--- a/daemon/digest.h
+++ b/daemon/digest.h
@@ -42,8 +42,8 @@ int ha_digestparse(char* header, ha_buffer_t* buf, digest_header_t* rec,
int ha_digestnonce(time_t* tm, unsigned char* nonce);
-int ha_digestcheck(const char* realm, const char* method, const char* uri,
- ha_buffer_t* buf, digest_header_t* header, digest_record_t* rec);
+int digest_check(digest_header_t* dg, digest_record_t* rec, ha_options_t* opts,
+ ha_buffer_t* buf, const char* method, const char* uri);
const char* digest_respond(ha_buffer_t* buf, digest_header_t* dg,
digest_record_t* rec, unsigned char* next);
diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c
index 7c74754..55092db 100644
--- a/daemon/httpauthd.c
+++ b/daemon/httpauthd.c
@@ -1314,6 +1314,16 @@ static int config_parse(const char* file, ha_buffer_t* buf)
recog = 1;
}
+ else if(strcmp(name, "digestignorenc") == 0)
+ {
+ int v;
+ if(ha_confbool(name, value, &v) < 0)
+ exit(1); /* Message already printed */
+
+ opts->digest_ignorenc = v;
+ recog = 1;
+ }
+
else if(strcmp(name, "digestdomains") == 0)
{
opts->digest_domains = value;
diff --git a/daemon/httpauthd.h b/daemon/httpauthd.h
index cd1d39e..d225e4b 100644
--- a/daemon/httpauthd.h
+++ b/daemon/httpauthd.h
@@ -188,7 +188,8 @@ typedef struct ha_options
const char* realm;
/* For digest auth: */
- int digest_ignoreuri;
+ unsigned int digest_ignoreuri : 1;
+ unsigned int digest_ignorenc : 1;
const char* digest_domains;
const char* digest_debugnonce;
}
diff --git a/daemon/ldap.c b/daemon/ldap.c
index 78e048f..1e03c32 100644
--- a/daemon/ldap.c
+++ b/daemon/ldap.c
@@ -981,7 +981,7 @@ static int digest_ldap_challenge(ldap_context_t* ctx, ha_response_t* resp,
if(ctx->opts->digest_debugnonce)
{
nonce_str = ctx->opts->digest_debugnonce;
- ha_messagex(LOG_WARNING, "simple: using debug nonce. security non-existant.");
+ ha_messagex(LOG_WARNING, "ldap: using debug nonce. security non-existant.");
}
else
#endif
@@ -1036,7 +1036,6 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
if(dg.nonce && strcmp(dg.nonce, ctx->opts->digest_debugnonce) != 0)
{
ret = HA_FALSE;
- resp->code = HA_SERVER_BADREQ;
ha_messagex(LOG_WARNING, "ldap: digest response contains invalid nonce");
goto finally;
}
@@ -1054,10 +1053,7 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
if(r != HA_OK)
{
if(r == HA_FALSE)
- {
- resp->code = HA_SERVER_BADREQ;
ha_messagex(LOG_WARNING, "ldap: digest response contains invalid nonce");
- }
goto finally;
}
@@ -1099,11 +1095,13 @@ static int digest_ldap_response(ldap_context_t* ctx, const char* header,
}
}
- /* Increment our nonce count */
- rec->nc++;
+ /* We had a record so ... */
+ else
+ {
+ rec->nc++;
+ }
- ret = digest_check(ctx->opts->realm, method,
- ctx->opts->digest_ignoreuri ? NULL : uri, buf, &dg, rec);
+ ret = digest_check(&dg, rec, ctx->opts, buf, method, uri);
if(ret == HA_BADREQ)
{
@@ -1391,7 +1389,7 @@ int ldap_process(ha_context_t* context, ha_request_t* req,
header = ha_getheader(req, "Authorization", HA_PREFIX_DIGEST);
if(header)
{
- ha_messagex(LOG_DEBUG, "ldap: processing basic auth header");
+ ha_messagex(LOG_DEBUG, "ldap: processing digest auth header");
ret = digest_ldap_response(ctx, header, req->args[AUTH_ARG_METHOD],
req->args[AUTH_ARG_URI], resp, buf);
if(ret < 0)
@@ -1405,7 +1403,7 @@ int ldap_process(ha_context_t* context, ha_request_t* req,
header = ha_getheader(req, "Authorization", HA_PREFIX_BASIC);
if(header)
{
- ha_messagex(LOG_DEBUG, "ldap: processing digest auth header");
+ ha_messagex(LOG_DEBUG, "ldap: processing basic auth header");
ret = basic_ldap_response(ctx, header, resp, buf);
if(ret < 0)
return ret;
diff --git a/daemon/simple.c b/daemon/simple.c
index 5b4eb60..d45668f 100644
--- a/daemon/simple.c
+++ b/daemon/simple.c
@@ -458,7 +458,6 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
{
if(dg.nonce && strcmp(dg.nonce, ctx->opts->digest_debugnonce) != 0)
{
- resp->code = HA_SERVER_BADREQ;
ret = HA_FALSE;
ha_messagex(LOG_WARNING, "simple: digest response contains invalid nonce");
goto finally;
@@ -477,10 +476,7 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
if(r != HA_OK)
{
if(r == HA_FALSE)
- {
- resp->code = HA_SERVER_BADREQ;
ha_messagex(LOG_WARNING, "simple: digest response contains invalid nonce");
- }
ret = r;
goto finally;
@@ -523,11 +519,13 @@ static int simple_digest_response(simple_context_t* ctx, const char* header,
}
}
- /* Increment our nonce count */
- rec->nc++;
+ /* We had a record so ... */
+ else
+ {
+ rec->nc++;
+ }
- ret = digest_check(ctx->opts->realm, method,
- ctx->opts->digest_ignoreuri ? NULL : uri, buf, &dg, rec);
+ ret = digest_check(&dg, rec, ctx->opts, buf, method, uri);
if(ret == HA_BADREQ)
{