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 +----------------------------------------------------------------------+
24 #include "ext/standard/base64.h"
27 #include "php_http_api.h"
28 #include "php_http_std_defs.h"
29 #include "php_http_send_api.h"
36 /* {{{ STATUS http_auth_basic_header(char*) */
37 PHP_HTTP_API STATUS
_http_auth_basic_header(const char *realm TSRMLS_DC
)
39 char realm_header
[1024] = {0};
40 snprintf(realm_header
, 1023, "WWW-Authenticate: Basic realm=\"%s\"", realm
);
41 return http_send_status_header(401, realm_header
);
45 /* {{{ STATUS http_auth_credentials(char **, char **) */
46 PHP_HTTP_API STATUS
_http_auth_basic_credentials(char **user
, char **pass TSRMLS_DC
)
48 if (strncmp(sapi_module
.name
, "isapi", 5)) {
51 HTTP_GSC(zuser
, "PHP_AUTH_USER", FAILURE
);
52 HTTP_GSC(zpass
, "PHP_AUTH_PW", FAILURE
);
54 *user
= estrndup(Z_STRVAL_P(zuser
), Z_STRLEN_P(zuser
));
55 *pass
= estrndup(Z_STRVAL_P(zpass
), Z_STRLEN_P(zpass
));
60 HTTP_GSC(zauth
, "HTTP_AUTHORIZATION", FAILURE
);
63 char *colon
, *decoded
= (char *) php_base64_decode((const unsigned char *) Z_STRVAL_P(zauth
), Z_STRLEN_P(zauth
), &decoded_len
);
65 if (colon
= strchr(decoded
+ 6, ':')) {
66 *user
= estrndup(decoded
+ 6, colon
- decoded
- 6);
67 *pass
= estrndup(colon
+ 1, decoded
+ decoded_len
- colon
- 6 - 1);
81 #include "ext/standard/php_rand.h"
82 #include "ext/standard/md5.h"
84 #define DIGEST_ALGORITHM "MD5"
85 #define DIGEST_SECRETLEN 20
86 static unsigned char digest_secret[DIGEST_SECRETLEN];
88 #define DIGEST_BIN_LEN 16
89 typedef char http_digest_bin_t[DIGEST_BIN_LEN];
90 #define DIGEST_HEX_LEN 32
91 typedef char http_digest_hex_t[DIGEST_HEX_LEN+1];
93 void _http_auth_global_init(TSRMLS_D)
96 // XX this is pretty loose
97 for (i = 0; i < DIGEST_SECRETLEN; ++i) {
98 digest_secret[i] = (unsigned char) ((php_rand(TSRMLS_C) % 254) + 1);
102 static void http_digest_line_decoder(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
108 phpstr_init_ex(&s, encoded_len, 1);
110 for (i = 0; i < encoded_len; ++i) {
111 if ((encoded[i] != '\\') && (encoded[i] != '"')) {
112 phpstr_append(&s, encoded+i, 1);
118 *decoded = PHPSTR_VAL(&s);
119 *decoded_len = PHPSTR_LEN(&s);
122 static void http_digest_tohex(http_digest_bin_t bin, http_digest_hex_t hex)
127 for (i = 0; i < DIGEST_BIN_LEN; i++) {
128 j = (bin[i] >> 4) & 0xf;
130 hex[i*2] = (j + '0');
132 hex[i*2] = (j + 'a' - 10);
136 hex[i*2+1] = (j + '0');
138 hex[i*2+1] = (j + 'a' - 10);
141 hex[DIGEST_HEX_LEN] = '\0';
144 static void http_digest_calc_HA1(
145 const char *alg, const char *user,
146 const char *realm, const char *pass,
147 const char *nonce, const char *cnonce,
148 http_digest_hex_t HA1)
151 http_digest_bin_t HA1_bin;
154 PHP_MD5Update(&md5, user, strlen(user));
155 PHP_MD5Update(&md5, ":", 1);
156 PHP_MD5Update(&md5, realm, strlen(realm));
157 PHP_MD5Update(&md5, ":", 1);
158 PHP_MD5Update(&md5, pass, strlen(pass));
159 PHP_MD5Final(HA1_bin, &md5);
161 if (strcasecmp(alg, "md5-sess") == 0) {
163 PHP_MD5Update(&md5, HA1_bin, DIGEST_BIN_LEN);
164 PHP_MD5Update(&md5, ":", 1);
165 PHP_MD5Update(&md5, nonce, strlen(nonce));
166 PHP_MD5Update(&md5, ":", 1);
167 PHP_MD5Update(&md5, cnonce, strlen(cnonce));
168 PHP_MD5Final(HA1_bin, &md5);
170 http_digest_tohex(HA1_bin, HA1);
173 static void http_digest_calc_response(
174 const http_digest_hex_t HA1,
175 const char *nonce, const char *noncecount,
176 const char *cnonce, const char *qop,
177 const char *method, const char *uri,
178 http_digest_hex_t ent,
179 http_digest_hex_t response)
182 http_digest_bin_t HA2;
183 http_digest_bin_t bin;
184 http_digest_hex_t HA2_hex;
188 PHP_MD5Update(&md5, method, strlen(method));
189 PHP_MD5Update(&md5, ":", 1);
190 PHP_MD5Update(&md5, uri, strlen(uri));
191 if (strcasecmp(qop, "auth-int") == 0) {
192 PHP_MD5Update(&md5, ":", 1);
193 PHP_MD5Update(&md5, HEntity, DIGEST_HEX_LEN);
195 PHP_MD5Final(HA2, &md5);
196 http_digest_tohex(HA2, HA2_hex);
198 // calculate response
200 PHP_MD5Update(&md5, HA1, DIGEST_HEX_LEN);
201 PHP_MD5Update(&md5, ":", 1);
202 PHP_MD5Update(&md5, nonce, strlen(nonce));
203 PHP_MD5Update(&md5, ":", 1);
205 PHP_MD5Update(&md5, noncecount, strlen(noncecount));
206 PHP_MD5Update(&md5, ":", 1);
207 PHP_MD5Update(&md5, cnonce, strlen(cnonce));
208 PHP_MD5Update(&md5, ":", 1);
209 PHP_MD5Update(&md5, qop, strlen(qop));
210 PHP_MD5Update(&md5, ":", 1);
212 PHP_MD5Update(&md5, HA2_hex, DIGEST_HEX_LEN);
213 PHP_MD5Final(bin, &md5);
214 http_digest_tohex(bin, response);
217 PHP_HTTP_API STATUS _http_auth_digest_credentials(HashTable *items TSRMLS_DC)
220 zval array, *zauth = NULL;
222 HTTP_GSC(zauth, "HTTP_AUTHORIZATION", FAILURE);
223 auth = Z_STRVAL_P(zauth);
225 if (strncasecmp(auth, "Digest ", sizeof("Digest")) || (!(auth += sizeof("Digest")))) {
228 if (SUCCESS != http_parse_key_list(auth, items, ',', http_digest_line_decoder, 0)) {
231 if ( !zend_hash_exists(items, "uri", sizeof("uri")) ||
232 !zend_hash_exists(items, "realm", sizeof("realm")) ||
233 !zend_hash_exists(items, "nonce", sizeof("nonce")) ||
234 !zend_hash_exists(items, "username", sizeof("username")) ||
235 !zend_hash_exists(items, "response", sizeof("response"))) {
236 zend_hash_clean(items);
242 PHP_HTTP_API STATUS _http_auth_digest_header(const char *realm TSRMLS_DC)
254 * vim600: sw=4 ts=4 fdm=marker