From 670eba73c474230e31d688e9568fcd540b4e3b39 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Mon, 9 Aug 2004 18:35:56 +0000 Subject: - added request parameter to ha_message... - combined ha_request and ha_response --- daemon/digest.c | 822 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 411 insertions(+), 411 deletions(-) (limited to 'daemon/digest.c') diff --git a/daemon/digest.c b/daemon/digest.c index 405a661..099bf31 100644 --- a/daemon/digest.c +++ b/daemon/digest.c @@ -12,103 +12,103 @@ static unsigned int g_digest_unique = 0; typedef struct internal_nonce { - unsigned char hash[MD5_LEN]; - time_t tm; - unsigned int unique; + unsigned char hash[MD5_LEN]; + time_t tm; + unsigned int unique; } internal_nonce_t; void digest_makenonce(unsigned char* nonce, unsigned char* secret, unsigned char* old) { - internal_nonce_t in; - md5_ctx_t md5; - - ASSERT(nonce && secret); - ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN); - - if(old) - { - internal_nonce_t* nold = (internal_nonce_t*)old; - in.tm = nold->tm; - in.unique = nold->unique; - } - else - { - in.tm = time(NULL); - ha_lock(NULL); - in.unique = g_digest_unique++; - ha_unlock(NULL); - } - - md5_init(&md5); - md5_update(&md5, secret, DIGEST_SECRET_LEN); - md5_update(&md5, &(in.tm), sizeof(in.tm)); - md5_update(&md5, &(in.unique), sizeof(in.unique)); - md5_final(in.hash, &md5); - - memcpy(nonce, &in, DIGEST_NONCE_LEN); + internal_nonce_t in; + md5_ctx_t md5; + + ASSERT(nonce && secret); + ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN); + + if(old) + { + internal_nonce_t* nold = (internal_nonce_t*)old; + in.tm = nold->tm; + in.unique = nold->unique; + } + else + { + in.tm = time(NULL); + ha_lock(NULL); + in.unique = g_digest_unique++; + ha_unlock(NULL); + } + + md5_init(&md5); + md5_update(&md5, secret, DIGEST_SECRET_LEN); + md5_update(&md5, &(in.tm), sizeof(in.tm)); + md5_update(&md5, &(in.unique), sizeof(in.unique)); + md5_final(in.hash, &md5); + + memcpy(nonce, &in, DIGEST_NONCE_LEN); } int digest_checknonce(unsigned char* nonce, unsigned char* secret, time_t* tm) { - internal_nonce_t in; + internal_nonce_t in; - ASSERT(nonce && secret); - ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN); + ASSERT(nonce && secret); + ASSERT(sizeof(internal_nonce_t) == DIGEST_NONCE_LEN); - digest_makenonce((unsigned char*)&in, secret, nonce); + digest_makenonce((unsigned char*)&in, secret, nonce); - if(memcmp((unsigned char*)&in, nonce, DIGEST_SECRET_LEN) == 0) - { - if(tm) - *tm = in.tm; + if(memcmp((unsigned char*)&in, nonce, DIGEST_SECRET_LEN) == 0) + { + if(tm) + *tm = in.tm; - return HA_OK; - } + return HA_OK; + } - return HA_FALSE; + return HA_FALSE; } digest_record_t* digest_makerec(unsigned char* nonce, const char* user) { - digest_record_t* rec = (digest_record_t*)malloc(sizeof(*rec)); + digest_record_t* rec = (digest_record_t*)malloc(sizeof(*rec)); - ASSERT(nonce && user); + ASSERT(nonce && user); - if(!rec) - { - ha_messagex(LOG_CRIT, "out of memory"); - return NULL; - } + if(!rec) + { + ha_messagex(NULL, LOG_CRIT, "out of memory"); + return NULL; + } - memset(rec, 0, sizeof(*rec)); - memcpy(rec->nonce, nonce, DIGEST_NONCE_LEN); + memset(rec, 0, sizeof(*rec)); + memcpy(rec->nonce, nonce, DIGEST_NONCE_LEN); - md5_string(rec->userhash, user); - return rec; + md5_string(rec->userhash, user); + return rec; } const char* digest_challenge(ha_buffer_t* buf, const char* nonce_str, const char* realm, const char* domains, int stale) { - ASSERT(buf && realm && nonce_str); + ASSERT(buf && realm && nonce_str); - ha_bufmcat(buf, HA_PREFIX_DIGEST, " realm=\"", realm, "\", nonce=\"", - nonce_str, "\", qop=\"auth\", algorithm=\"MD5\"", NULL); + ha_bufmcat(buf, HA_PREFIX_DIGEST, " realm=\"", realm, "\", nonce=\"", + nonce_str, "\", qop=\"auth\", algorithm=\"MD5\"", NULL); - if(domains) - { - ha_bufjoin(buf); - ha_bufmcat(buf, ", domain=\"", domains, "\"", NULL); - } + if(domains) + { + ha_bufjoin(buf); + ha_bufmcat(buf, ", domain=\"", domains, "\"", NULL); + } - if(stale) - { - ha_bufjoin(buf); - ha_bufcat(buf, ", stale=true"); - } + if(stale) + { + ha_bufjoin(buf); + ha_bufcat(buf, ", stale=true"); + } - return ha_bufdata(buf); + return ha_bufdata(buf); } /* @@ -130,316 +130,396 @@ const char* digest_challenge(ha_buffer_t* buf, const char* nonce_str, int digest_parse(char* header, ha_buffer_t* buf, digest_header_t* rec, unsigned char* nonce) { - char next; - char* key; - char* value; - - ASSERT(header && buf && rec); - - header = ha_bufcpy(buf, header); - - if(!header) - return HA_CRITERROR; - - memset(rec, 0, sizeof(*rec)); - - while(header[0]) - { - /* find key */ - header = (char*)trim_start(header); - key = header; + char next; + char* key; + char* value; - while(header[0] && header[0] != '=' && header[0] != ',' && - !isspace(header[0])) - header++; + ASSERT(header && buf && rec); - /* null terminate and move on */ - next = header[0]; - header[0] = '\0'; - header++; + header = ha_bufcpy(buf, header); - if(!next) - break; - - if(isspace(header[0])) - { - header = (char*)trim_start(header); - next = header[0]; - } + if(!header) + return HA_CRITERROR; - /* find value */ + memset(rec, 0, sizeof(*rec)); - if(next == '=') + while(header[0]) { - header = (char*)trim_start(header); + /* find key */ + header = (char*)trim_start(header); + key = header; - if(header[0] == '\"') /* quoted string */ - { - header++; - value = header; - - while(header[0] && header[0] != '\"') - header++; + while(header[0] && header[0] != '=' && header[0] != ',' && + !isspace(header[0])) + header++; + /* null terminate and move on */ next = header[0]; - header[0] = 0; + header[0] = '\0'; header++; - } - else /* token */ - { - value = header; + if(!next) + break; + + if(isspace(header[0])) + { + header = (char*)trim_start(header); + next = header[0]; + } - while(header[0] && header[0] != ',' && !isspace(header[0])) - header++; + /* find value */ - next = header[0]; - header[0] = 0; - header++; - } - - if(next != ',') - { - while(header[0] && header[0] != ',') - header++; - - if(header[0]) - header++; - } - - if(!strcasecmp(key, "username")) - rec->username = value; - else if(!strcasecmp(key, "realm")) - rec->realm = value; - else if (!strcasecmp(key, "nonce")) - rec->nonce = value; - else if (!strcasecmp(key, "uri")) - rec->uri = value; - else if (!strcasecmp(key, "response")) - rec->digest = value; - else if (!strcasecmp(key, "algorithm")) - rec->algorithm = value; - else if (!strcasecmp(key, "cnonce")) - rec->cnonce = value; - else if (!strcasecmp(key, "opaque")) - rec->opaque = value; - else if (!strcasecmp(key, "qop")) - rec->qop = value; - else if (!strcasecmp(key, "nc")) - rec->nc = value; + if(next == '=') + { + header = (char*)trim_start(header); + + if(header[0] == '\"') /* quoted string */ + { + header++; + value = header; + + while(header[0] && header[0] != '\"') + header++; + + next = header[0]; + header[0] = 0; + header++; + } + + else /* token */ + { + value = header; + + while(header[0] && header[0] != ',' && !isspace(header[0])) + header++; + + next = header[0]; + header[0] = 0; + header++; + } + + if(next != ',') + { + while(header[0] && header[0] != ',') + header++; + + if(header[0]) + header++; + } + + if(!strcasecmp(key, "username")) + rec->username = value; + else if(!strcasecmp(key, "realm")) + rec->realm = value; + else if (!strcasecmp(key, "nonce")) + rec->nonce = value; + else if (!strcasecmp(key, "uri")) + rec->uri = value; + else if (!strcasecmp(key, "response")) + rec->digest = value; + else if (!strcasecmp(key, "algorithm")) + rec->algorithm = value; + else if (!strcasecmp(key, "cnonce")) + rec->cnonce = value; + else if (!strcasecmp(key, "opaque")) + rec->opaque = value; + else if (!strcasecmp(key, "qop")) + rec->qop = value; + else if (!strcasecmp(key, "nc")) + rec->nc = value; + } } - } - if(nonce) - { - memset(nonce, 0, DIGEST_NONCE_LEN); - - if(rec->nonce) + if(nonce) { - size_t len = DIGEST_NONCE_LEN; - void* d = ha_bufdechex(buf, rec->nonce, &len); + memset(nonce, 0, DIGEST_NONCE_LEN); + + if(rec->nonce) + { + size_t len = DIGEST_NONCE_LEN; + void* d = ha_bufdechex(buf, rec->nonce, &len); - if(d && len == DIGEST_NONCE_LEN) - memcpy(nonce, d, DIGEST_NONCE_LEN); + if(d && len == DIGEST_NONCE_LEN) + memcpy(nonce, d, DIGEST_NONCE_LEN); + } } - } - return HA_OK; + return HA_OK; } int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_t* ctx, 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(ctx && method && buf && dg && rec); - - /* TODO: Many of these should somehow communicate BAD REQ back to the client */ - - /* Check for digest */ - if(!dg->digest || !dg->digest[0]) - { - ha_messagex(LOG_WARNING, "digest response missing digest"); - return HA_BADREQ; - } - - /* Username */ - 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) - { - ha_messagex(LOG_WARNING, "digest response contains missing realm"); - return HA_BADREQ; - } - - if(strcmp(dg->realm, ctx->realm) != 0) - { - ha_messagex(LOG_ERR, "digest response contains invalid realm: %s", dg->realm); - return HA_FALSE; - } + unsigned char hash[MD5_LEN]; + md5_ctx_t md5; + const char* digest; + const char* t; - /* Components in the new RFC */ - if(dg->qop) - { - /* - * We only support 'auth' qop. We don't have access to the data - * and wouldn't be able to support anything else. - */ - if(strcmp(dg->qop, "auth") != 0) + ASSERT(ctx && method && buf && dg && rec); + + /* TODO: This stuff should probably go into bd.c */ + + /* Check for digest */ + if(!dg->digest || !dg->digest[0]) { - ha_messagex(LOG_WARNING, "digest response contains unknown or unsupported qop: '%s'", - dg->qop ? dg->qop : ""); - return HA_BADREQ; + ha_messagex(NULL, LOG_WARNING, "digest response missing digest"); + return HA_BADREQ; } - /* The cnonce */ - if(!dg->cnonce || !dg->cnonce[0]) + /* Username */ + if(!dg->username || !dg->username[0]) { - ha_messagex(LOG_WARNING, "digest response is missing cnonce value"); - return HA_BADREQ; + ha_messagex(NULL, LOG_WARNING, "digest response missing username"); + return HA_BADREQ; + } + + if(md5_strcmp(rec->userhash, dg->username) != 0) + { + ha_messagex(NULL, LOG_ERR, "digest response contains invalid username"); + return HA_FALSE; } - if(!ctx->digest_ignorenc) + /* The realm */ + if(!dg->realm) { - /* The nonce count */ - if(!dg->nc || !dg->nc[0]) - { - ha_messagex(LOG_WARNING, "digest response is missing nc value"); + ha_messagex(NULL, LOG_WARNING, "digest response contains missing realm"); return HA_BADREQ; - } + } - /* Validate the nc */ - else - { - char* e; - long nc = strtol(dg->nc, &e, 16); + if(strcmp(dg->realm, ctx->realm) != 0) + { + ha_messagex(NULL, LOG_ERR, "digest response contains invalid realm: %s", dg->realm); + return HA_FALSE; + } - if(*e) + /* Components in the new RFC */ + if(dg->qop) + { + /* + * We only support 'auth' qop. We don't have access to the data + * and wouldn't be able to support anything else. + */ + if(strcmp(dg->qop, "auth") != 0) { - ha_messagex(LOG_ERR, "digest response has invalid nc value: %s", dg->nc); - return HA_BADREQ; + ha_messagex(NULL, LOG_WARNING, "digest response contains unknown or unsupported qop: '%s'", + dg->qop ? dg->qop : ""); + return HA_BADREQ; } - /* If we didn't a nc then save it away */ - if(!*e && rec->nc == 0) - rec->nc = nc; + /* The cnonce */ + if(!dg->cnonce || !dg->cnonce[0]) + { + ha_messagex(NULL, LOG_WARNING, "digest response is missing cnonce value"); + return HA_BADREQ; + } - if(*e || nc != rec->nc) + if(!ctx->digest_ignorenc) { - ha_messagex(LOG_WARNING, "digest response has wrong nc value. " - "possible replay attack: %s", dg->nc); - return HA_FALSE; + /* The nonce count */ + if(!dg->nc || !dg->nc[0]) + { + ha_messagex(NULL, 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(NULL, 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(NULL, LOG_WARNING, "digest response has wrong nc value. " + "possible replay attack: %s", dg->nc); + return HA_FALSE; + } + } } - } } - } - - /* The algorithm */ - if(dg->algorithm && strcasecmp(dg->algorithm, "MD5") != 0) - { - ha_messagex(LOG_WARNING, "digest response contains unknown or unsupported algorithm: '%s'", - dg->algorithm ? dg->algorithm : ""); - return HA_BADREQ; - } - - /* Request URI */ - if(!dg->uri) - { - ha_messagex(LOG_WARNING, "digest response is missing uri"); - return HA_BADREQ; - } - - if(!ctx->digest_ignoreuri && strcmp(dg->uri, uri) != 0) - { - ha_uri_t d_uri; - ha_uri_t s_uri; - - if(ha_uriparse(buf, dg->uri, &d_uri) < 0) + + /* The algorithm */ + if(dg->algorithm && strcasecmp(dg->algorithm, "MD5") != 0) { - if(ha_buferr(buf)) - return HA_CRITERROR; + ha_messagex(NULL, LOG_WARNING, "digest response contains unknown or unsupported algorithm: '%s'", + dg->algorithm ? dg->algorithm : ""); + return HA_BADREQ; + } - ha_messagex(LOG_WARNING, "digest response constains invalid uri: %s", dg->uri); - return HA_BADREQ; + /* Request URI */ + if(!dg->uri) + { + ha_messagex(NULL, LOG_WARNING, "digest response is missing uri"); + return HA_BADREQ; } - if(ha_uriparse(buf, uri, &s_uri) < 0) + if(!ctx->digest_ignoreuri && strcmp(dg->uri, uri) != 0) { - if(ha_buferr(buf)) + ha_uri_t d_uri; + ha_uri_t s_uri; + + if(ha_uriparse(buf, dg->uri, &d_uri) < 0) + { + if(ha_buferr(buf)) + return HA_CRITERROR; + + ha_messagex(NULL, LOG_WARNING, "digest response constains invalid uri: %s", dg->uri); + return HA_BADREQ; + } + + if(ha_uriparse(buf, uri, &s_uri) < 0) + { + if(ha_buferr(buf)) + return HA_CRITERROR; + + ha_messagex(NULL, LOG_ERR, "server sent us an invalid uri"); + return HA_BADREQ; + } + + if(ha_uricmp(&d_uri, &s_uri) != 0) + { + ha_messagex(NULL, LOG_ERR, "digest response contains wrong uri: %s " + "(should be %s)", dg->uri, uri); + return HA_FALSE; + } + } + + /* + * nonce: should have already been validated by the caller who + * found this nice rec structure to pass us. + * + * opaque: We also don't use opaque. The caller should have validated it + * if it's used there. + */ + + /* + * Now we validate the digest response + */ + + /* Encode ha1 */ + t = ha_bufenchex(buf, rec->ha1, MD5_LEN); + + if(t == NULL) + return HA_CRITERROR; + + /* Encode ha2 */ + md5_init(&md5); + md5_update(&md5, method, strlen(method)); + md5_update(&md5, ":", 1); + md5_update(&md5, dg->uri, strlen(dg->uri)); + md5_final(hash, &md5); + + ha_bufenchex(buf, hash, MD5_LEN); + + if(!ha_bufdata(buf)) return HA_CRITERROR; - ha_messagex(LOG_ERR, "server sent us an invalid uri"); - return HA_BADREQ; + + /* Old style digest (RFC 2069) */ + if(!dg->qop) + { + md5_init(&md5); + md5_update(&md5, t, MD5_LEN * 2); /* ha1 */ + md5_update(&md5, ":", 1); + md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */ + md5_update(&md5, ":", 1); + md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha1 */ + md5_final(hash, &md5); + } + + /* New style 'auth' digest (RFC 2617) */ + else + { + md5_init(&md5); + md5_update(&md5, t, MD5_LEN * 2); /* ha1 */ + md5_update(&md5, ":", 1); + md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */ + md5_update(&md5, ":", 1); + md5_update(&md5, dg->nc, strlen(dg->nc)); /* nc */ + md5_update(&md5, ":", 1); + md5_update(&md5, dg->cnonce, strlen(dg->cnonce)); /* cnonce */ + md5_update(&md5, ":", 1); + md5_update(&md5, dg->qop, strlen(dg->qop)); /* qop */ + md5_update(&md5, ":", 1); + md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha2 */ + md5_final(hash, &md5); } - if(ha_uricmp(&d_uri, &s_uri) != 0) + /* Encode the digest */ + digest = ha_bufenchex(buf, hash, MD5_LEN); + + if(digest == NULL) + return HA_CRITERROR; + + if(strcasecmp(dg->digest, digest) != 0) { - ha_messagex(LOG_ERR, "digest response contains wrong uri: %s " - "(should be %s)", dg->uri, uri); - return HA_FALSE; + ha_messagex(NULL, LOG_WARNING, "digest authentication failed for user: %s", dg->username); + return HA_FALSE; } - } - /* - * nonce: should have already been validated by the caller who - * found this nice rec structure to pass us. - * - * opaque: We also don't use opaque. The caller should have validated it - * if it's used there. - */ + return HA_OK; +} - /* - * Now we validate the digest response - */ +const char* digest_respond(ha_buffer_t* buf, digest_header_t* dg, + digest_record_t* rec, unsigned char* next) +{ + unsigned char hash[MD5_LEN]; + md5_ctx_t md5; + const char* nextnonce = NULL; + const char* t; - /* Encode ha1 */ - t = ha_bufenchex(buf, rec->ha1, MD5_LEN); + ASSERT(buf && dg && rec); - if(t == NULL) - return HA_CRITERROR; + /* This makes a new buffer */ + ha_bufcpy(buf, ""); - /* Encode ha2 */ - md5_init(&md5); - md5_update(&md5, method, strlen(method)); - md5_update(&md5, ":", 1); - md5_update(&md5, dg->uri, strlen(dg->uri)); - md5_final(hash, &md5); + if(next) + { + nextnonce = ha_bufenc64(buf, next, DIGEST_NONCE_LEN); - ha_bufenchex(buf, hash, MD5_LEN); + if(nextnonce == NULL) + return NULL; + } - if(!ha_bufdata(buf)) - return HA_CRITERROR; + /* For older clients RFC 2069 */ + if(!dg->qop) + { + if(nextnonce) + ha_bufmcat(buf, "nextnonce=\"", nextnonce, "\"", NULL); + + return ha_bufdata(buf); + } + + /* Otherwise we do the whole song and dance */ + /* Encode ha1 */ + t = ha_bufenchex(buf, rec->ha1, MD5_LEN); - /* Old style digest (RFC 2069) */ - if(!dg->qop) - { + if(t == NULL) + return NULL; + + /* Encode ha2 */ md5_init(&md5); - md5_update(&md5, t, MD5_LEN * 2); /* ha1 */ - md5_update(&md5, ":", 1); - md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */ md5_update(&md5, ":", 1); - md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha1 */ + md5_update(&md5, dg->uri, strlen(dg->uri)); md5_final(hash, &md5); - } - /* New style 'auth' digest (RFC 2617) */ - else - { + ha_bufenchex(buf, hash, MD5_LEN); + + if(!ha_bufdata(buf)) + return NULL; + + /* New style 'auth' digest (RFC 2617) */ md5_init(&md5); md5_update(&md5, t, MD5_LEN * 2); /* ha1 */ md5_update(&md5, ":", 1); @@ -453,119 +533,39 @@ int digest_check(digest_header_t* dg, digest_record_t* rec, const ha_context_t* md5_update(&md5, ":", 1); md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha2 */ md5_final(hash, &md5); - } - /* Encode the digest */ - digest = ha_bufenchex(buf, hash, MD5_LEN); + /* Encode the digest */ + t = ha_bufenchex(buf, hash, MD5_LEN); - if(digest == NULL) - return HA_CRITERROR; + if(t == NULL) + return NULL; - if(strcasecmp(dg->digest, digest) != 0) - { - ha_messagex(LOG_WARNING, "digest authentication failed for user: %s", dg->username); - return HA_FALSE; - } - - return HA_OK; -} - -const char* digest_respond(ha_buffer_t* buf, digest_header_t* dg, - digest_record_t* rec, unsigned char* next) -{ - unsigned char hash[MD5_LEN]; - md5_ctx_t md5; - const char* nextnonce = NULL; - const char* t; - - ASSERT(buf && dg && rec); + ha_bufmcat(buf, "rspauth=\"", t, "\"", + ", qop=", dg->qop, + ", nc=", dg->nc, + ", cnonce=\"", dg->cnonce, "\"", NULL); - /* This makes a new buffer */ - ha_bufcpy(buf, ""); - - if(next) - { - nextnonce = ha_bufenc64(buf, next, DIGEST_NONCE_LEN); - - if(nextnonce == NULL) - return NULL; - } - - /* For older clients RFC 2069 */ - if(!dg->qop) - { if(nextnonce) - ha_bufmcat(buf, "nextnonce=\"", nextnonce, "\"", NULL); + { + ha_bufjoin(buf); + ha_bufmcat(buf, ", nextnonce=\"", nextnonce, "\"", NULL); + } return ha_bufdata(buf); - } - - /* Otherwise we do the whole song and dance */ - - /* Encode ha1 */ - t = ha_bufenchex(buf, rec->ha1, MD5_LEN); - - if(t == NULL) - return NULL; - - /* Encode ha2 */ - md5_init(&md5); - md5_update(&md5, ":", 1); - md5_update(&md5, dg->uri, strlen(dg->uri)); - md5_final(hash, &md5); - - ha_bufenchex(buf, hash, MD5_LEN); - - if(!ha_bufdata(buf)) - return NULL; - - /* New style 'auth' digest (RFC 2617) */ - md5_init(&md5); - md5_update(&md5, t, MD5_LEN * 2); /* ha1 */ - md5_update(&md5, ":", 1); - md5_update(&md5, dg->nonce, strlen(dg->nonce)); /* nonce */ - md5_update(&md5, ":", 1); - md5_update(&md5, dg->nc, strlen(dg->nc)); /* nc */ - md5_update(&md5, ":", 1); - md5_update(&md5, dg->cnonce, strlen(dg->cnonce)); /* cnonce */ - md5_update(&md5, ":", 1); - md5_update(&md5, dg->qop, strlen(dg->qop)); /* qop */ - md5_update(&md5, ":", 1); - md5_update(&md5, ha_bufdata(buf), MD5_LEN * 2); /* ha2 */ - md5_final(hash, &md5); - - /* Encode the digest */ - t = ha_bufenchex(buf, hash, MD5_LEN); - - if(t == NULL) - return NULL; - - ha_bufmcat(buf, "rspauth=\"", t, "\"", - ", qop=", dg->qop, - ", nc=", dg->nc, - ", cnonce=\"", dg->cnonce, "\"", NULL); - - if(nextnonce) - { - ha_bufjoin(buf); - ha_bufmcat(buf, ", nextnonce=\"", nextnonce, "\"", NULL); - } - - return ha_bufdata(buf); } void digest_makeha1(unsigned char* digest, const char* user, const char* realm, const char* password) { - md5_ctx_t md5; + md5_ctx_t md5; - ASSERT(digest && user && realm && password); + ASSERT(digest && user && realm && password); - md5_init(&md5); - md5_update(&md5, user, strlen(user)); - md5_update(&md5, ":", 1); - md5_update(&md5, realm, strlen(realm)); - md5_update(&md5, ":", 1); - md5_update(&md5, password, strlen(password)); - md5_final(digest, &md5); + md5_init(&md5); + md5_update(&md5, user, strlen(user)); + md5_update(&md5, ":", 1); + md5_update(&md5, realm, strlen(realm)); + md5_update(&md5, ":", 1); + md5_update(&md5, password, strlen(password)); + md5_final(digest, &md5); } -- cgit v1.2.3