summaryrefslogtreecommitdiff
path: root/ext/openssl
diff options
context:
space:
mode:
Diffstat (limited to 'ext/openssl')
-rw-r--r--ext/openssl/config.w323
-rw-r--r--ext/openssl/config0.m44
-rw-r--r--ext/openssl/openssl.c358
-rw-r--r--ext/openssl/php_openssl.h9
-rw-r--r--ext/openssl/tests/005.phpt34
-rw-r--r--ext/openssl/tests/005_crt.txt22
-rw-r--r--ext/openssl/tests/bug38261.phpt4
-rw-r--r--ext/openssl/xp_ssl.c42
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;