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