pajoye          Wed Apr  4 21:24:02 2007 UTC

  Modified files:              (Branch: PHP_5_2)
    /php-src/ext/openssl        openssl.c php_openssl.h 
    /php-src/ext/openssl/tests  005.phpt 
  Log:
  - implement #39867, PKCS#12 support
  - Fix possible multibyte issues issue in the add_assoc function
  - add test for openssl_csr_get_subject
  
  
http://cvs.php.net/viewvc.cgi/php-src/ext/openssl/openssl.c?r1=1.98.2.5.2.28&r2=1.98.2.5.2.29&diff_format=u
Index: php-src/ext/openssl/openssl.c
diff -u php-src/ext/openssl/openssl.c:1.98.2.5.2.28 
php-src/ext/openssl/openssl.c:1.98.2.5.2.29
--- php-src/ext/openssl/openssl.c:1.98.2.5.2.28 Sat Feb 24 02:17:25 2007
+++ php-src/ext/openssl/openssl.c       Wed Apr  4 21:24:01 2007
@@ -15,10 +15,12 @@
    | Authors: Stig Venaas <[EMAIL PROTECTED]>                                |
    |          Wez Furlong <[EMAIL PROTECTED]>                          |
    |          Sascha Kettler <[EMAIL PROTECTED]>                            |
+   |          Pierre-Alain Joye <[EMAIL PROTECTED]>                          |
+   |          Marc Delling <[EMAIL PROTECTED]> (PKCS12 functions)        |     
        
    +----------------------------------------------------------------------+
  */
 
-/* $Id: openssl.c,v 1.98.2.5.2.28 2007/02/24 02:17:25 helly Exp $ */
+/* $Id: openssl.c,v 1.98.2.5.2.29 2007/04/04 21:24:01 pajoye 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 @@
        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 @@
        }
        
        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 @@
                                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 @@
                        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);
                        }
                }
        }
@@ -1302,6 +1321,326 @@
 
 /* }}} */
 
+
+/* 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)
+{
+       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);
+       /* end parse extra config */
+
+       p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 
0, 0);
+       //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);
+
+       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);
+       // 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);
+       /* 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)) {
+                       
+                       zval_dtor(zout);
+                       array_init(zout);
+               
+                       BIO * bio_out;
+
+                       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 */
http://cvs.php.net/viewvc.cgi/php-src/ext/openssl/php_openssl.h?r1=1.16.2.1.2.3&r2=1.16.2.1.2.4&diff_format=u
Index: php-src/ext/openssl/php_openssl.h
diff -u php-src/ext/openssl/php_openssl.h:1.16.2.1.2.3 
php-src/ext/openssl/php_openssl.h:1.16.2.1.2.4
--- php-src/ext/openssl/php_openssl.h:1.16.2.1.2.3      Mon Jan  1 09:36:04 2007
+++ php-src/ext/openssl/php_openssl.h   Wed Apr  4 21:24:01 2007
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_openssl.h,v 1.16.2.1.2.3 2007/01/01 09:36:04 sebastian 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_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);
http://cvs.php.net/viewvc.cgi/php-src/ext/openssl/tests/005.phpt?r1=1.1.2.2&r2=1.1.2.3&diff_format=u
Index: php-src/ext/openssl/tests/005.phpt
diff -u php-src/ext/openssl/tests/005.phpt:1.1.2.2 
php-src/ext/openssl/tests/005.phpt:1.1.2.3
--- php-src/ext/openssl/tests/005.phpt:1.1.2.2  Sat Jan 20 22:08:29 2007
+++ php-src/ext/openssl/tests/005.phpt  Wed Apr  4 21:24:01 2007
@@ -1,34 +1,31 @@
 --TEST--
-openSSL: read public key from x.509 resource
+openssl_csr_get_subject() tests
 --SKIPIF--
-<?php 
-if (!extension_loaded("openssl")) die("skip"); 
-?>
+<?php if (!extension_loaded("openssl")) print "skip"; ?>
 --FILE--
-<?php 
-$dir = dirname(__FILE__);
-$file_pub = $dir . '/bug37820cert.pem';
-$file_key = $dir . '/bug37820key.pem';
+<?php
 
-$priv_key = file_get_contents($file_key);
-$priv_key_id = openssl_get_privatekey($priv_key);
-
-$x509 = openssl_x509_read(file_get_contents($file_pub));
-
-$pub_key_id = openssl_get_publickey($x509);
-$data = "some custom data";
-if (!openssl_sign($data, $signature, $priv_key_id, OPENSSL_ALGO_MD5)) {
-       echo "openssl_sign failed.";
+$csr = file_get_contents(dirname(__FILE__) . '/005_crt.txt');
+if ($out = openssl_csr_get_subject($csr, 1)) {
+       var_dump($out);
 }
-
-$ok = openssl_verify($data, $signature, $pub_key_id, OPENSSL_ALGO_MD5);
-if ($ok == 1) {
-   echo "Ok";
-} elseif ($ok == 0) {
-   echo "openssl_verify failed.";
+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"
 }
 
-
-?>
---EXPECTF--
-Ok
+string(15) "*.triconnect.nl"

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

Reply via email to