diff options
Diffstat (limited to 'ext/openssl')
| -rw-r--r-- | ext/openssl/config.w32 | 3 | ||||
| -rw-r--r-- | ext/openssl/config0.m4 | 4 | ||||
| -rw-r--r-- | ext/openssl/openssl.c | 358 | ||||
| -rw-r--r-- | ext/openssl/php_openssl.h | 9 | ||||
| -rw-r--r-- | ext/openssl/tests/005.phpt | 34 | ||||
| -rw-r--r-- | ext/openssl/tests/005_crt.txt | 22 | ||||
| -rw-r--r-- | ext/openssl/tests/bug38261.phpt | 4 | ||||
| -rw-r--r-- | ext/openssl/xp_ssl.c | 42 |
8 files changed, 456 insertions, 20 deletions
diff --git a/ext/openssl/config.w32 b/ext/openssl/config.w32 index 2f111b81f..08b8a0c6b 100644 --- a/ext/openssl/config.w32 +++ b/ext/openssl/config.w32 @@ -1,4 +1,4 @@ -// $Id: config.w32,v 1.1 2003/12/05 23:13:27 wez Exp $ +// $Id: config.w32,v 1.1.6.1 2007/01/07 18:38:22 iliaa Exp $ // vim:ft=javascript ARG_WITH("openssl", "OpenSSL support", "no"); @@ -11,6 +11,7 @@ if (PHP_OPENSSL != "no") { AC_DEFINE("HAVE_OPENSSL_EXT", PHP_OPENSSL_SHARED ? 0 : 1, "Have openssl"); AC_DEFINE("HAVE_OPENSSL", 1); + AC_DEFINE("HAVE_DSA_DEFAULT_METHOD", 1); } } diff --git a/ext/openssl/config0.m4 b/ext/openssl/config0.m4 index a805527a3..91efd6629 100644 --- a/ext/openssl/config0.m4 +++ b/ext/openssl/config0.m4 @@ -1,5 +1,5 @@ dnl -dnl $Id: config0.m4,v 1.4 2005/01/01 14:32:58 wez Exp $ +dnl $Id: config0.m4,v 1.4.4.1 2007/01/07 18:38:22 iliaa Exp $ dnl PHP_ARG_WITH(openssl, for OpenSSL support, @@ -16,6 +16,8 @@ if test "$PHP_OPENSSL" != "no"; then PHP_SETUP_KERBEROS(OPENSSL_SHARED_LIBADD) fi + AC_CHECK_LIB(ssl, DSA_get_default_method, AC_DEFINE(HAVE_DSA_DEFAULT_METHOD, 1, [OpenSSL 0.9.7 or later])) + PHP_SETUP_OPENSSL(OPENSSL_SHARED_LIBADD, [ AC_DEFINE(HAVE_OPENSSL_EXT,1,[ ]) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 115a286f0..3163d1748 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | + | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -15,10 +15,12 @@ | Authors: Stig Venaas <venaas@php.net> | | Wez Furlong <wez@thebrainroom.com> | | Sascha Kettler <kettler@gmx.net> | + | Pierre-Alain Joye <pierre@php.net> | + | Marc Delling <delling@silpion.de> (PKCS12 functions) | +----------------------------------------------------------------------+ */ -/* $Id: openssl.c,v 1.98.2.5.2.23 2006/10/15 21:09:24 tony2001 Exp $ */ +/* $Id: openssl.c,v 1.98.2.5.2.32 2007/04/05 18:08:42 rrichards Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -42,6 +44,7 @@ #include <openssl/conf.h> #include <openssl/rand.h> #include <openssl/ssl.h> +#include <openssl/pkcs12.h> #define DEFAULT_KEY_LENGTH 512 #define MIN_KEY_LENGTH 384 @@ -110,6 +113,11 @@ zend_function_entry openssl_functions[] = { PHP_FE(openssl_x509_export, second_arg_force_ref) PHP_FE(openssl_x509_export_to_file, NULL) +/* PKCS12 funcs */ + PHP_FE(openssl_pkcs12_export, second_arg_force_ref) + PHP_FE(openssl_pkcs12_export_to_file, NULL) + PHP_FE(openssl_pkcs12_read, second_arg_force_ref) + /* CSR funcs */ PHP_FE(openssl_csr_new, second_arg_force_ref) PHP_FE(openssl_csr_export, second_arg_force_ref) @@ -260,6 +268,10 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s } for (i = 0; i < X509_NAME_entry_count(name); i++) { + unsigned char *to_add; + int to_add_len; + + ne = X509_NAME_get_entry(name, i); obj = X509_NAME_ENTRY_get_object(ne); nid = OBJ_obj2nid(obj); @@ -283,7 +295,14 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s obj_cnt++; ne = X509_NAME_get_entry(name, j); str = X509_NAME_ENTRY_get_data(ne); - add_next_index_stringl(subentries, (char *)str->data, str->length, 1); + if (ASN1_STRING_type(str) != V_ASN1_UTF8STRING) { + to_add_len = ASN1_STRING_to_UTF8(&to_add, str); + add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1); + } else { + to_add = ASN1_STRING_data(str); + to_add_len = ASN1_STRING_length(str); + add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1); + } } last = j; } @@ -295,7 +314,7 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s zval_dtor(subentries); FREE_ZVAL(subentries); if (obj_cnt && str) { - add_assoc_stringl(subitem, sname, (char *)str->data, str->length, 1); + add_assoc_stringl(subitem, sname, (char *)to_add, to_add_len, 1); } } } @@ -316,7 +335,7 @@ static time_t asn1_time_to_time_t(ASN1_UTCTIME * timestr TSRMLS_DC) /* {{{ */ /* This is how the time string is formatted: - sprintf(p,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100, + snprintf(p, sizeof(p), "%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100, ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec); */ @@ -1003,7 +1022,8 @@ PHP_FUNCTION(openssl_x509_parse) add_assoc_name_entry(return_value, "issuer", X509_get_issuer_name(cert), useshortnames TSRMLS_CC); add_assoc_long(return_value, "version", X509_get_version(cert)); - add_assoc_long(return_value, "serialNumber", ASN1_INTEGER_get(X509_get_serialNumber(cert))); + + add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1); add_assoc_asn1_string(return_value, "validFrom", X509_get_notBefore(cert)); add_assoc_asn1_string(return_value, "validTo", X509_get_notAfter(cert)); @@ -1301,6 +1321,324 @@ PHP_FUNCTION(openssl_x509_free) /* }}} */ + +/* Pop all X509 from Stack and free them, free the stack afterwards */ +static void php_sk_X509_free(STACK_OF(X509) * sk) +{ + for (;;) { + X509* x = sk_X509_pop(sk); + if (!x) break; + X509_free(x); + } + sk_X509_free(sk); +} + +static STACK_OF(X509) * php_array_to_X509_sk(zval ** zcerts TSRMLS_DC) +{ + HashPosition hpos; + zval ** zcertval; + STACK_OF(X509) * sk = NULL; + X509 * cert; + long certresource; + + sk = sk_X509_new_null(); + + /* get certs */ + if (Z_TYPE_PP(zcerts) == IS_ARRAY) { + zend_hash_internal_pointer_reset_ex(HASH_OF(*zcerts), &hpos); + while(zend_hash_get_current_data_ex(HASH_OF(*zcerts), (void**)&zcertval, &hpos) == SUCCESS) { + + cert = php_openssl_x509_from_zval(zcertval, 0, &certresource TSRMLS_CC); + if (cert == NULL) { + goto clean_exit; + } + + if (certresource != -1) { + cert = X509_dup(cert); + + if (cert == NULL) { + goto clean_exit; + } + + } + sk_X509_push(sk, cert); + + zend_hash_move_forward_ex(HASH_OF(*zcerts), &hpos); + } + } else { + /* a single certificate */ + cert = php_openssl_x509_from_zval(zcerts, 0, &certresource TSRMLS_CC); + + if (cert == NULL) { + goto clean_exit; + } + + if (certresource != -1) { + cert = X509_dup(cert); + if (cert == NULL) { + goto clean_exit; + } + } + sk_X509_push(sk, cert); + } + + clean_exit: + return sk; +} + +/* {{{ proto bool openssl_pkcs12_export_to_file(mixed x509, string filename, mixed priv_key, string pass[, array args]) + Creates and exports a PKCS to file */ +PHP_FUNCTION(openssl_pkcs12_export_to_file) +{ + X509 * cert = NULL; + BIO * bio_out = NULL; + PKCS12 * p12 = NULL; + char * filename; + char * friendly_name = NULL; + int filename_len; + char * pass; + int pass_len; + zval *zcert = NULL, *zpkey = NULL, *args = NULL; + EVP_PKEY *priv_key = NULL; + long certresource, keyresource; + zval ** item; + STACK_OF(X509) *ca = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zszs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE) + return; + + RETVAL_FALSE; + + cert = php_openssl_x509_from_zval(&zcert, 0, &certresource TSRMLS_CC); + if (cert == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1"); + return; + } + priv_key = php_openssl_evp_from_zval(&zpkey, 0, "", 1, &keyresource TSRMLS_CC); + if (priv_key == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get private key from parameter 3"); + goto cleanup; + } + if (cert && !X509_check_private_key(cert, priv_key)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key does not correspond to cert"); + goto cleanup; + } + if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { + goto cleanup; + } + + /* parse extra config from args array, promote this to an extra function */ + if (args && zend_hash_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name"), (void**)&item) == SUCCESS) + friendly_name = Z_STRVAL_PP(item); + /* certpbe (default RC2-40) + keypbe (default 3DES) + friendly_caname + */ + + if (args && zend_hash_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts"), (void**)&item) == SUCCESS) + ca = php_array_to_X509_sk(item TSRMLS_CC); + /* end parse extra config */ + + /*PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, STACK_OF(X509) *ca, + int nid_key, int nid_cert, int iter, int mac_iter, int keytype);*/ + + p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0); + + bio_out = BIO_new_file(filename, "w"); + if (bio_out) { + + i2d_PKCS12_bio(bio_out, p12); + + RETVAL_TRUE; + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "error opening file %s", filename); + } + + BIO_free(bio_out); + PKCS12_free(p12); + php_sk_X509_free(ca); + +cleanup: + + if (keyresource == -1 && priv_key) { + EVP_PKEY_free(priv_key); + } + if (certresource == -1 && cert) { + X509_free(cert); + } +} +/* }}} */ + +/* {{{ proto bool openssl_pkcs12_export(mixed x509, string &out, mixed priv_key, string pass[, array args]) + Creates and exports a PKCS12 to a var */ +PHP_FUNCTION(openssl_pkcs12_export) +{ + X509 * cert = NULL; + BIO * bio_out; + PKCS12 * p12 = NULL; + zval * zcert = NULL, *zout = NULL, *zpkey, *args = NULL; + EVP_PKEY *priv_key = NULL; + long certresource, keyresource; + char * pass; + int pass_len; + char * friendly_name = NULL; + zval ** item; + STACK_OF(X509) *ca = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzzs|a", &zcert, &zout, &zpkey, &pass, &pass_len, &args) == FAILURE) + return; + + RETVAL_FALSE; + + cert = php_openssl_x509_from_zval(&zcert, 0, &certresource TSRMLS_CC); + if (cert == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1"); + return; + } + priv_key = php_openssl_evp_from_zval(&zpkey, 0, "", 1, &keyresource TSRMLS_CC); + if (priv_key == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get private key from parameter 3"); + goto cleanup; + } + if (cert && !X509_check_private_key(cert, priv_key)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key does not correspond to cert"); + goto cleanup; + } + + /* parse extra config from args array, promote this to an extra function */ + if (args && zend_hash_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name"), (void**)&item) == SUCCESS) + friendly_name = Z_STRVAL_PP(item); + + if (args && zend_hash_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts"), (void**)&item) == SUCCESS) + ca = php_array_to_X509_sk(item TSRMLS_CC); + /* end parse extra config */ + + p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0); + + bio_out = BIO_new(BIO_s_mem()); + if (i2d_PKCS12_bio(bio_out, p12)) { + BUF_MEM *bio_buf; + + zval_dtor(zout); + BIO_get_mem_ptr(bio_out, &bio_buf); + ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length, 1); + + RETVAL_TRUE; + } + + BIO_free(bio_out); + PKCS12_free(p12); + php_sk_X509_free(ca); + +cleanup: + + if (keyresource == -1 && priv_key) { + EVP_PKEY_free(priv_key); + } + if (certresource == -1 && cert) { + X509_free(cert); + } +} +/* }}} */ + +/* {{{ proto bool openssl_pkcs12_read(mixed PKCS12, array &certs, string pass) + Parses a PKCS12 to an array */ +PHP_FUNCTION(openssl_pkcs12_read) +{ + zval *zp12 = NULL, *zout = NULL, *zextracerts, *zcert, *zpkey; + char * pass; + int pass_len; + PKCS12 * p12 = NULL; + EVP_PKEY * pkey = NULL; + X509 * cert = NULL; + STACK_OF(X509) * ca = NULL; + BIO * bio_in = NULL; + int i; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzs", &zp12, &zout, &pass, &pass_len) == FAILURE) + return; + + RETVAL_FALSE; + + bio_in = BIO_new(BIO_s_mem()); + + if(!BIO_write(bio_in, Z_STRVAL_P(zp12), Z_STRLEN_P(zp12))) + goto cleanup; + + if(d2i_PKCS12_bio(bio_in, &p12)) { + if(PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { + BIO * bio_out; + + zval_dtor(zout); + array_init(zout); + + bio_out = BIO_new(BIO_s_mem()); + if (PEM_write_bio_X509(bio_out, cert)) { + BUF_MEM *bio_buf; + BIO_get_mem_ptr(bio_out, &bio_buf); + MAKE_STD_ZVAL(zcert); + ZVAL_STRINGL(zcert, bio_buf->data, bio_buf->length, 1); + add_assoc_zval(zout, "cert", zcert); + } + BIO_free(bio_out); + + bio_out = BIO_new(BIO_s_mem()); + if (PEM_write_bio_PrivateKey(bio_out, pkey, NULL, NULL, 0, 0, NULL)) { + BUF_MEM *bio_buf; + BIO_get_mem_ptr(bio_out, &bio_buf); + MAKE_STD_ZVAL(zpkey); + ZVAL_STRINGL(zpkey, bio_buf->data, bio_buf->length, 1); + add_assoc_zval(zout, "pkey", zpkey); + } + BIO_free(bio_out); + + MAKE_STD_ZVAL(zextracerts); + array_init(zextracerts); + + for (i=0;;i++) { + zval * zextracert; + X509* aCA = sk_X509_pop(ca); + if (!aCA) break; + + bio_out = BIO_new(BIO_s_mem()); + if (PEM_write_bio_X509(bio_out, aCA)) { + BUF_MEM *bio_buf; + BIO_get_mem_ptr(bio_out, &bio_buf); + MAKE_STD_ZVAL(zextracert); + ZVAL_STRINGL(zextracert, bio_buf->data, bio_buf->length, 1); + add_index_zval(zextracerts, i, zextracert); + + } + BIO_free(bio_out); + + X509_free(aCA); + } + if(ca) { + sk_X509_free(ca); + add_assoc_zval(zout, "extracerts", zextracerts); + } else { + zval_dtor(zextracerts); + } + + RETVAL_TRUE; + + PKCS12_free(p12); + } + } + + cleanup: + if (bio_in) { + BIO_free(bio_in); + } + if (pkey) { + EVP_PKEY_free(pkey); + } + if (cert) { + X509_free(cert); + } +} +/* }}} */ + /* {{{ x509 CSR functions */ /* {{{ php_openssl_make_REQ */ @@ -1957,10 +2295,10 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * /* got the key - return it */ return (EVP_PKEY*)what; } + } else { + /* other types could be used here - eg: file pointers and read in the data from them */ + TMP_CLEAN; } - - /* other types could be used here - eg: file pointers and read in the data from them */ - TMP_CLEAN; } else { /* force it to be a string and check if it refers to a file */ /* passing non string values leaks, object uses toString, it returns NULL @@ -2055,7 +2393,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req return_val = req->priv_key; } break; -#ifndef NO_DSA +#if !defined(NO_DSA) && defined(HAVE_DSA_DEFAULT_METHOD) case OPENSSL_KEYTYPE_DSA: { DSA *dsapar = DSA_generate_parameters(req->priv_key_bits, NULL, 0, NULL, NULL, NULL, NULL); diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index a56ef8a1a..15023b233 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | + | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_openssl.h,v 1.16.2.1.2.2 2006/08/15 20:27:20 pajoye Exp $ */ +/* $Id: php_openssl.h,v 1.16.2.1.2.4 2007/04/04 21:24:01 pajoye Exp $ */ #ifndef PHP_OPENSSL_H #define PHP_OPENSSL_H @@ -63,6 +63,11 @@ PHP_FUNCTION(openssl_x509_checkpurpose); PHP_FUNCTION(openssl_x509_export); PHP_FUNCTION(openssl_x509_export_to_file); PHP_FUNCTION(openssl_x509_check_private_key); + +PHP_FUNCTION(openssl_pkcs12_export); +PHP_FUNCTION(openssl_pkcs12_export_to_file); +PHP_FUNCTION(openssl_pkcs12_read); + PHP_FUNCTION(openssl_csr_new); PHP_FUNCTION(openssl_csr_export); PHP_FUNCTION(openssl_csr_export_to_file); diff --git a/ext/openssl/tests/005.phpt b/ext/openssl/tests/005.phpt new file mode 100644 index 000000000..f7fa20156 --- /dev/null +++ b/ext/openssl/tests/005.phpt @@ -0,0 +1,34 @@ +--TEST-- +openssl_csr_get_subject() tests +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!function_exists("utf8_decode")) die("skip"); +?> +--FILE-- +<?php + +$csr = file_get_contents(dirname(__FILE__) . '/005_crt.txt'); +if ($out = openssl_csr_get_subject($csr, 1)) { + var_dump($out); +} +echo "\n"; +$cn = utf8_decode($out['CN']); +var_dump($cn); +--EXPECTF-- +array(6) { + ["C"]=> + string(2) "NL" + ["ST"]=> + string(13) "Noord Brabant" + ["L"]=> + string(4) "Uden" + ["O"]=> + string(10) "Triconnect" + ["OU"]=> + string(10) "Triconnect" + ["CN"]=> + string(15) "*.triconnect.nl" +} + +string(15) "*.triconnect.nl" diff --git a/ext/openssl/tests/005_crt.txt b/ext/openssl/tests/005_crt.txt new file mode 100644 index 000000000..39084bce0 --- /dev/null +++ b/ext/openssl/tests/005_crt.txt @@ -0,0 +1,22 @@ +-----BEGIN NEW CERTIFICATE REQUEST----- +MIIDYzCCAswCAQAwgYcxCzAJBgNVBAYTAk5MMRYwFAYDVQQIEw1Ob29yZCBCcmFi +YW50MQ0wCwYDVQQHEwRVZGVuMRMwEQYDVQQKEwpUcmljb25uZWN0MRMwEQYDVQQL +EwpUcmljb25uZWN0MScwJQYDVQQDHh4AKgAuAHQAcgBpAGMAbwBuAG4AZQBjAHQA +LgBuAGwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANjE/qKAKgo93162HhtX +OZdvunF5eG/PFK2yn6uAUDWgZciPoKBslgL6a6sK+RdcS7LjWdjWEOOANGzZY1Kk +FelzxrIjIGSGJHC9eubebdu2LWFFM5cEMDiH0QSD9Rdiy7svSLWvngUDYj0wwd+m +iV2duzUFHnusj9iVPpD9s47RAgMBAAGgggGZMBoGCisGAQQBgjcNAgMxDBYKNS4y +LjM3OTAuMjB7BgorBgEEAYI3AgEOMW0wazAOBgNVHQ8BAf8EBAMCBPAwRAYJKoZI +hvcNAQkPBDcwNTAOBggqhkiG9w0DAgICAIAwDgYIKoZIhvcNAwQCAgCAMAcGBSsO +AwIHMAoGCCqGSIb3DQMHMBMGA1UdJQQMMAoGCCsGAQUFBwMBMIH9BgorBgEEAYI3 +DQICMYHuMIHrAgEBHloATQBpAGMAcgBvAHMAbwBmAHQAIABSAFMAQQAgAFMAQwBo +AGEAbgBuAGUAbAAgAEMAcgB5AHAAdABvAGcAcgBhAHAAaABpAGMAIABQAHIAbwB2 +AGkAZABlAHIDgYkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAADANBgkqhkiG9w0BAQUFAAOBgQA4agiUkIblhF+n0wth4vQY+PwMadyaBpA4 +epr4TKL0QEkA0bQBbIERw5dDE3WQi6aVFJe6y870QymBwmKIvfBBfOyyA0IlQq/n +uybhzQNQbSMKF1T82hpfh1w2RwVGaGrw7f6qH+CLyP1ydvBPvmD88HwiibNBBB3c +R23mEEGYUQ== +-----END NEW CERTIFICATE REQUEST----- + diff --git a/ext/openssl/tests/bug38261.phpt b/ext/openssl/tests/bug38261.phpt index e7d806083..b06fa4f8f 100644 --- a/ext/openssl/tests/bug38261.phpt +++ b/ext/openssl/tests/bug38261.phpt @@ -27,8 +27,8 @@ bool(false) bool(false) bool(false) -Warning: openssl_x509_parse() expects at least 1 parameter, 0 given in %s/bug38261.php on line %d +Warning: openssl_x509_parse() expects at least 1 parameter, 0 given in %sbug38261.php on line %d NULL bool(false) -Catchable fatal error: Object of class stdClass could not be converted to string in %s/bug38261.php on line %d +Catchable fatal error: Object of class stdClass could not be converted to string in %sbug38261.php on line %d diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index c6594c64d..c6778e06d 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2006 The PHP Group | + | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: xp_ssl.c,v 1.22.2.3.2.2 2006/10/05 00:38:00 iliaa Exp $ */ +/* $Id: xp_ssl.c,v 1.22.2.3.2.7 2007/04/04 10:44:55 tony2001 Exp $ */ #include "php.h" #include "ext/standard/file.h" @@ -27,6 +27,10 @@ #include <openssl/x509.h> #include <openssl/err.h> +#ifdef PHP_WIN32 +#include "win32/time.h" +#endif + #ifdef NETWARE #include <sys/select.h> #endif @@ -43,6 +47,7 @@ int php_openssl_get_x509_list_id(void); typedef struct _php_openssl_netstream_data_t { php_netstream_data_t s; SSL *ssl_handle; + struct timeval connect_timeout; int enable_on_connect; int is_client; int ssl_active; @@ -99,7 +104,7 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes TSRMLS_DC) /* re-negotiation, or perhaps the SSL layer needs more * packets: retry in next iteration */ errno = EAGAIN; - retry = sslsock->s.is_blocked; + retry = 1; break; case SSL_ERROR_SYSCALL: if (ERR_peek_error() == 0) { @@ -164,6 +169,9 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes TSRMLS_DC) err, ebuf ? "OpenSSL Error messages:\n" : "", ebuf ? ebuf : ""); + if (ebuf) { + efree(ebuf); + } } retry = 0; @@ -386,6 +394,9 @@ static inline int php_openssl_enable_crypto(php_stream *stream, int n, retry = 1; if (cparam->inputs.activate && !sslsock->ssl_active) { + float timeout = sslsock->connect_timeout.tv_sec + sslsock->connect_timeout.tv_usec / 1000000; + int blocked = sslsock->s.is_blocked; + if (!sslsock->state_set) { if (sslsock->is_client) { SSL_set_connect_state(sslsock->ssl_handle); @@ -395,9 +406,23 @@ static inline int php_openssl_enable_crypto(php_stream *stream, sslsock->state_set = 1; } + if (sslsock->is_client && SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) { + sslsock->s.is_blocked = 0; + } do { if (sslsock->is_client) { + struct timeval tvs, tve; + struct timezone tz; + + gettimeofday(&tvs, &tz); n = SSL_connect(sslsock->ssl_handle); + gettimeofday(&tve, &tz); + + timeout -= (tve.tv_sec + tve.tv_usec / 1000000) - (tvs.tv_sec + tvs.tv_usec / 1000000); + if (timeout < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: connection timeout"); + return -1; + } } else { n = SSL_accept(sslsock->ssl_handle); } @@ -409,6 +434,10 @@ static inline int php_openssl_enable_crypto(php_stream *stream, } } while (retry); + if (sslsock->is_client && sslsock->s.is_blocked != blocked && SUCCESS == php_set_sock_blocking(sslsock->s.socket, blocked TSRMLS_CC)) { + sslsock->s.is_blocked = blocked; + } + if (n == 1) { X509 *peer_cert; @@ -583,7 +612,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val tv.tv_sec = FG(default_socket_timeout); tv.tv_usec = 0; } else { - tv = sslsock->s.timeout; + tv = sslsock->connect_timeout; } } else { tv.tv_sec = value; @@ -741,9 +770,14 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, memset(sslsock, 0, sizeof(*sslsock)); sslsock->s.is_blocked = 1; + /* this timeout is used by standard stream funcs, therefor it should use the default value */ sslsock->s.timeout.tv_sec = FG(default_socket_timeout); sslsock->s.timeout.tv_usec = 0; + /* use separate timeout for our private funcs */ + sslsock->connect_timeout.tv_sec = timeout->tv_sec; + sslsock->connect_timeout.tv_usec = timeout->tv_usec; + /* we don't know the socket until we have determined if we are binding or * connecting */ sslsock->s.socket = -1; |
