123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #include "http_digest.h"
- #include <library/cpp/digest/md5/md5.h>
- #include <util/stream/output.h>
- #include <util/stream/str.h>
- /************************************************************/
- /************************************************************/
- static const char* WWW_PREFIX = "Authorization: Digest ";
- /************************************************************/
- httpDigestHandler::httpDigestHandler()
- : User_(nullptr)
- , Password_(nullptr)
- , Nonce_(nullptr)
- , NonceCount_(0)
- , HeaderInstruction_(nullptr)
- {
- }
- /************************************************************/
- httpDigestHandler::~httpDigestHandler() {
- clear();
- }
- /************************************************************/
- void httpDigestHandler::clear() {
- free(Nonce_);
- free(HeaderInstruction_);
- User_ = Password_ = nullptr;
- Nonce_ = HeaderInstruction_ = nullptr;
- NonceCount_ = 0;
- }
- /************************************************************/
- void httpDigestHandler::setAuthorization(const char* user, const char* password) {
- clear();
- if (user && password) {
- User_ = user;
- Password_ = password;
- }
- }
- /************************************************************/
- const char* httpDigestHandler::getHeaderInstruction() const {
- return HeaderInstruction_;
- }
- /************************************************************/
- Y_FORCE_INLINE void addMD5(MD5& ctx, const char* value) {
- ctx.Update((const unsigned char*)(value), strlen(value));
- }
- Y_FORCE_INLINE void addMD5(MD5& ctx, const char* value, int len) {
- ctx.Update((const unsigned char*)(value), len);
- }
- Y_FORCE_INLINE void addMD5(MD5& ctx, std::string_view str) {
- ctx.Update(str);
- }
- Y_FORCE_INLINE void addMD5Sep(MD5& ctx) {
- addMD5(ctx, ":", 1);
- }
- /************************************************************/
- /* calculate H(A1) as per spec */
- void httpDigestHandler::digestCalcHA1(const THttpAuthHeader& hd,
- char* outSessionKey,
- const std::string& outCNonce) {
- MD5 ctx;
- ctx.Init();
- addMD5(ctx, User_);
- addMD5Sep(ctx);
- addMD5(ctx, hd.realm);
- addMD5Sep(ctx);
- addMD5(ctx, Password_);
- if (hd.algorithm == 1) { //MD5-sess
- unsigned char digest[16];
- ctx.Final(digest);
- ctx.Init();
- ctx.Update(digest, 16);
- addMD5Sep(ctx);
- addMD5(ctx, hd.nonce);
- addMD5Sep(ctx);
- addMD5(ctx, outCNonce);
- ctx.End(outSessionKey);
- }
- ctx.End(outSessionKey);
- }
- /************************************************************/
- /* calculate request-digest/response-digest as per HTTP Digest spec */
- void httpDigestHandler::digestCalcResponse(const THttpAuthHeader& hd,
- const char* path,
- const char* method,
- const char* nonceCount,
- char* outResponse,
- const std::string& outCNonce) {
- char HA1[33];
- digestCalcHA1(hd, HA1, outCNonce);
- char HA2[33];
- MD5 ctx;
- ctx.Init();
- addMD5(ctx, method);
- addMD5Sep(ctx);
- addMD5(ctx, path);
- //ignore auth-int
- ctx.End(HA2);
- ctx.Init();
- addMD5(ctx, HA1, 32);
- addMD5Sep(ctx);
- addMD5(ctx, Nonce_);
- addMD5Sep(ctx);
- if (hd.qop_auth) {
- addMD5(ctx, nonceCount, 8);
- addMD5Sep(ctx);
- addMD5(ctx, outCNonce);
- addMD5Sep(ctx);
- addMD5(ctx, "auth", 4);
- addMD5Sep(ctx);
- }
- addMD5(ctx, HA2, 32);
- ctx.End(outResponse);
- }
- /************************************************************/
- bool httpDigestHandler::processHeader(const THttpAuthHeader* header,
- const char* path,
- const char* method,
- const char* cnonceIn) {
- if (!User_ || !header || !header->use_auth || !header->realm || !header->nonce)
- return false;
- if (Nonce_) {
- if (strcmp(Nonce_, header->nonce)) {
- free(Nonce_);
- Nonce_ = nullptr;
- NonceCount_ = 0;
- }
- }
- if (!Nonce_) {
- Nonce_ = strdup(header->nonce);
- NonceCount_ = 0;
- }
- free(HeaderInstruction_);
- HeaderInstruction_ = nullptr;
- NonceCount_++;
- char nonceCount[20];
- snprintf(nonceCount, sizeof(nonceCount), "%08d", NonceCount_);
- std::string cNonce = cnonceIn ? std::string(cnonceIn) : std::to_string(time(nullptr));
- char response[33];
- digestCalcResponse(*header, path, method, nonceCount, response, cNonce);
- //digest-response = 1#( username | realm | nonce | digest-uri
- // | response | [ algorithm ] | [cnonce] |
- // [opaque] | [message-qop] |
- // [nonce-count] | [auth-param] )
- TStringStream out;
- out << WWW_PREFIX << "username=\"" << User_ << "\"";
- out << ", realm=\"" << header->realm << "\"";
- out << ", nonce=\"" << header->nonce << "\"";
- out << ", uri=\"" << path << "\"";
- if (header->algorithm == 1)
- out << ", algorithm=MD5-sess";
- else
- out << ", algorithm=MD5";
- if (header->qop_auth)
- out << ", qop=auth";
- out << ", nc=" << nonceCount;
- if (!cNonce.empty())
- out << ", cnonce=\"" << cNonce << "\"";
- out << ", response=\"" << response << "\"";
- if (header->opaque)
- out << ", opaque=\"" << header->opaque << "\"";
- out << "\r\n";
- TString s_out = out.Str();
- HeaderInstruction_ = strdup(s_out.c_str());
- return true;
- }
- /************************************************************/
- /************************************************************/
|