#include "MD5.h" #include #include "HTTPDigest.h" #ifdef _WIN32 //#define strcasecmp _stricmp //#define strncasecmp _strnicmp #endif #ifdef _MSC_VER #define strcasecmp _stricmp #define strncasecmp _strnicmp #endif void my_CvtHex( IN HASH Bin, OUT HASHHEX Hex ) { unsigned short i; unsigned char j; for (i = 0; i < HASHLEN; i++) { j = (Bin[i] >> 4) & 0xf; if (j <= 9) Hex[i*2] = (j + '0'); else Hex[i*2] = (j + 'a' - 10); j = Bin[i] & 0xf; if (j <= 9) Hex[i*2+1] = (j + '0'); else Hex[i*2+1] = (j + 'a' - 10); }; Hex[HASHHEXLEN] = '\0'; } /* calculate H(A1) as per spec */ void DigestCalcHA1 (IN const char *pszAlg, IN const char *pszUserName, IN const char *pszRealm, IN const char *pszPassword, IN const char *pszNonce, IN const char *pszCNonce, OUT HASHHEX SessionKey) { MD5_CTX Md5Ctx; HASH HA1; MD5Init (&Md5Ctx); MD5Update (&Md5Ctx, (unsigned char *) pszUserName, (unsigned int) strlen (pszUserName)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszRealm, (unsigned int) strlen (pszRealm)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszPassword, (unsigned int) strlen (pszPassword)); MD5Final ((unsigned char *) HA1, &Md5Ctx); if ((pszAlg != NULL) && strcasecmp (pszAlg, "md5-sess") == 0) { MD5Init (&Md5Ctx); MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHLEN); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, (unsigned int) strlen (pszCNonce)); MD5Final ((unsigned char *) HA1, &Md5Ctx); } my_CvtHex (HA1, SessionKey); } /* calculate request-digest/response-digest as per HTTP Digest spec */ void DigestCalcResponse (IN HASHHEX HA1, /* H(A1) */ IN const char *pszNonce, /* nonce from server */ IN const char *pszNonceCount, /* 8 hex digits */ IN const char *pszCNonce, /* client nonce */ IN const char *pszQop, /* qop-value: "", "auth", "auth-int" */ IN int Aka, /* Calculating AKAv1-MD5 response */ IN const char *pszMethod, /* method from the request */ IN const char *pszDigestUri, /* requested URL */ IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ OUT HASHHEX Response /* request-digest or response-digest */ ) { MD5_CTX Md5Ctx; HASH HA2; HASH RespHash; HASHHEX HA2Hex; /* calculate H(A2) */ MD5Init (&Md5Ctx); MD5Update (&Md5Ctx, (unsigned char *) pszMethod, (unsigned int) strlen (pszMethod)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszDigestUri, (unsigned int) strlen (pszDigestUri)); if (pszQop == NULL) { goto auth_withoutqop; } else if (0 == strcasecmp (pszQop, "auth-int")) { goto auth_withauth_int; } else if (0 == strcasecmp (pszQop, "auth")) { goto auth_withauth; } auth_withoutqop: MD5Final ((unsigned char *) HA2, &Md5Ctx); my_CvtHex (HA2, HA2Hex); /* calculate response */ MD5Init (&Md5Ctx); MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); goto end; auth_withauth_int: MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) HEntity, HASHHEXLEN); auth_withauth: MD5Final ((unsigned char *) HA2, &Md5Ctx); my_CvtHex (HA2, HA2Hex); /* calculate response */ MD5Init (&Md5Ctx); MD5Update (&Md5Ctx, (unsigned char *) HA1, HASHHEXLEN); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszNonce, (unsigned int) strlen (pszNonce)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); if (Aka == 0) { MD5Update (&Md5Ctx, (unsigned char *) pszNonceCount, (unsigned int) strlen (pszNonceCount)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszCNonce, (unsigned int) strlen (pszCNonce)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); MD5Update (&Md5Ctx, (unsigned char *) pszQop, (unsigned int) strlen (pszQop)); MD5Update (&Md5Ctx, (unsigned char *) ":", 1); } end: MD5Update (&Md5Ctx, (unsigned char *) HA2Hex, HASHHEXLEN); MD5Final ((unsigned char *) RespHash, &Md5Ctx); my_CvtHex (RespHash, Response); }