static CURLcode pop3_state_apop(struct connectdata *conn) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; size_t i; MD5_context *ctxt; unsigned char digest[MD5_DIGEST_LEN]; char secret[2 * MD5_DIGEST_LEN + 1]; ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp, curlx_uztoui(strlen(pop3c->apoptimestamp))); Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd, curlx_uztoui(strlen(conn->passwd))); /* Finalise the digest */ Curl_MD5_final(ctxt, digest); /* Convert the calculated 16 octet digest into a 32 byte hex string */ for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&secret[2 * i], 3, "%02x", digest[i]); result = Curl_pp_sendf(&pop3c->pp, "APOP %s %s", conn->user, secret); if(!result) state(conn, POP3_APOP); return result; }
CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ size_t md5len) { #ifdef curlssl_md5sum curlssl_md5sum(tmp, tmplen, md5sum, md5len); #else MD5_context *MD5pw; (void) md5len; MD5pw = Curl_MD5_init(Curl_DIGEST_MD5); if(!MD5pw) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen)); Curl_MD5_final(MD5pw, md5sum); #endif return CURLE_OK; }
/* * Curl_sasl_create_digest_md5_message() * * This is used to generate an already encoded DIGEST-MD5 response message * ready for sending to the recipient. * * Parameters: * * data [in] - The session handle. * chlg64 [in] - Pointer to the base64 encoded challenge message. * userp [in] - The user name. * passdwp [in] - The user's password. * service [in] - The service type such as www, smtp, pop or imap. * outptr [in/out] - The address where a pointer to newly allocated memory * holding the result will be stored upon completion. * outlen [out] - The length of the output message. * * Returns CURLE_OK on success. */ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, const char *chlg64, const char *userp, const char *passwdp, const char *service, char **outptr, size_t *outlen) { CURLcode result = CURLE_OK; size_t i; MD5_context *ctxt; char *response = NULL; unsigned char digest[MD5_DIGEST_LEN]; char HA1_hex[2 * MD5_DIGEST_LEN + 1]; char HA2_hex[2 * MD5_DIGEST_LEN + 1]; char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; char nonce[64]; char realm[128]; char algorithm[64]; char qop_options[64]; int qop_values; char cnonce[33]; unsigned int entropy[4]; char nonceCount[] = "00000001"; char method[] = "AUTHENTICATE"; char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; char *spn = NULL; /* Decode the challange message */ result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce), realm, sizeof(realm), algorithm, sizeof(algorithm), qop_options, sizeof(qop_options)); if(result) return result; /* We only support md5 sessions */ if(strcmp(algorithm, "md5-sess") != 0) return CURLE_BAD_CONTENT_ENCODING; /* Get the qop-values from the qop-options */ result = sasl_digest_get_qop_values(qop_options, &qop_values); if(result) return result; /* We only support auth quality-of-protection */ if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) return CURLE_BAD_CONTENT_ENCODING; /* Generate 16 bytes of random data */ entropy[0] = Curl_rand(data); entropy[1] = Curl_rand(data); entropy[2] = Curl_rand(data); entropy[3] = Curl_rand(data); /* Convert the random data into a 32 byte hex string */ snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x", entropy[0], entropy[1], entropy[2], entropy[3]); /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) userp, curlx_uztoui(strlen(userp))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) realm, curlx_uztoui(strlen(realm))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) passwdp, curlx_uztoui(strlen(passwdp))); Curl_MD5_final(ctxt, digest); ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_final(ctxt, digest); /* Convert calculated 16 octet hex into 32 bytes string */ for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]); /* Generate our SPN */ spn = Curl_sasl_build_spn(service, realm); if(!spn) return CURLE_OUT_OF_MEMORY; /* Calculate H(A2) */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) { Curl_safefree(spn); return CURLE_OUT_OF_MEMORY; } Curl_MD5_update(ctxt, (const unsigned char *) method, curlx_uztoui(strlen(method))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) spn, curlx_uztoui(strlen(spn))); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]); /* Now calculate the response hash */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) { Curl_safefree(spn); return CURLE_OUT_OF_MEMORY; } Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, curlx_uztoui(strlen(nonceCount))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) qop, curlx_uztoui(strlen(qop))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); /* Generate the response */ response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\"," "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s," "qop=%s", userp, realm, nonce, cnonce, nonceCount, spn, resp_hash_hex, qop); Curl_safefree(spn); if(!response) return CURLE_OUT_OF_MEMORY; /* Base64 encode the response */ result = Curl_base64_encode(data, response, 0, outptr, outlen); Curl_safefree(response); return result; }
/* * Curl_sasl_create_digest_md5_message() * * This is used to generate an already encoded DIGEST-MD5 response message * ready for sending to the recipient. * * Parameters: * * data [in] - The session handle. * nonce [in] - The nonce. * realm [in] - The realm. * userp [in] - The user name. * passdwp [in] - The user's password. * service [in] - The service type such as www, smtp, pop or imap. * outptr [in/out] - The address where a pointer to newly allocated memory * holding the result will be stored upon completion. * outlen [out] - The length of the output message. * * Returns CURLE_OK on success. */ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, const char *nonce, const char *realm, const char *userp, const char *passwdp, const char *service, char **outptr, size_t *outlen) { #ifndef DEBUGBUILD static const char table16[] = "0123456789abcdef"; #endif CURLcode result = CURLE_OK; size_t i; MD5_context *ctxt; char *response = NULL; unsigned char digest[MD5_DIGEST_LEN]; char HA1_hex[2 * MD5_DIGEST_LEN + 1]; char HA2_hex[2 * MD5_DIGEST_LEN + 1]; char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; char nonceCount[] = "00000001"; char cnonce[] = "12345678"; /* will be changed */ char method[] = "AUTHENTICATE"; char qop[] = "auth"; char uri[128]; #ifndef DEBUGBUILD /* Generate 64 bits of random data */ for(i = 0; i < 8; i++) cnonce[i] = table16[Curl_rand(data)%16]; #endif /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) userp, curlx_uztoui(strlen(userp))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) realm, curlx_uztoui(strlen(realm))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) passwdp, curlx_uztoui(strlen(passwdp))); Curl_MD5_final(ctxt, digest); ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_final(ctxt, digest); /* Convert calculated 16 octet hex into 32 bytes string */ for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]); /* Prepare the URL string */ snprintf(uri, sizeof(uri), "%s/%s", service, realm); /* Calculate H(A2) */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) method, curlx_uztoui(strlen(method))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) uri, curlx_uztoui(strlen(uri))); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]); /* Now calculate the response hash */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, curlx_uztoui(strlen(nonceCount))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) qop, curlx_uztoui(strlen(qop))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); /* Generate the response */ response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\"," "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s", userp, realm, nonce, cnonce, nonceCount, uri, resp_hash_hex); if(!response) return CURLE_OUT_OF_MEMORY; /* Base64 encode the response */ result = Curl_base64_encode(data, response, 0, outptr, outlen); Curl_safefree(response); return result; }
/* * Curl_sasl_create_digest_md5_message() * * This is used to generate an already encoded DIGEST-MD5 response message * ready for sending to the recipient. * * Parameters: * * data [in] - The session handle. * chlg64 [in] - Pointer to the base64 encoded challenge buffer. * userp [in] - The user name. * passdwp [in] - The user's password. * service [in] - The service type such as www, smtp or pop * outptr [in/out] - The address where a pointer to newly allocated memory * holding the result will be stored upon completion. * outlen [out] - The length of the output message. * * Returns CURLE_OK on success. */ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, const char* chlg64, const char* userp, const char* passwdp, const char* service, char **outptr, size_t *outlen) { static const char table16[] = "0123456789abcdef"; CURLcode result = CURLE_OK; unsigned char *chlg = (unsigned char *) NULL; size_t chlglen = 0; size_t i; MD5_context *ctxt; unsigned char digest[MD5_DIGEST_LEN]; char HA1_hex[2 * MD5_DIGEST_LEN + 1]; char HA2_hex[2 * MD5_DIGEST_LEN + 1]; char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; char nonce[64]; char realm[128]; char alg[64]; char nonceCount[] = "00000001"; char cnonce[] = "12345678"; /* will be changed */ char method[] = "AUTHENTICATE"; char qop[] = "auth"; char uri[128]; char response[512]; result = Curl_base64_decode(chlg64, &chlg, &chlglen); if(result) return result; /* Retrieve nonce string from the challenge */ if(!sasl_digest_get_key_value(chlg, "nonce=\"", nonce, sizeof(nonce), '\"')) { Curl_safefree(chlg); return CURLE_LOGIN_DENIED; } /* Retrieve realm string from the challenge */ if(!sasl_digest_get_key_value(chlg, "realm=\"", realm, sizeof(realm), '\"')) { /* Challenge does not have a realm, set empty string [RFC2831] page 6 */ strcpy(realm, ""); } /* Retrieve algorithm string from the challenge */ if(!sasl_digest_get_key_value(chlg, "algorithm=", alg, sizeof(alg), ',')) { Curl_safefree(chlg); return CURLE_LOGIN_DENIED; } Curl_safefree(chlg); /* We do not support other algorithms */ if(strcmp(alg, "md5-sess") != 0) return CURLE_LOGIN_DENIED; /* Generate 64 bits of random data */ for(i = 0; i < 8; i++) cnonce[i] = table16[Curl_rand()%16]; /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) userp, curlx_uztoui(strlen(userp))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) realm, curlx_uztoui(strlen(realm))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) passwdp, curlx_uztoui(strlen(passwdp))); Curl_MD5_final(ctxt, digest); ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_final(ctxt, digest); /* Convert calculated 16 octet hex into 32 bytes string */ for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]); /* Prepare the URL string */ snprintf(uri, sizeof(uri), "%s/%s", service, realm); /* Calculate H(A2) */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) method, curlx_uztoui(strlen(method))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) uri, curlx_uztoui(strlen(uri))); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]); /* Now calculate the response hash */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, curlx_uztoui(strlen(nonceCount))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) qop, curlx_uztoui(strlen(qop))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); snprintf(response, sizeof(response), "username=\"%s\",realm=\"%s\",nonce=\"%s\"," "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s", userp, realm, nonce, cnonce, nonceCount, uri, resp_hash_hex); /* Base64 encode the reply */ return Curl_base64_encode(data, response, 0, outptr, outlen); }
/* * Curl_sasl_create_digest_md5_message() * * This is used to generate an already encoded DIGEST-MD5 response message * ready for sending to the recipient. * * Parameters: * * data [in] - The session handle. * chlg64 [in] - Pointer to the base64 encoded challenge message. * userp [in] - The user name. * passdwp [in] - The user's password. * service [in] - The service type such as www, smtp, pop or imap. * outptr [in/out] - The address where a pointer to newly allocated memory * holding the result will be stored upon completion. * outlen [out] - The length of the output message. * * Returns CURLE_OK on success. */ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, const char *chlg64, const char *userp, const char *passwdp, const char *service, char **outptr, size_t *outlen) { #ifndef DEBUGBUILD static const char table16[] = "0123456789abcdef"; #endif CURLcode result = CURLE_OK; size_t i; MD5_context *ctxt; char *response = NULL; unsigned char digest[MD5_DIGEST_LEN]; char HA1_hex[2 * MD5_DIGEST_LEN + 1]; char HA2_hex[2 * MD5_DIGEST_LEN + 1]; char resp_hash_hex[2 * MD5_DIGEST_LEN + 1]; char nonce[64]; char realm[128]; char algorithm[64]; char qop_options[64]; int qop_values; char nonceCount[] = "00000001"; char cnonce[] = "12345678"; /* will be changed */ char method[] = "AUTHENTICATE"; char qop[] = DIGEST_QOP_VALUE_STRING_AUTH; char uri[128]; /* Decode the challange message */ result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce), realm, sizeof(realm), algorithm, sizeof(algorithm), qop_options, sizeof(qop_options)); if(result) return result; /* We only support md5 sessions */ if(strcmp(algorithm, "md5-sess") != 0) return CURLE_BAD_CONTENT_ENCODING; /* Get the qop-values from the qop-options */ result = sasl_digest_get_qop_values(qop_options, &qop_values); if(result) return result; /* We only support auth quality-of-protection */ if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) return CURLE_BAD_CONTENT_ENCODING; #ifndef DEBUGBUILD /* Generate 64 bits of random data */ for(i = 0; i < 8; i++) cnonce[i] = table16[Curl_rand(data)%16]; #endif /* So far so good, now calculate A1 and H(A1) according to RFC 2831 */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) userp, curlx_uztoui(strlen(userp))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) realm, curlx_uztoui(strlen(realm))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) passwdp, curlx_uztoui(strlen(passwdp))); Curl_MD5_final(ctxt, digest); ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_final(ctxt, digest); /* Convert calculated 16 octet hex into 32 bytes string */ for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]); /* Prepare the URL string */ snprintf(uri, sizeof(uri), "%s/%s", service, realm); /* Calculate H(A2) */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) method, curlx_uztoui(strlen(method))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) uri, curlx_uztoui(strlen(uri))); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&HA2_hex[2 * i], 3, "%02x", digest[i]); /* Now calculate the response hash */ ctxt = Curl_MD5_init(Curl_DIGEST_MD5); if(!ctxt) return CURLE_OUT_OF_MEMORY; Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonce, curlx_uztoui(strlen(nonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, curlx_uztoui(strlen(nonceCount))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) qop, curlx_uztoui(strlen(qop))); Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) snprintf(&resp_hash_hex[2 * i], 3, "%02x", digest[i]); /* Generate the response */ response = aprintf("username=\"%s\",realm=\"%s\",nonce=\"%s\"," "cnonce=\"%s\",nc=\"%s\",digest-uri=\"%s\",response=%s", userp, realm, nonce, cnonce, nonceCount, uri, resp_hash_hex); if(!response) return CURLE_OUT_OF_MEMORY; /* Base64 encode the response */ result = Curl_base64_encode(data, response, 0, outptr, outlen); Curl_safefree(response); return result; }