1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: namespace Cake\Http\Client\Auth;
15:
16: use Cake\Http\Client;
17: use Cake\Http\Client\Request;
18:
19: 20: 21: 22: 23: 24:
25: class Digest
26: {
27: 28: 29: 30: 31:
32: protected $_client;
33:
34: 35: 36: 37: 38: 39:
40: public function __construct(Client $client, $options = null)
41: {
42: $this->_client = $client;
43: }
44:
45: 46: 47: 48: 49: 50: 51: 52:
53: public function authentication(Request $request, array $credentials)
54: {
55: if (!isset($credentials['username'], $credentials['password'])) {
56: return $request;
57: }
58: if (!isset($credentials['realm'])) {
59: $credentials = $this->_getServerInfo($request, $credentials);
60: }
61: if (!isset($credentials['realm'])) {
62: return $request;
63: }
64: $value = $this->_generateHeader($request, $credentials);
65:
66: return $request->withHeader('Authorization', $value);
67: }
68:
69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79:
80: protected function _getServerInfo(Request $request, $credentials)
81: {
82: $response = $this->_client->get(
83: $request->getUri(),
84: [],
85: ['auth' => ['type' => null]]
86: );
87:
88: if (!$response->getHeader('WWW-Authenticate')) {
89: return [];
90: }
91: preg_match_all(
92: '@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@',
93: $response->getHeaderLine('WWW-Authenticate'),
94: $matches,
95: PREG_SET_ORDER
96: );
97: foreach ($matches as $match) {
98: $credentials[$match[1]] = $match[2];
99: }
100: if (!empty($credentials['qop']) && empty($credentials['nc'])) {
101: $credentials['nc'] = 1;
102: }
103:
104: return $credentials;
105: }
106:
107: 108: 109: 110: 111: 112: 113:
114: protected function _generateHeader(Request $request, $credentials)
115: {
116: $path = $request->getUri()->getPath();
117: $a1 = md5($credentials['username'] . ':' . $credentials['realm'] . ':' . $credentials['password']);
118: $a2 = md5($request->getMethod() . ':' . $path);
119: $nc = null;
120:
121: if (empty($credentials['qop'])) {
122: $response = md5($a1 . ':' . $credentials['nonce'] . ':' . $a2);
123: } else {
124: $credentials['cnonce'] = uniqid();
125: $nc = sprintf('%08x', $credentials['nc']++);
126: $response = md5($a1 . ':' . $credentials['nonce'] . ':' . $nc . ':' . $credentials['cnonce'] . ':auth:' . $a2);
127: }
128:
129: $authHeader = 'Digest ';
130: $authHeader .= 'username="' . str_replace(['\\', '"'], ['\\\\', '\\"'], $credentials['username']) . '", ';
131: $authHeader .= 'realm="' . $credentials['realm'] . '", ';
132: $authHeader .= 'nonce="' . $credentials['nonce'] . '", ';
133: $authHeader .= 'uri="' . $path . '", ';
134: $authHeader .= 'response="' . $response . '"';
135: if (!empty($credentials['opaque'])) {
136: $authHeader .= ', opaque="' . $credentials['opaque'] . '"';
137: }
138: if (!empty($credentials['qop'])) {
139: $authHeader .= ', qop="auth", nc=' . $nc . ', cnonce="' . $credentials['cnonce'] . '"';
140: }
141:
142: return $authHeader;
143: }
144: }
145:
146:
147: class_alias('Cake\Http\Client\Auth\Digest', 'Cake\Network\Http\Auth\Digest');
148: