dmitry          Tue Jan 25 06:03:20 2005 EDT

  Modified files:              
    /php-src/ext/soap   php_http.c 
  Log:
  Fixed bug #28041 (SOAP HTTP Digest Access Authentication was implemented)
  
  
http://cvs.php.net/diff.php/php-src/ext/soap/php_http.c?r1=1.63&r2=1.64&ty=u
Index: php-src/ext/soap/php_http.c
diff -u php-src/ext/soap/php_http.c:1.63 php-src/ext/soap/php_http.c:1.64
--- php-src/ext/soap/php_http.c:1.63    Thu Jan 20 12:29:16 2005
+++ php-src/ext/soap/php_http.c Tue Jan 25 06:03:20 2005
@@ -17,10 +17,11 @@
   |          Dmitry Stogov <[EMAIL PROTECTED]>                             |
   +----------------------------------------------------------------------+
 */
-/* $Id: php_http.c,v 1.63 2005/01/20 17:29:16 dmitry Exp $ */
+/* $Id: php_http.c,v 1.64 2005/01/25 11:03:20 dmitry Exp $ */
 
 #include "php_soap.h"
 #include "ext/standard/base64.h"
+#include "ext/standard/md5.h"
 
 static char *get_http_header_value(char *headers, char *type);
 static int get_http_body(php_stream *socketd, int close, char *headers,  char 
**response, int *out_size TSRMLS_DC);
@@ -126,7 +127,7 @@
                STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
                NULL /*persistent_id*/,
                NULL /*timeout*/,
-               context, 
+               context,
                NULL, NULL);
        efree(name);
 #else
@@ -199,13 +200,13 @@
   }
 }
 
-int make_http_soap_request(zval  *this_ptr, 
+int make_http_soap_request(zval  *this_ptr,
                            char  *buf,
                            int    buf_size,
-                           char  *location, 
-                           char  *soapaction, 
+                           char  *location,
+                           char  *soapaction,
                            int    soap_version,
-                           char **buffer, 
+                           char **buffer,
                            int   *buffer_len TSRMLS_DC)
 {
        char *request;
@@ -286,7 +287,7 @@
                phpurl = php_url_parse(location);
        }
 
-try_again:     
+try_again:
        if (phpurl == NULL || phpurl->host == NULL) {
          if (phpurl != NULL) {php_url_free(phpurl);}
                if (request != buf) {efree(request);}
@@ -427,23 +428,164 @@
                smart_str_append_const(&soap_headers, "\r\n");
 
                /* HTTP Authentication */
-               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", 
sizeof("_login"), (void **)&login) == SUCCESS) {
-                       char* buf;
-                       int len;
-
-                       smart_str auth = {0};
-                       smart_str_appendl(&auth, Z_STRVAL_PP(login), 
Z_STRLEN_PP(login));
-                       smart_str_appendc(&auth, ':');
-                       if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", 
sizeof("_password"), (void **)&password) == SUCCESS) {
-                               smart_str_appendl(&auth, Z_STRVAL_PP(password), 
Z_STRLEN_PP(password));
-                       }
-                       smart_str_0(&auth);
-                       buf = php_base64_encode(auth.c, auth.len, &len);
-                       smart_str_append_const(&soap_headers, "Authorization: 
Basic ");
-                       smart_str_appendl(&soap_headers, buf, len);
-                       smart_str_append_const(&soap_headers, "\r\n");
-                       efree(buf);
-                       smart_str_free(&auth);
+               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", 
sizeof("_login"), (void **)&login) == SUCCESS &&
+                   Z_TYPE_PP(login) == IS_STRING) {
+                       zval **digest;
+
+                       if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_digest", 
sizeof("_digest"), (void **)&digest) == SUCCESS) {
+                               if (Z_TYPE_PP(digest) == IS_ARRAY) {
+                                       char          HA1[33], HA2[33], 
response[33], cnonce[33], nc[9];
+                                       PHP_MD5_CTX   md5ctx;
+                                       unsigned char hash[16];
+
+                                       PHP_MD5Init(&md5ctx);
+                                       sprintf(cnonce, "%d", rand());
+                                       PHP_MD5Update(&md5ctx, cnonce, 
strlen(cnonce));
+                                       PHP_MD5Final(hash, &md5ctx);
+                                       make_digest(cnonce, hash);
+
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"nc", sizeof("nc"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_LONG) {
+                                               Z_LVAL_PP(tmp)++;
+                                               sprintf(nc, "%08ld", 
Z_LVAL_PP(tmp));
+                                       } else {
+                                               add_assoc_long(*digest, "nc", 
1);
+                                               strcpy(nc, "00000001");
+                                       }
+
+                                       PHP_MD5Init(&md5ctx);
+                                       PHP_MD5Update(&md5ctx, 
Z_STRVAL_PP(login), Z_STRLEN_PP(login));
+                                       PHP_MD5Update(&md5ctx, ":", 1);
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"realm", sizeof("realm"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING) {
+                                               PHP_MD5Update(&md5ctx, 
Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+                                       }
+                                       PHP_MD5Update(&md5ctx, ":", 1);
+                                       if 
(zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void 
**)&password) == SUCCESS &&
+                                           Z_TYPE_PP(password) == IS_STRING) {
+                                               PHP_MD5Update(&md5ctx, 
Z_STRVAL_PP(password), Z_STRLEN_PP(password));
+                                       }
+                                       PHP_MD5Final(hash, &md5ctx);
+                                       make_digest(HA1, hash);
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"algorithm", sizeof("algorithm"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING &&
+                                           Z_STRLEN_PP(tmp) == 
sizeof("md5-sess")-1 &&
+                                           stricmp(Z_STRVAL_PP(tmp), 
"md5-sess") == 0) {
+                                               PHP_MD5Init(&md5ctx);
+                                               PHP_MD5Update(&md5ctx, HA1, 32);
+                                               PHP_MD5Update(&md5ctx, ":", 1);
+                                               if 
(zend_hash_find(Z_ARRVAL_PP(digest), "nonce", sizeof("nonce"), (void **)&tmp) 
== SUCCESS &&
+                                                   Z_TYPE_PP(tmp) == 
IS_STRING) {
+                                                       PHP_MD5Update(&md5ctx, 
Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+                                               }
+                                               PHP_MD5Update(&md5ctx, ":", 1);
+                                               PHP_MD5Update(&md5ctx, cnonce, 
8);
+                                               PHP_MD5Final(hash, &md5ctx);
+                                               make_digest(HA1, hash);
+                                       }
+
+                                       PHP_MD5Init(&md5ctx);
+                                       PHP_MD5Update(&md5ctx, "POST:", 
sizeof("POST:")-1);
+                                       if (phpurl->path) {
+                                               PHP_MD5Update(&md5ctx, 
phpurl->path, strlen(phpurl->path));
+                                       }
+                                       if (phpurl->query) {
+                                               PHP_MD5Update(&md5ctx, "?", 1);
+                                               PHP_MD5Update(&md5ctx, 
phpurl->query, strlen(phpurl->query));
+                                       }
+
+                                       /* TODO: Support for qop="auth-int" */
+/*
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING &&
+                                           Z_STRLEN_PP(tmp) == 
sizeof("auth-int")-1 &&
+                                           stricmp(Z_STRVAL_PP(tmp), 
"auth-int") == 0) {
+                                               PHP_MD5Update(&md5ctx, ":", 1);
+                                               PHP_MD5Update(&md5ctx, HEntity, 
HASHHEXLEN);
+                                       }
+*/
+                                       PHP_MD5Final(hash, &md5ctx);
+                                       make_digest(HA2, hash);
+
+                                       PHP_MD5Init(&md5ctx);
+                                       PHP_MD5Update(&md5ctx, HA1, 32);
+                                       PHP_MD5Update(&md5ctx, ":", 1);
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING) {
+                                               PHP_MD5Update(&md5ctx, 
Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+                                       }
+                                       PHP_MD5Update(&md5ctx, ":", 1);
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING) {
+                                               PHP_MD5Update(&md5ctx, nc, 8);
+                                               PHP_MD5Update(&md5ctx, ":", 1);
+                                               PHP_MD5Update(&md5ctx, cnonce, 
8);
+                                               PHP_MD5Update(&md5ctx, ":", 1);
+                                               /* TODO: Support for 
qop="auth-int" */
+                                               PHP_MD5Update(&md5ctx, "auth", 
sizeof("auth")-1);
+                                               PHP_MD5Update(&md5ctx, ":", 1);
+                                       }
+                                       PHP_MD5Update(&md5ctx, HA2, 32);
+                                       PHP_MD5Final(hash, &md5ctx);
+                                       make_digest(response, hash);
+       
+                                       smart_str_append_const(&soap_headers, 
"Authorization: Digest username=\"");
+                                       smart_str_appendl(&soap_headers, 
Z_STRVAL_PP(login), Z_STRLEN_PP(login));
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"realm", sizeof("realm"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING) {
+                                               
smart_str_append_const(&soap_headers, "\", realm=\"");
+                                               
smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+                                       }
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING) {
+                                               
smart_str_append_const(&soap_headers, "\", nonce=\"");
+                                               
smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+                                       }
+                                       smart_str_append_const(&soap_headers, 
"\", uri=\"");
+                                       if (phpurl->path) {
+                                               
smart_str_appends(&soap_headers, phpurl->path);
+                                       }
+                                       if (phpurl->query) {
+                                               
smart_str_appendc(&soap_headers, '?');
+                                               
smart_str_appends(&soap_headers, phpurl->query);
+                                       }
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING) {
+                                       /* TODO: Support for qop="auth-int" */
+                                               
smart_str_append_const(&soap_headers, "\", qop=\"auth");
+                                               
smart_str_append_const(&soap_headers, "\", nc=\"");
+                                               
smart_str_appendl(&soap_headers, nc, 8);
+                                               
smart_str_append_const(&soap_headers, "\", cnonce=\"");
+                                               
smart_str_appendl(&soap_headers, cnonce, 8);
+                                       }
+                                       smart_str_append_const(&soap_headers, 
"\", response=\"");
+                                       smart_str_appendl(&soap_headers, 
response, 32);
+                                       if (zend_hash_find(Z_ARRVAL_PP(digest), 
"opaque", sizeof("opaque"), (void **)&tmp) == SUCCESS &&
+                                           Z_TYPE_PP(tmp) == IS_STRING) {
+                                               
smart_str_append_const(&soap_headers, "\", opaque=\"");
+                                               
smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+                                       }
+                                       smart_str_append_const(&soap_headers, 
"\"\r\n");
+                               }
+                       } else {
+                               char* buf;
+                               int len;
+
+                               smart_str auth = {0};
+                               smart_str_appendl(&auth, Z_STRVAL_PP(login), 
Z_STRLEN_PP(login));
+                               smart_str_appendc(&auth, ':');
+                               if (zend_hash_find(Z_OBJPROP_P(this_ptr), 
"_password", sizeof("_password"), (void **)&password) == SUCCESS &&
+                                   Z_TYPE_PP(password) == IS_STRING) {
+                                       smart_str_appendl(&auth, 
Z_STRVAL_PP(password), Z_STRLEN_PP(password));
+                               }
+                               smart_str_0(&auth);
+                               buf = php_base64_encode(auth.c, auth.len, &len);
+                               smart_str_append_const(&soap_headers, 
"Authorization: Basic ");
+                               smart_str_appendl(&soap_headers, buf, len);
+                               smart_str_append_const(&soap_headers, "\r\n");
+                               efree(buf);
+                               smart_str_free(&auth);
+                       }
                }
 
                /* Proxy HTTP Authentication */
@@ -544,48 +686,6 @@
                }
                efree(http_version);
 
-               /* Process HTTP status codes */
-               if (http_status >= 200 && http_status < 300) {
-               } else if (http_status >= 300 && http_status < 400) {
-                       char *loc;
-
-                       if ((loc = 
get_http_header_value(http_headers,"Location: ")) != NULL) {
-                         php_url *new_url  = php_url_parse(loc);
-                         char *body;
-                         int body_size;
-
-                               if (new_url != NULL) {
-                                       if (get_http_body(stream, !http_1_1, 
http_headers, &body, &body_size TSRMLS_CC)) {
-                                               efree(body);
-                                       } else {
-                                               php_stream_close(stream);
-                                               
zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
-                                               stream = NULL;
-                                       }
-                                       efree(http_headers);
-                                       efree(loc);
-                                       if (new_url->scheme == NULL && 
new_url->path != NULL) {                                         
-                                         new_url->scheme = 
estrdup(phpurl->scheme);
-                                         new_url->host = estrdup(phpurl->host);
-                                         new_url->port = phpurl->port;
-                                               if (new_url->path && 
new_url->path[0] != '/') {
-                                                 char *t = 
phpurl->path?phpurl->path:"/";
-                                                 char *p = strrchr(t, '/');
-                                                 char *s = emalloc((p - t) + 
strlen(new_url->path) + 2);
-
-                                                 strncpy(s, t, (p - t) + 1);
-                                                 s[(p - t) + 1] = 0;
-                                                 strcat(s, new_url->path);
-                                                 efree(new_url->path);
-                                                 new_url->path = s;
-                                               } 
-                                       }
-                                       phpurl = new_url;
-                                       goto try_again;
-                               }
-                       }
-               }
-
                /* Try and get headers again */
                if (http_status == 100) {
                        efree(http_headers);
@@ -725,6 +825,127 @@
                zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", 
sizeof("_use_proxy"));
        }
 
+       /* Process HTTP status codes */
+       if (http_status >= 300 && http_status < 400) {
+               char *loc;
+
+               if ((loc = get_http_header_value(http_headers,"Location: ")) != 
NULL) {
+                       php_url *new_url  = php_url_parse(loc);
+                       char *body;
+                       int body_size;
+
+                       if (new_url != NULL) {
+                               if (get_http_body(stream, !http_1_1, 
http_headers, &body, &body_size TSRMLS_CC)) {
+                                       efree(body);
+                               } else {
+                                       php_stream_close(stream);
+                                       zend_hash_del(Z_OBJPROP_P(this_ptr), 
"httpsocket", sizeof("httpsocket"));
+                                       stream = NULL;
+                               }
+                               efree(http_headers);
+                               efree(http_body);
+                               efree(loc);
+                               if (new_url->scheme == NULL && new_url->path != 
NULL) {
+                                       new_url->scheme = 
estrdup(phpurl->scheme);
+                                       new_url->host = estrdup(phpurl->host);
+                                       new_url->port = phpurl->port;
+                                       if (new_url->path && new_url->path[0] 
!= '/') {
+                                               char *t = 
phpurl->path?phpurl->path:"/";
+                                               char *p = strrchr(t, '/');
+                                               char *s = emalloc((p - t) + 
strlen(new_url->path) + 2);
+
+                                               strncpy(s, t, (p - t) + 1);
+                                               s[(p - t) + 1] = 0;
+                                               strcat(s, new_url->path);
+                                               efree(new_url->path);
+                                               new_url->path = s;
+                                       }
+                               }
+                               phpurl = new_url;
+
+                               goto try_again;
+                       }
+               }
+       } else if (http_status == 401) {
+               /* Digest authentication */
+               zval **digest, **login, **password;
+               char *auth = get_http_header_value(http_headers, 
"WWW-Authenticate: ");
+
+               if (auth &&
+                               strstr(auth, "Digest") == auth &&
+                   (zend_hash_find(Z_OBJPROP_P(this_ptr), "_digest", 
sizeof("_digest"), (void **)&digest) == FAILURE ||
+                    Z_TYPE_PP(digest) != IS_ARRAY) &&
+                   zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", 
sizeof("_login"), (void **)&login) == SUCCESS &&
+                   Z_TYPE_PP(login) == IS_STRING &&
+                   zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", 
sizeof("_password"), (void **)&password) == SUCCESS &&
+                   Z_TYPE_PP(password) == IS_STRING) {
+                       char *s;
+                       zval *digest = NULL;
+
+                       s = auth + sizeof("Digest")-1;
+                       while (*s != '\0') {
+                               char *name, *val;
+                               while (*s == ' ') ++s;
+                               name = s;
+                               while (*s != '\0' && *s != '=') ++s;
+                               if (*s == '=') {
+                                       *s = '\0';
+                                       ++s;
+                                       if (*s == '"') {
+                                               ++s;
+                                               val = s;
+                                               while (*s != '\0' && *s != '"') 
++s;
+                                       } else {
+                                               val = s;
+                                               while (*s != '\0' && *s != ' ' 
&& *s != ',') ++s;
+                                       }
+                                       if (*s != '\0') {
+                                               if (*s != ',') {
+                                                       *s = '\0';
+                                                       ++s;
+                                                       while (*s != '\0' && *s 
!= ',') ++s;
+                                                       if (*s != '\0') ++s;
+                                               } else {
+                                                       *s = '\0';
+                                                       ++s;
+                                               }
+                                       }
+                                       if (digest == NULL) {
+                                               ALLOC_INIT_ZVAL(digest);
+                                               array_init(digest);
+                                       }
+                                       add_assoc_string(digest, name, val ,1);
+                               }
+                       }
+
+                       if (digest != NULL) {
+                               php_url *new_url  = emalloc(sizeof(php_url));
+
+#ifdef ZEND_ENGINE_2
+                               digest->refcount--;
+#endif
+                               add_property_zval_ex(this_ptr, "_digest", 
sizeof("_digest"), digest TSRMLS_CC);
+
+                               *new_url = *phpurl;
+                               if (phpurl->scheme) phpurl->scheme = 
estrdup(phpurl->scheme);
+                               if (phpurl->user) phpurl->user = 
estrdup(phpurl->user);
+                               if (phpurl->pass) phpurl->pass = 
estrdup(phpurl->pass);
+                               if (phpurl->host) phpurl->host = 
estrdup(phpurl->host);
+                               if (phpurl->path) phpurl->path = 
estrdup(phpurl->path);
+                               if (phpurl->query) phpurl->query = 
estrdup(phpurl->query);
+                               if (phpurl->fragment) phpurl->fragment = 
estrdup(phpurl->fragment);
+                               phpurl = new_url;
+
+                               efree(auth);
+                               efree(http_headers);
+                               efree(http_body);
+
+                               goto try_again;
+                       }
+               }
+               if (auth) efree(auth);
+       }
+
        /* Check and see if the server even sent a xml document */
        content_type = get_http_header_value(http_headers,"Content-Type: ");
        if (content_type) {

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to