2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.0 of the PHP license, that |
6 | is bundled with this package in the file LICENSE, and is available |
7 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
8 | If you did not receive a copy of the PHP license and are unable to |
9 | obtain it through the world-wide-web, please send a note to |
10 | license@php.net so we can mail you a copy immediately. |
11 +----------------------------------------------------------------------+
12 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
13 +----------------------------------------------------------------------+
23 #include "ext/standard/base64.h"
28 #include "php_http_api.h"
29 #include "php_http_std_defs.h"
30 #include "php_http_send_api.h"
37 /* {{{ STATUS http_auth_basic_header(char*) */
38 PHP_HTTP_API STATUS
_http_auth_basic_header(const char *realm TSRMLS_DC
)
40 char realm_header
[1024] = {0};
41 snprintf(realm_header
, 1023, "WWW-Authenticate: Basic realm=\"%s\"", realm
);
42 return http_send_status_header(401, realm_header
);
46 /* {{{ STATUS http_auth_credentials(char **, char **) */
47 PHP_HTTP_API STATUS
_http_auth_basic_credentials(char **user
, char **pass TSRMLS_DC
)
49 if (strncmp(sapi_module
.name
, "isapi", 5)) {
52 HTTP_GSC(zuser
, "PHP_AUTH_USER", FAILURE
);
53 HTTP_GSC(zpass
, "PHP_AUTH_PW", FAILURE
);
55 *user
= estrndup(Z_STRVAL_P(zuser
), Z_STRLEN_P(zuser
));
56 *pass
= estrndup(Z_STRVAL_P(zpass
), Z_STRLEN_P(zpass
));
61 HTTP_GSC(zauth
, "HTTP_AUTHORIZATION", FAILURE
);
64 char *colon
, *decoded
= php_base64_decode(Z_STRVAL_P(zauth
), Z_STRLEN_P(zauth
), &decoded_len
);
66 if (colon
= strchr(decoded
+ 6, ':')) {
67 *user
= estrndup(decoded
+ 6, colon
- decoded
- 6);
68 *pass
= estrndup(colon
+ 1, decoded
+ decoded_len
- colon
- 6 - 1);
82 #include "ext/standard/php_rand.h"
83 #include "ext/standard/md5.h"
85 #define DIGEST_ALGORITHM "MD5"
86 #define DIGEST_SECRETLEN 20
87 static unsigned char digest_secret[DIGEST_SECRETLEN];
89 #define DIGEST_BIN_LEN 16
90 typedef char http_digest_bin_t[DIGEST_BIN_LEN];
91 #define DIGEST_HEX_LEN 32
92 typedef char http_digest_hex_t[DIGEST_HEX_LEN+1];
94 void _http_auth_global_init(TSRMLS_D)
97 // XX this is pretty loose
98 for (i = 0; i < DIGEST_SECRETLEN; ++i) {
99 digest_secret[i] = (unsigned char) ((php_rand(TSRMLS_C) % 254) + 1);
103 static void http_digest_line_decoder(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
109 phpstr_init_ex(&s, encoded_len, 1);
111 for (i = 0; i < encoded_len; ++i) {
112 if ((encoded[i] != '\\') && (encoded[i] != '"')) {
113 phpstr_append(&s, encoded+i, 1);
119 *decoded = PHPSTR_VAL(&s);
120 *decoded_len = PHPSTR_LEN(&s);
123 static void http_digest_tohex(http_digest_bin_t bin, http_digest_hex_t hex)
128 for (i = 0; i < DIGEST_BIN_LEN; i++) {
129 j = (bin[i] >> 4) & 0xf;
131 hex[i*2] = (j + '0');
133 hex[i*2] = (j + 'a' - 10);
137 hex[i*2+1] = (j + '0');
139 hex[i*2+1] = (j + 'a' - 10);
142 hex[DIGEST_HEX_LEN] = '\0';
145 static void http_digest_calc_HA1(
146 const char *alg, const char *user,
147 const char *realm, const char *pass,
148 const char *nonce, const char *cnonce,
149 http_digest_hex_t HA1)
152 http_digest_bin_t HA1_bin;
155 PHP_MD5Update(&md5, user, strlen(user));
156 PHP_MD5Update(&md5, ":", 1);
157 PHP_MD5Update(&md5, realm, strlen(realm));
158 PHP_MD5Update(&md5, ":", 1);
159 PHP_MD5Update(&md5, pass, strlen(pass));
160 PHP_MD5Final(HA1_bin, &md5);
162 if (strcasecmp(alg, "md5-sess") == 0) {
164 PHP_MD5Update(&md5, HA1_bin, DIGEST_BIN_LEN);
165 PHP_MD5Update(&md5, ":", 1);
166 PHP_MD5Update(&md5, nonce, strlen(nonce));
167 PHP_MD5Update(&md5, ":", 1);
168 PHP_MD5Update(&md5, cnonce, strlen(cnonce));
169 PHP_MD5Final(HA1_bin, &md5);
171 http_digest_tohex(HA1_bin, HA1);
174 static void http_digest_calc_response(
175 const http_digest_hex_t HA1,
176 const char *nonce, const char *noncecount,
177 const char *cnonce, const char *qop,
178 const char *method, const char *uri,
179 http_digest_hex_t ent,
180 http_digest_hex_t response)
183 http_digest_bin_t HA2;
184 http_digest_bin_t bin;
185 http_digest_hex_t HA2_hex;
189 PHP_MD5Update(&md5, method, strlen(method));
190 PHP_MD5Update(&md5, ":", 1);
191 PHP_MD5Update(&md5, uri, strlen(uri));
192 if (strcasecmp(qop, "auth-int") == 0) {
193 PHP_MD5Update(&md5, ":", 1);
194 PHP_MD5Update(&md5, HEntity, DIGEST_HEX_LEN);
196 PHP_MD5Final(HA2, &md5);
197 http_digest_tohex(HA2, HA2_hex);
199 // calculate response
201 PHP_MD5Update(&md5, HA1, DIGEST_HEX_LEN);
202 PHP_MD5Update(&md5, ":", 1);
203 PHP_MD5Update(&md5, nonce, strlen(nonce));
204 PHP_MD5Update(&md5, ":", 1);
206 PHP_MD5Update(&md5, noncecount, strlen(noncecount));
207 PHP_MD5Update(&md5, ":", 1);
208 PHP_MD5Update(&md5, cnonce, strlen(cnonce));
209 PHP_MD5Update(&md5, ":", 1);
210 PHP_MD5Update(&md5, qop, strlen(qop));
211 PHP_MD5Update(&md5, ":", 1);
213 PHP_MD5Update(&md5, HA2_hex, DIGEST_HEX_LEN);
214 PHP_MD5Final(bin, &md5);
215 http_digest_tohex(bin, response);
218 PHP_HTTP_API STATUS _http_auth_digest_credentials(HashTable *items TSRMLS_DC)
221 zval array, *zauth = NULL;
223 HTTP_GSC(zauth, "HTTP_AUTHORIZATION", FAILURE);
224 auth = Z_STRVAL_P(zauth);
226 if (strncasecmp(auth, "Digest ", sizeof("Digest")) || (!(auth += sizeof("Digest")))) {
229 if (SUCCESS != http_parse_key_list(auth, items, ',', http_digest_line_decoder, 0)) {
232 if ( !zend_hash_exists(items, "uri", sizeof("uri")) ||
233 !zend_hash_exists(items, "realm", sizeof("realm")) ||
234 !zend_hash_exists(items, "nonce", sizeof("nonce")) ||
235 !zend_hash_exists(items, "username", sizeof("username")) ||
236 !zend_hash_exists(items, "response", sizeof("response"))) {
237 zend_hash_clean(items);
243 PHP_HTTP_API STATUS _http_auth_digest_header(const char *realm TSRMLS_DC)
255 * vim600: sw=4 ts=4 fdm=marker