summaryrefslogtreecommitdiff
path: root/daemon/digest.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/digest.c')
-rw-r--r--daemon/digest.c87
1 files changed, 55 insertions, 32 deletions
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);