OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_auth_handler_digest.h" | 5 #include "net/http/http_auth_handler_digest.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/md5.h" | 10 #include "base/md5.h" |
11 #include "base/rand_util.h" | 11 #include "base/rand_util.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
16 #include "net/base/net_util.h" | 16 #include "net/base/net_util.h" |
17 #include "net/http/http_auth.h" | 17 #include "net/http/http_auth.h" |
18 #include "net/http/http_request_info.h" | 18 #include "net/http/http_request_info.h" |
19 #include "net/http/http_util.h" | 19 #include "net/http/http_util.h" |
20 | 20 |
21 // TODO(eroman): support qop=auth-int | |
22 | |
23 namespace net { | 21 namespace net { |
24 | 22 |
25 // Digest authentication is specified in RFC 2617. | 23 // Digest authentication is specified in RFC 2617. |
26 // The expanded derivations are listed in the tables below. | 24 // The expanded derivations are listed in the tables below. |
27 | 25 |
28 //==========+==========+==========================================+ | 26 //==========+==========+==========================================+ |
29 // qop |algorithm | response | | 27 // qop |algorithm | response | |
30 //==========+==========+==========================================+ | 28 //==========+==========+==========================================+ |
31 // ? | ?, md5, | MD5(MD5(A1):nonce:MD5(A2)) | | 29 // ? | ?, md5, | MD5(MD5(A1):nonce:MD5(A2)) | |
32 // | md5-sess | | | 30 // | md5-sess | | |
(...skipping 25 matching lines...) Expand all Loading... | |
58 if (fixed_cnonce_) | 56 if (fixed_cnonce_) |
59 return std::string(domain); | 57 return std::string(domain); |
60 std::string cnonce; | 58 std::string cnonce; |
61 cnonce.reserve(16); | 59 cnonce.reserve(16); |
62 for (int i = 0; i < 16; ++i) | 60 for (int i = 0; i < 16; ++i) |
63 cnonce.push_back(domain[base::RandInt(0, 15)]); | 61 cnonce.push_back(domain[base::RandInt(0, 15)]); |
64 return cnonce; | 62 return cnonce; |
65 } | 63 } |
66 | 64 |
67 // static | 65 // static |
68 std::string HttpAuthHandlerDigest::QopToString(int qop) { | 66 std::string HttpAuthHandlerDigest::QopToString(int qop) { |
eroman
2010/11/11 23:02:58
I think this function should be changed to either
| |
69 switch (qop) { | 67 // qop is a bitmask, so report highest priority one first. |
70 case QOP_AUTH: | 68 if (qop & QOP_AUTH_INT) { |
71 return "auth"; | 69 return "auth-int"; |
72 case QOP_AUTH_INT: | 70 } else if (qop & QOP_AUTH) { |
eroman
2010/11/11 23:02:58
style: we avoid "else" when using returns.
As in:
| |
73 return "auth-int"; | 71 return "auth"; |
74 default: | 72 } else { |
75 return ""; | 73 return ""; |
76 } | 74 } |
77 } | 75 } |
78 | 76 |
79 // static | 77 // static |
80 std::string HttpAuthHandlerDigest::AlgorithmToString(int algorithm) { | 78 std::string HttpAuthHandlerDigest::AlgorithmToString(int algorithm) { |
81 switch (algorithm) { | 79 switch (algorithm) { |
82 case ALGORITHM_MD5: | 80 case ALGORITHM_MD5: |
83 return "MD5"; | 81 return "MD5"; |
84 case ALGORITHM_MD5_SESS: | 82 case ALGORITHM_MD5_SESS: |
85 return "MD5-sess"; | 83 return "MD5-sess"; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 const std::string& cnonce, | 143 const std::string& cnonce, |
146 const std::string& nc) const { | 144 const std::string& nc) const { |
147 // ha1 = MD5(A1) | 145 // ha1 = MD5(A1) |
148 // TODO(eroman): is this the right encoding? | 146 // TODO(eroman): is this the right encoding? |
149 std::string ha1 = MD5String(UTF16ToUTF8(username) + ":" + realm_ + ":" + | 147 std::string ha1 = MD5String(UTF16ToUTF8(username) + ":" + realm_ + ":" + |
150 UTF16ToUTF8(password)); | 148 UTF16ToUTF8(password)); |
151 if (algorithm_ == HttpAuthHandlerDigest::ALGORITHM_MD5_SESS) | 149 if (algorithm_ == HttpAuthHandlerDigest::ALGORITHM_MD5_SESS) |
152 ha1 = MD5String(ha1 + ":" + nonce_ + ":" + cnonce); | 150 ha1 = MD5String(ha1 + ":" + nonce_ + ":" + cnonce); |
153 | 151 |
154 // ha2 = MD5(A2) | 152 // ha2 = MD5(A2) |
155 // TODO(eroman): need to add MD5(req-entity-body) for qop=auth-int. | 153 // TODO(eroman): need to add MD5(req-entity-body) for qop=auth-int. |
eroman
2010/11/11 23:02:58
Can you add an assertion here that qop is not auth
| |
156 std::string ha2 = MD5String(method + ":" + path); | 154 std::string ha2 = MD5String(method + ":" + path); |
157 | 155 |
158 std::string nc_part; | 156 std::string nc_part; |
159 if (qop_ != HttpAuthHandlerDigest::QOP_UNSPECIFIED) { | 157 if (qop_ != HttpAuthHandlerDigest::QOP_UNSPECIFIED) { |
160 nc_part = nc + ":" + cnonce + ":" + QopToString(qop_) + ":"; | 158 nc_part = nc + ":" + cnonce + ":" + QopToString(qop_) + ":"; |
161 } | 159 } |
162 | 160 |
163 return MD5String(ha1 + ":" + nonce_ + ":" + nc_part + ha2); | 161 return MD5String(ha1 + ":" + nonce_ + ":" + nc_part + ha2); |
164 } | 162 } |
165 | 163 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 algorithm_ = ALGORITHM_MD5; | 300 algorithm_ = ALGORITHM_MD5; |
303 } else if (LowerCaseEqualsASCII(value, "md5-sess")) { | 301 } else if (LowerCaseEqualsASCII(value, "md5-sess")) { |
304 algorithm_ = ALGORITHM_MD5_SESS; | 302 algorithm_ = ALGORITHM_MD5_SESS; |
305 } else { | 303 } else { |
306 DVLOG(1) << "Unknown value of algorithm"; | 304 DVLOG(1) << "Unknown value of algorithm"; |
307 return false; // FAIL -- unsupported value of algorithm. | 305 return false; // FAIL -- unsupported value of algorithm. |
308 } | 306 } |
309 } else if (LowerCaseEqualsASCII(name, "qop")) { | 307 } else if (LowerCaseEqualsASCII(name, "qop")) { |
310 // Parse the comma separated list of qops. | 308 // Parse the comma separated list of qops. |
311 HttpUtil::ValuesIterator qop_values(value.begin(), value.end(), ','); | 309 HttpUtil::ValuesIterator qop_values(value.begin(), value.end(), ','); |
310 int qop = QOP_UNSPECIFIED; | |
312 while (qop_values.GetNext()) { | 311 while (qop_values.GetNext()) { |
313 if (LowerCaseEqualsASCII(qop_values.value(), "auth")) { | 312 if (LowerCaseEqualsASCII(qop_values.value(), "auth")) { |
314 qop_ |= QOP_AUTH; | 313 qop |= QOP_AUTH; |
315 } else if (LowerCaseEqualsASCII(qop_values.value(), "auth-int")) { | 314 } else if (LowerCaseEqualsASCII(qop_values.value(), "auth-int")) { |
316 qop_ |= QOP_AUTH_INT; | 315 qop |= QOP_AUTH_INT; |
317 } | 316 } |
318 } | 317 } |
318 // TODO(cbentzel): Since auth-int isn't currently supported, fail | |
319 // parsing if it is the only qop option available. | |
320 // http://crbug.com/45194 | |
321 if (qop == QOP_AUTH_INT) | |
322 return false; | |
eroman
2010/11/11 23:02:58
I suggest outputting some sort of warning or log m
| |
323 qop_ = (qop & ~QOP_AUTH_INT); | |
319 } else { | 324 } else { |
320 DVLOG(1) << "Skipping unrecognized digest property"; | 325 DVLOG(1) << "Skipping unrecognized digest property"; |
321 // TODO(eroman): perhaps we should fail instead of silently skipping? | 326 // TODO(eroman): perhaps we should fail instead of silently skipping? |
322 } | 327 } |
323 return true; | 328 return true; |
324 } | 329 } |
325 | 330 |
326 HttpAuthHandlerDigest::Factory::Factory() { | 331 HttpAuthHandlerDigest::Factory::Factory() { |
327 } | 332 } |
328 | 333 |
(...skipping 12 matching lines...) Expand all Loading... | |
341 // method and only constructing when valid. | 346 // method and only constructing when valid. |
342 scoped_ptr<HttpAuthHandler> tmp_handler( | 347 scoped_ptr<HttpAuthHandler> tmp_handler( |
343 new HttpAuthHandlerDigest(digest_nonce_count)); | 348 new HttpAuthHandlerDigest(digest_nonce_count)); |
344 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) | 349 if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) |
345 return ERR_INVALID_RESPONSE; | 350 return ERR_INVALID_RESPONSE; |
346 handler->swap(tmp_handler); | 351 handler->swap(tmp_handler); |
347 return OK; | 352 return OK; |
348 } | 353 } |
349 | 354 |
350 } // namespace net | 355 } // namespace net |
OLD | NEW |