]> granicus.if.org Git - php/commitdiff
Unicode support
authorDmitry Stogov <dmitry@php.net>
Wed, 11 Jul 2007 12:10:28 +0000 (12:10 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 11 Jul 2007 12:10:28 +0000 (12:10 +0000)
improved openssl_x509_parse() extensions support

ext/openssl/openssl.c
ext/openssl/tests/005.phpt
ext/openssl/tests/bug28382.phpt

index d3aa0977056c032c192cf617985d779364d0be9e..c6eee0183a7a5093f1b0494c9ac4293af911e70b 100644 (file)
@@ -283,11 +283,11 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s
                                str = X509_NAME_ENTRY_get_data(ne);
                                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);
+                                       add_next_index_utf8_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);
+                                       add_next_index_utf8_stringl(subentries, (char *)to_add, to_add_len, 1);
                                }
                        }
                        last = j;
@@ -295,24 +295,36 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s
                i = last;
                
                if (obj_cnt > 1) {
-                       add_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries);
+                       add_ascii_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries);
                } else {
                        zval_dtor(subentries);
                        FREE_ZVAL(subentries);
                        if (obj_cnt && str) {
-                               add_assoc_stringl(subitem, sname, (char *)to_add, to_add_len, 1);
+                               add_ascii_assoc_utf8_stringl(subitem, sname, (char *)to_add, to_add_len, 1);
                        }
                }
        }
        if (key != NULL) {
-               zend_hash_update(HASH_OF(val), key, strlen(key) + 1, (void *)&subitem, sizeof(subitem), NULL);
+               add_ascii_assoc_zval_ex(val, key, strlen(key) + 1, subitem);
        }
 }
 /* }}} */
 
 static void add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str) /* {{{ */
 {
-       add_assoc_stringl(val, key, (char *)str->data, str->length, 1);
+       unsigned char *data;
+       int data_len;
+       TSRMLS_FETCH();
+
+       if (ASN1_STRING_type(str) != V_ASN1_UTF8STRING) {
+               data = ASN1_STRING_data(str);
+               data_len = ASN1_STRING_length(str);
+               add_ascii_assoc_stringl(val, key, (char*)data, data_len, 1);
+       } else {
+               data = ASN1_STRING_data(str);
+               data_len = ASN1_STRING_length(str);
+               add_ascii_assoc_utf8_stringl(val, key, (char*)data, data_len, 1);
+       }
 }
 /* }}} */
 
@@ -443,13 +455,15 @@ static int add_oid_section(struct php_x509_request * req TSRMLS_DC) /* {{{ */
                        req->config_filename, req->var, req->req_config TSRMLS_CC) == FAILURE) return FAILURE
 
 #define SET_OPTIONAL_STRING_ARG(key, varname, defval)  \
-       if (optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), key, sizeof(key), (void**)&item) == SUCCESS) \
+       if (optional_args && zend_ascii_hash_find(Z_ARRVAL_P(optional_args), key, sizeof(key), (void**)&item) == SUCCESS) { \
+               convert_to_string_ex(item); \
                varname = Z_STRVAL_PP(item); \
-       else \
-               varname = defval
+       } else \
+               varname = defval;
+
 
 #define SET_OPTIONAL_LONG_ARG(key, varname, defval)    \
-       if (optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), key, sizeof(key), (void**)&item) == SUCCESS) \
+       if (optional_args && zend_ascii_hash_find(Z_ARRVAL_P(optional_args), key, sizeof(key), (void**)&item) == SUCCESS) \
                varname = Z_LVAL_PP(item); \
        else \
                varname = defval
@@ -985,8 +999,11 @@ PHP_FUNCTION(openssl_x509_parse)
        char * tmpstr;
        zval * subitem;
        X509_EXTENSION *extension;
-       ASN1_OCTET_STRING *extdata;
        char *extname;
+       BIO  *bio_out;
+       BUF_MEM *bio_buf;
+       char buf[256];
+
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|b", &zcert, &useshortnames) == FAILURE) {
                return;
@@ -998,37 +1015,37 @@ PHP_FUNCTION(openssl_x509_parse)
        array_init(return_value);
 
        if (cert->name) {
-               add_assoc_string(return_value, "name", cert->name, 1);
+               add_ascii_assoc_string(return_value, "name", cert->name, 1);
        }
-/*     add_assoc_bool(return_value, "valid", cert->valid); */
+/*     add_ascii_assoc_bool(return_value, "valid", cert->valid); */
 
        add_assoc_name_entry(return_value, "subject",           X509_get_subject_name(cert), useshortnames TSRMLS_CC);
        /* hash as used in CA directories to lookup cert by subject name */
        {
                char buf[32];
                snprintf(buf, sizeof(buf), "%08lx", X509_subject_name_hash(cert));
-               add_assoc_string(return_value, "hash", buf, 1);
+               add_ascii_assoc_string(return_value, "hash", buf, 1);
        }
        
        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_ascii_assoc_long(return_value, "version",                   X509_get_version(cert));
 
-       add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1);
+       add_ascii_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));
 
-       add_assoc_long(return_value, "validFrom_time_t",        asn1_time_to_time_t(X509_get_notBefore(cert) TSRMLS_CC));
-       add_assoc_long(return_value, "validTo_time_t",          asn1_time_to_time_t(X509_get_notAfter(cert) TSRMLS_CC));
+       add_ascii_assoc_long(return_value, "validFrom_time_t",  asn1_time_to_time_t(X509_get_notBefore(cert) TSRMLS_CC));
+       add_ascii_assoc_long(return_value, "validTo_time_t",            asn1_time_to_time_t(X509_get_notAfter(cert) TSRMLS_CC));
 
        tmpstr = (char *)X509_alias_get0(cert, NULL);
        if (tmpstr) {
-               add_assoc_string(return_value, "alias", tmpstr, 1);
+               add_ascii_assoc_string(return_value, "alias", tmpstr, 1);
        }
 /*
-       add_assoc_long(return_value, "signaturetypeLONG", X509_get_signature_type(cert));
-       add_assoc_string(return_value, "signaturetype", OBJ_nid2sn(X509_get_signature_type(cert)), 1);
-       add_assoc_string(return_value, "signaturetypeLN", OBJ_nid2ln(X509_get_signature_type(cert)), 1);
+       add_ascii_assoc_long(return_value, "signaturetypeLONG", X509_get_signature_type(cert));
+       add_ascii_assoc_string(return_value, "signaturetype", OBJ_nid2sn(X509_get_signature_type(cert)), 1);
+       add_ascii_assoc_string(return_value, "signaturetypeLN", OBJ_nid2ln(X509_get_signature_type(cert)), 1);
 */
        MAKE_STD_ZVAL(subitem);
        array_init(subitem);
@@ -1060,19 +1077,29 @@ PHP_FUNCTION(openssl_x509_parse)
 
                add_index_zval(subitem, id, subsub);
        }
-       add_assoc_zval(return_value, "purposes", subitem);
+       add_ascii_assoc_zval(return_value, "purposes", subitem);
 
        MAKE_STD_ZVAL(subitem);
        array_init(subitem);
 
-
        for (i = 0; i < X509_get_ext_count(cert); i++) {
                extension = X509_get_ext(cert, i);
-               extdata = X509_EXTENSION_get_data(extension);
-               extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension)));
-               add_assoc_asn1_string(subitem, extname, extdata);
+               if (OBJ_obj2nid(X509_EXTENSION_get_object(extension)) != NID_undef) {
+                       extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension)));
+               } else {
+                       OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1);
+                       extname = buf;
+               }
+               bio_out = BIO_new(BIO_s_mem());
+               if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
+                       BIO_get_mem_ptr(bio_out, &bio_buf);
+                       add_ascii_assoc_utf8_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1);
+               } else {
+                       add_assoc_asn1_string(subitem, extname, X509_EXTENSION_get_data(extension));
+               }
+               BIO_free(bio_out);
        }
-       add_assoc_zval(return_value, "extensions", subitem);
+       add_ascii_assoc_zval(return_value, "extensions", subitem);
 
        if (certresource == -1 && cert) {
                X509_free(cert);
@@ -1583,7 +1610,7 @@ PHP_FUNCTION(openssl_pkcs12_read)
                                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);
+                               add_ascii_assoc_zval(zout, "cert", zcert);
                        }
                        BIO_free(bio_out);
 
@@ -1593,7 +1620,7 @@ PHP_FUNCTION(openssl_pkcs12_read)
                                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);
+                               add_ascii_assoc_zval(zout, "pkey", zpkey);
                        }
                        BIO_free(bio_out);
 
@@ -1620,7 +1647,7 @@ PHP_FUNCTION(openssl_pkcs12_read)
                        }
                        if(ca) {
                                sk_X509_free(ca);
-                               add_assoc_zval(zout, "extracerts", zextracerts);
+                               add_ascii_assoc_zval(zout, "extracerts", zextracerts);
                        } else {
                                zval_dtor(zextracerts);
                        }
@@ -1687,26 +1714,40 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
                        zstr strindex = NULL_ZSTR;
                        uint strindexlen = 0;
                        ulong intindex;
+                       zend_uchar index_type;
+                       zval index;
                        
-                       zend_hash_get_current_key_ex(HASH_OF(dn), &strindex, &strindexlen, &intindex, 0, &hpos);
+                       index_type = zend_hash_get_current_key_ex(HASH_OF(dn), &strindex, &strindexlen, &intindex, 0, &hpos);
+                       if (index_type == IS_UNICODE) {
+                               ZVAL_UNICODEL(&index, strindex.u, strindexlen-1, 1);
+                               convert_to_string(&index);
+                       } else {
+                               ZVAL_STRINGL(&index, strindex.s, strindexlen-1, 0);
+                       }
 
                        convert_to_string_ex(item);
 
-                       if (strindex.s) {
+                       if (Z_STRVAL(index)) {
                                int nid;
 
-                               nid = OBJ_txt2nid(strindex.s);
+                               nid = OBJ_txt2nid(Z_STRVAL(index));
                                if (nid != NID_undef) {
                                        if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, 
                                                                (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0))
                                        {
                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_PP(item));
+                                               if (index_type == IS_UNICODE) {
+                                                       zval_dtor(&index);
+                                               }
                                                return FAILURE;
                                        }
                                } else {
-                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", strindex.s);
+                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", Z_STRVAL(index));
                                }
                        }
+                       if (index_type == IS_UNICODE) {
+                               zval_dtor(&index);
+                       }
                        zend_hash_move_forward_ex(HASH_OF(dn), &hpos);
                }
 
@@ -1762,23 +1803,38 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
                                zstr strindex;
                                uint strindexlen;
                                ulong intindex;
+                               zend_uchar index_type;
+                               zval index;
+
+                               index_type = zend_hash_get_current_key_ex(HASH_OF(attribs), &strindex, &strindexlen, &intindex, 0, &hpos);
+                               if (index_type == IS_UNICODE) {
+                                       ZVAL_UNICODEL(&index, strindex.u, strindexlen-1, 1);
+                                       convert_to_string(&index);
+                               } else {
+                                       ZVAL_STRINGL(&index, strindex.s, strindexlen-1, 0);
+                               }
 
-                               zend_hash_get_current_key_ex(HASH_OF(attribs), &strindex, &strindexlen, &intindex, 0, &hpos);
                                convert_to_string_ex(item);
 
-                               if (strindex.s) {
+                               if (Z_STRVAL(index)) {
                                        int nid;
 
-                                       nid = OBJ_txt2nid(strindex.s);
+                                       nid = OBJ_txt2nid(Z_STRVAL(index));
                                        if (nid != NID_undef) {
                                                if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0)) {
                                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribs: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_PP(item));
+                                                       if (index_type == IS_UNICODE) {
+                                                               zval_dtor(&index);
+                                                       }
                                                        return FAILURE;
                                                }
                                        } else {
-                                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", strindex.s);
+                                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", Z_STRVAL(index));
                                        }
                                }
+                               if (index_type == IS_UNICODE) {
+                                       zval_dtor(&index);
+                               }
                                zend_hash_move_forward_ex(HASH_OF(attribs), &hpos);
                        }
                        for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
@@ -2704,8 +2760,8 @@ PHP_FUNCTION(openssl_pkey_get_details)
        pbio_len = BIO_get_mem_data(out, &pbio);
 
        array_init(return_value);
-       add_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey));
-       add_assoc_stringl(return_value, "key", pbio, pbio_len, 1);
+       add_ascii_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey));
+       add_ascii_assoc_stringl(return_value, "key", pbio, pbio_len, 1);
        /*TODO: Use the real values once the openssl constants are used 
         * See the enum at the top of this file
         */
@@ -2732,7 +2788,7 @@ PHP_FUNCTION(openssl_pkey_get_details)
                        ktype = -1;
                        break;
        }
-       add_assoc_long(return_value, "type", ktype);
+       add_ascii_assoc_long(return_value, "type", ktype);
 
        BIO_free(out);
 }
index f7fa2015610b301979efebc99af805b87d5e783a..e4431fb972d34dae98d15426535780e2fa607fd2 100644 (file)
@@ -32,3 +32,20 @@ array(6) {
 }
 
 string(15) "*.triconnect.nl"
+--UEXPECTF--   
+array(6) {
+  [u"C"]=>
+  unicode(2) "NL"
+  [u"ST"]=>
+  unicode(13) "Noord Brabant"
+  [u"L"]=>
+  unicode(4) "Uden"
+  [u"O"]=>
+  unicode(10) "Triconnect"
+  [u"OU"]=>
+  unicode(10) "Triconnect"
+  [u"CN"]=>
+  unicode(15) "*.triconnect.nl"
+}
+
+unicode(15) "*.triconnect.nl"
index 255f0304125f8dc60ef8e7c419dd75b83f378436..a26cf3409d8572aa22bcd9b847f7744c62a2e131 100644 (file)
@@ -14,25 +14,56 @@ var_dump($ext['extensions']);
 --EXPECTF--
 array(11) {
   ["basicConstraints"]=>
-  string(2) "%s"
+  string(8) "CA:FALSE"
   ["nsComment"]=>
-  string(40) "%s"
+  string(38) "For Grid use only; request tag userTag"
   ["nsCertType"]=>
-  string(4) "%s"
+  string(30) "SSL Client, SSL Server, S/MIME"
   ["crlDistributionPoints"]=>
-  string(56) "%s"
+  string(51) "URI:http://mobile.blue-software.ro:90/ca/crl.shtml
+"
   ["nsCaPolicyUrl"]=>
-  string(40) "%s"
+  string(38) "http://mobile.blue-software.ro:90/pub/"
   ["subjectAltName"]=>
-  string(26) "%s"
+  string(28) "email:sergiu@bluesoftware.ro"
   ["subjectKeyIdentifier"]=>
-  string(22) "%s"
+  string(59) "B0:A7:FF:F9:41:15:DE:23:39:BD:DD:31:0F:97:A0:B2:A2:74:E0:FC"
   ["authorityKeyIdentifier"]=>
-  string(159) "%s"
+  string(115) "DirName:/C=RO/ST=Romania/L=Craiova/O=Sergiu/OU=Sergiu SRL/CN=Sergiu CA/emailAddress=n_sergiu@hotmail.com
+serial:00
+"
   ["keyUsage"]=>
-  string(4) "%s"
+  string(71) "Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment"
   ["nsBaseUrl"]=>
-  string(22) "%s"
-  ["UNDEF"]=>
+  string(20) "http://62.231.98.52/"
+  ["1.2.3.4"]=>
   string(4) "%s"
 }
+--UEXPECTF--
+array(11) {
+  [u"basicConstraints"]=>
+  unicode(8) "CA:FALSE"
+  [u"nsComment"]=>
+  unicode(38) "For Grid use only; request tag userTag"
+  [u"nsCertType"]=>
+  unicode(30) "SSL Client, SSL Server, S/MIME"
+  [u"crlDistributionPoints"]=>
+  unicode(51) "URI:http://mobile.blue-software.ro:90/ca/crl.shtml
+"
+  [u"nsCaPolicyUrl"]=>
+  unicode(38) "http://mobile.blue-software.ro:90/pub/"
+  [u"subjectAltName"]=>
+  unicode(28) "email:sergiu@bluesoftware.ro"
+  [u"subjectKeyIdentifier"]=>
+  unicode(59) "B0:A7:FF:F9:41:15:DE:23:39:BD:DD:31:0F:97:A0:B2:A2:74:E0:FC"
+  [u"authorityKeyIdentifier"]=>
+  unicode(115) "DirName:/C=RO/ST=Romania/L=Craiova/O=Sergiu/OU=Sergiu SRL/CN=Sergiu CA/emailAddress=n_sergiu@hotmail.com
+serial:00
+"
+  [u"keyUsage"]=>
+  unicode(71) "Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment"
+  [u"nsBaseUrl"]=>
+  unicode(20) "http://62.231.98.52/"
+  [u"1.2.3.4"]=>
+  string(4) "%s"
+}
\ No newline at end of file