/*---------------------------------------------------------------------------*/ HTTP_INT32 _HTTP_RealmPrintAuthorization ( HTTPAuthenticationRealm *realm, const HTTP_CHAR* method, const HTTP_CHAR* path, HTTP_INT32 (*writeFn) ( void* requestStream, const HTTP_CHAR* data, HTTP_INT32 len ), void* requestStream ) { switch (realm->scheme) { case HTTP_AUTHENTICATION_BASIC: if (realm->userName[0]) { HTTP_INT32 len = 0; char auth[HTTP_CFG_MAX_USERNAME_LEN + HTTP_CFG_MAX_PASSWORD_LEN]; char encoded[((HTTP_CFG_MAX_USERNAME_LEN + HTTP_CFG_MAX_PASSWORD_LEN) * 4 + 2) /3]; len = sizeof(HTTP_CLIENT_BASIC_STR) / sizeof(HTTP_CHAR) - sizeof(HTTP_CHAR); writeFn(requestStream, HTTP_CLIENT_BASIC_STR, len); writeFn(requestStream, " ", 1); tc_strcpy(auth, realm->userName); tc_strcat(auth, ":"); tc_strcat(auth, realm->password); len = _HTTP_Base64Encode(encoded, (HTTP_UINT8*) auth, (HTTP_INT32) tc_strlen(auth)); writeFn(requestStream, encoded, len); return (len); } break; case HTTP_AUTHENTICATION_DIGEST: if (realm->userName[0]) { HTTP_INT32 len = 0; HTTP_MD5_CTX md5Ctx; HTTP_CHAR hashA1[32]; HTTP_CHAR hashA2[32]; HTTP_CHAR finalHash[33]; /* according to RFC 2617, credentials = "Digest" digest-response where digest-response = "username=\"" + <user-name> + "\", realm=\"" + <realm-name> + "\", nonce=\"" + <server-nonce> + "\", uri=\"" + <path> + "\", response=\"" + (qop == auth || qop == auth-int)? KD(H(A1), <nonce> + ":" + <nonce-count> + ":" + <cnonce> + ":" + <qop> + ":" + H(A2)) : KD(H(A1), <nonce> + ":" + H(A2)) A1 = <user-name> + ":" + <realm-name> + ":" + <password> A2 = <method (GET,POST,etc)> + ":" + <path> H(X) = MD5(X), as a 32-character HEX string KD(I,J) = H(I + ":" + J); */ len = 17 /*Digest username="******", realm="*/ + tc_strlen(realm->realmName) + 10 /*", nonce="*/ + tc_strlen(realm->param.digest.serverNonce) + 8 /*", uri="*/ + tc_strlen(path) + 13 /*", response="*/ + 32 /* MD5 hash */ + 1; writeFn(requestStream, "Digest username=\"", 17); writeFn(requestStream, realm->userName, tc_strlen(realm->userName)); writeFn(requestStream, "\", realm=\"", 10); writeFn(requestStream, realm->realmName, tc_strlen(realm->realmName)); writeFn(requestStream, "\", nonce=\"", 10); writeFn(requestStream, realm->param.digest.serverNonce, tc_strlen(realm->param.digest.serverNonce)); writeFn(requestStream, "\", uri=\"", 8); writeFn(requestStream, path, tc_strlen(path)); writeFn(requestStream, "\", response=\"", 13); /*-----------------------------------------------------*/ /* find H(A1) */ /* if (algorithm == MD5) */ HTTP_MD5_Init(&md5Ctx); HTTP_MD5_Update(&md5Ctx, realm->userName, tc_strlen(realm->userName)); /* TBD!!! - what if HTTP_CHAR is not ASCII 8bit ? */ HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, realm->realmName, tc_strlen(realm->realmName)); HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, realm->password, tc_strlen(realm->password)); HTTP_MD5_Final(&md5Ctx); if (realm->param.digest.hashAlgorithm == HTTP_ALGORITHM_MD5_SESS) { HTTP_UINT8 HA1[16]; tc_memcpy(HA1, md5Ctx.digest, 16); HTTP_MD5_Init(&md5Ctx); HTTP_MD5_Update(&md5Ctx, HA1, 16); HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, realm->param.digest.serverNonce, tc_strlen(realm->param.digest.serverNonce)); HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, realm->param.digest.clientNonce, tc_strlen(realm->param.digest.clientNonce)); HTTP_MD5_Final(&md5Ctx); } _HTTP_HashToHex(hashA1, md5Ctx.digest, 16); /*-----------------------------------------------------*/ /* find H(A2) */ /* if (QOP == auth || QOP == none) */ HTTP_MD5_Init(&md5Ctx); HTTP_MD5_Update(&md5Ctx, method, tc_strlen(method)); HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, path, tc_strlen(path)); if (realm->param.digest.qop == HTTP_QOP_AUTH_INT) { HTTP_MD5_Update(&md5Ctx, ":", 1); /* What is HEntity!?!? */ /*HTTP_MD5_Update(&md5Ctx, HEntity, HASHHEXLEN);*/ } HTTP_MD5_Final(&md5Ctx); _HTTP_HashToHex(hashA2, md5Ctx.digest, 16); HTTP_MD5_Init(&md5Ctx); HTTP_MD5_Update(&md5Ctx, hashA1, 32); HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, realm->param.digest.serverNonce, tc_strlen(realm->param.digest.serverNonce)); HTTP_MD5_Update(&md5Ctx, ":", 1); if (realm->param.digest.qop == HTTP_QOP_AUTH || realm->param.digest.qop == HTTP_QOP_AUTH_INT) { HTTP_CHAR nonceCountStr[8]; _HTTP_UINT32ToHex(nonceCountStr, realm->param.digest.nonceCount); HTTP_MD5_Update(&md5Ctx, nonceCountStr, 8); HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, realm->param.digest.clientNonce, tc_strlen(realm->param.digest.clientNonce)); HTTP_MD5_Update(&md5Ctx, ":", 1); HTTP_MD5_Update(&md5Ctx, httpAuthQoPNames[realm->param.digest.qop], tc_strlen(httpAuthQoPNames[realm->param.digest.qop])); HTTP_MD5_Update(&md5Ctx, ":", 1); } HTTP_MD5_Update(&md5Ctx, hashA2, 32); HTTP_MD5_Final(&md5Ctx); _HTTP_HashToHex(finalHash, md5Ctx.digest, 16); finalHash[32] = '\"'; writeFn(requestStream, finalHash, 33); return (len); } break; default: break; } return (0); }
void doSummat(void writeFn(int,int)) { // ... writeFn(12,16); // ... }