20 #include <openssl/ssl.h> 21 #include <openssl/md5.h> 25 using std::ostringstream;
28 const string HTTPDigestAuthorization::_mechanism =
"digest";
33 HTTPDigestAuthorization::
34 HTTPDigestAuthorization(
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()) {
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()) {
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());
102 HTTPDigestAuthorization::
103 ~HTTPDigestAuthorization() {
111 bool HTTPDigestAuthorization::
113 return (_algorithm != A_unknown);
120 const string &HTTPDigestAuthorization::
121 get_mechanism()
const {
130 string HTTPDigestAuthorization::
131 generate(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();
167 int HTTPDigestAuthorization::
168 match_qop_token(
const string &token) {
169 if (token ==
"auth") {
171 }
else if (token ==
"auth-int") {
180 string HTTPDigestAuthorization::
181 calc_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());
207 string HTTPDigestAuthorization::
208 calc_h(
const string &data)
const {
209 switch (_algorithm) {
213 return calc_md5(data);
223 string HTTPDigestAuthorization::
224 calc_kd(
const string &secret,
const string &data)
const {
225 switch (_algorithm) {
229 return calc_h(secret +
":" + data);
238 string HTTPDigestAuthorization::
239 get_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;
259 string HTTPDigestAuthorization::
260 get_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;
281 string HTTPDigestAuthorization::
282 get_hex_nonce_count()
const {
284 strm << std::hex << std::setfill(
'0') << std::setw(8) << _nonce_count;
292 string HTTPDigestAuthorization::
293 calc_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);
310 operator << (ostream &out, HTTPDigestAuthorization::Algorithm algorithm) {
312 case HTTPDigestAuthorization::A_md5:
315 case HTTPDigestAuthorization::A_md5_sess:
318 case HTTPDigestAuthorization::A_unknown:
327 operator << (ostream &out, HTTPDigestAuthorization::Qop qop) {
329 case HTTPDigestAuthorization::Q_auth:
332 case HTTPDigestAuthorization::Q_auth_int:
335 case HTTPDigestAuthorization::Q_unused:
343 #endif // HAVE_OPENSSL A container for a URL, e.g.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const std::string & get_url() const
Returns the complete URL specification.