20#include <openssl/ssl.h>
21#include <openssl/md5.h>
25using std::ostringstream;
28const string HTTPDigestAuthorization::_mechanism =
"digest";
33HTTPDigestAuthorization::
34HTTPDigestAuthorization(
const HTTPAuthorization::Tokens &tokens,
35 const URLSpec &url,
bool is_proxy) :
36 HTTPAuthorization(tokens, url, is_proxy)
38 Tokens::const_iterator ti;
39 ti = tokens.find(
"nonce");
40 if (ti != tokens.end()) {
41 _nonce = (*ti).second;
45 ti = tokens.find(
"opaque");
46 if (ti != tokens.end()) {
47 _opaque = (*ti).second;
51 ti = tokens.find(
"algorithm");
52 if (ti != tokens.end()) {
53 string algo_str = HTTPChannel::downcase((*ti).second);
54 if (algo_str ==
"md5") {
56 }
else if (algo_str ==
"md5-sess") {
57 _algorithm = A_md5_sess;
59 _algorithm = A_unknown;
64 ti = tokens.find(
"qop");
65 if (ti != tokens.end()) {
66 string qop_str = HTTPChannel::downcase((*ti).second);
70 while (p < qop_str.length()) {
71 while (p < qop_str.length() && isspace(qop_str[p])) {
76 while (q < qop_str.length() && qop_str[q] !=
',') {
77 if (!isspace(qop_str[q])) {
78 qop_str[q] = tolower(qop_str[q]);
85 _qop |= match_qop_token(qop_str.substr(p, last_char - p + 1));
93 strm << time(
nullptr) <<
":" << clock() <<
":"
96 _cnonce = calc_md5(strm.str());
102HTTPDigestAuthorization::
103~HTTPDigestAuthorization() {
111bool HTTPDigestAuthorization::
113 return (_algorithm != A_unknown);
120const string &HTTPDigestAuthorization::
121get_mechanism()
const {
130string HTTPDigestAuthorization::
131generate(HTTPEnum::Method method,
const string &request_path,
132 const string &username,
const string &body) {
135 size_t colon = username.find(
':');
136 string username_only = username.substr(0, colon);
137 string password_only = username.substr(colon + 1);
139 string digest = calc_request_digest(username_only, password_only,
140 method, request_path, body);
143 strm <<
"Digest username=\"" << username.substr(0, colon) <<
"\""
144 <<
", realm=\"" << get_realm() <<
"\""
145 <<
", nonce=\"" << _nonce <<
"\""
146 <<
", uri=" << request_path
147 <<
", response=\"" << digest <<
"\""
148 <<
", algorithm=" << _algorithm;
150 if (!_opaque.empty()) {
151 strm <<
", opaque=\"" << _opaque <<
"\"";
154 if (_chosen_qop != Q_unused) {
155 strm <<
", qop=" << _chosen_qop
156 <<
", cnonce=\"" << _cnonce <<
"\""
157 <<
", nc=" << get_hex_nonce_count();
167int HTTPDigestAuthorization::
168match_qop_token(
const string &token) {
169 if (token ==
"auth") {
171 }
else if (token ==
"auth-int") {
180string HTTPDigestAuthorization::
181calc_request_digest(
const string &username,
const string &password,
182 HTTPEnum::Method method,
const string &request_path,
183 const string &body) {
184 _chosen_qop = Q_unused;
185 string h_a1 = calc_h(get_a1(username, password));
186 string h_a2 = calc_h(get_a2(method, request_path, body));
191 _chosen_qop = Q_unused;
192 strm << _nonce <<
":" << h_a2;
195 strm << _nonce <<
":" << get_hex_nonce_count() <<
":"
196 << _cnonce <<
":" << _chosen_qop <<
":"
200 return calc_kd(h_a1, strm.str());
207string HTTPDigestAuthorization::
208calc_h(
const string &data)
const {
209 switch (_algorithm) {
213 return calc_md5(data);
223string HTTPDigestAuthorization::
224calc_kd(
const string &secret,
const string &data)
const {
225 switch (_algorithm) {
229 return calc_h(secret +
":" + data);
238string HTTPDigestAuthorization::
239get_a1(
const string &username,
const string &password) {
240 switch (_algorithm) {
243 return username +
":" + get_realm() +
":" + password;
247 _a1 = calc_h(username +
":" + get_realm() +
":" + password) +
248 ":" + _nonce +
":" + _cnonce;
259string HTTPDigestAuthorization::
260get_a2(HTTPEnum::Method method,
const string &request_path,
261 const string &body) {
264 if ((_qop & Q_auth_int) != 0 && !body.empty()) {
265 _chosen_qop = Q_auth_int;
266 strm << method <<
":" << request_path <<
":" << calc_h(body);
269 _chosen_qop = Q_auth;
270 strm << method <<
":" << request_path;
281string HTTPDigestAuthorization::
282get_hex_nonce_count()
const {
284 strm << std::hex << std::setfill(
'0') << std::setw(8) << _nonce_count;
292string HTTPDigestAuthorization::
293calc_md5(
const string &source) {
294 unsigned char binary[MD5_DIGEST_LENGTH];
296 MD5((
const unsigned char *)source.data(), source.length(), binary);
299 result.reserve(MD5_DIGEST_LENGTH * 2);
301 for (
int i = 0; i < MD5_DIGEST_LENGTH; i++) {
302 result += hexdigit((binary[i] >> 4) & 0xf);
303 result += hexdigit(binary[i] & 0xf);
310operator << (ostream &out, HTTPDigestAuthorization::Algorithm algorithm) {
312 case HTTPDigestAuthorization::A_md5:
315 case HTTPDigestAuthorization::A_md5_sess:
318 case HTTPDigestAuthorization::A_unknown:
327operator << (ostream &out, HTTPDigestAuthorization::Qop qop) {
329 case HTTPDigestAuthorization::Q_auth:
332 case HTTPDigestAuthorization::Q_auth_int:
335 case HTTPDigestAuthorization::Q_unused:
A container for a URL, e.g.
const std::string & get_url() const
Returns the complete URL specification.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.