| 4631 | |
| 4632 | #ifdef CPPHTTPLIB_OPENSSL_SUPPORT |
| 4633 | inline std::pair<std::string, std::string> make_digest_authentication_header( |
| 4634 | const Request &req, const std::map<std::string, std::string> &auth, |
| 4635 | size_t cnonce_count, const std::string &cnonce, const std::string &username, |
| 4636 | const std::string &password, bool is_proxy = false) { |
| 4637 | std::string nc; |
| 4638 | { |
| 4639 | std::stringstream ss; |
| 4640 | ss << std::setfill('0') << std::setw(8) << std::hex << cnonce_count; |
| 4641 | nc = ss.str(); |
| 4642 | } |
| 4643 | |
| 4644 | std::string qop; |
| 4645 | if (auth.find("qop") != auth.end()) { |
| 4646 | qop = auth.at("qop"); |
| 4647 | if (qop.find("auth-int") != std::string::npos) { |
| 4648 | qop = "auth-int"; |
| 4649 | } else if (qop.find("auth") != std::string::npos) { |
| 4650 | qop = "auth"; |
| 4651 | } else { |
| 4652 | qop.clear(); |
| 4653 | } |
| 4654 | } |
| 4655 | |
| 4656 | std::string algo = "MD5"; |
| 4657 | if (auth.find("algorithm") != auth.end()) { algo = auth.at("algorithm"); } |
| 4658 | |
| 4659 | std::string response; |
| 4660 | { |
| 4661 | auto H = algo == "SHA-256" ? detail::SHA_256 |
| 4662 | : algo == "SHA-512" ? detail::SHA_512 |
| 4663 | : detail::MD5; |
| 4664 | |
| 4665 | auto A1 = username + ":" + auth.at("realm") + ":" + password; |
| 4666 | |
| 4667 | auto A2 = req.method + ":" + req.path; |
| 4668 | if (qop == "auth-int") { A2 += ":" + H(req.body); } |
| 4669 | |
| 4670 | if (qop.empty()) { |
| 4671 | response = H(H(A1) + ":" + auth.at("nonce") + ":" + H(A2)); |
| 4672 | } else { |
| 4673 | response = H(H(A1) + ":" + auth.at("nonce") + ":" + nc + ":" + cnonce + |
| 4674 | ":" + qop + ":" + H(A2)); |
| 4675 | } |
| 4676 | } |
| 4677 | |
| 4678 | auto opaque = (auth.find("opaque") != auth.end()) ? auth.at("opaque") : ""; |
| 4679 | |
| 4680 | auto field = "Digest username=\"" + username + "\", realm=\"" + |
| 4681 | auth.at("realm") + "\", nonce=\"" + auth.at("nonce") + |
| 4682 | "\", uri=\"" + req.path + "\", algorithm=" + algo + |
| 4683 | (qop.empty() ? ", response=\"" |
| 4684 | : ", qop=" + qop + ", nc=" + nc + ", cnonce=\"" + |
| 4685 | cnonce + "\", response=\"") + |
| 4686 | response + "\"" + |
| 4687 | (opaque.empty() ? "" : ", opaque=\"" + opaque + "\""); |
| 4688 | |
| 4689 | auto key = is_proxy ? "Proxy-Authorization" : "Authorization"; |
| 4690 | return std::make_pair(key, field); |