diff options
Diffstat (limited to 'daemon/digest.c')
-rw-r--r-- | daemon/digest.c | 87 |
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); |