--- embedaddon/php/ext/openssl/openssl.c 2012/02/21 23:47:59 1.1.1.1 +++ embedaddon/php/ext/openssl/openssl.c 2012/05/29 12:34:36 1.1.1.2 @@ -16,11 +16,11 @@ | Wez Furlong | | Sascha Kettler | | Pierre-Alain Joye | - | Marc Delling (PKCS12 functions) | + | Marc Delling (PKCS12 functions) | +----------------------------------------------------------------------+ */ -/* $Id: openssl.c,v 1.1.1.1 2012/02/21 23:47:59 misho Exp $ */ +/* $Id: openssl.c,v 1.1.1.2 2012/05/29 12:34:36 misho Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -36,6 +36,10 @@ #include "ext/standard/md5.h" #include "ext/standard/base64.h" +#if PHP_WIN32 +# include "win32/winutil.h" +#endif + /* OpenSSL includes */ #include #include @@ -89,6 +93,9 @@ enum php_openssl_cipher_type { PHP_OPENSSL_CIPHER_RC2_64, PHP_OPENSSL_CIPHER_DES, PHP_OPENSSL_CIPHER_3DES, + PHP_OPENSSL_CIPHER_AES_128_CBC, + PHP_OPENSSL_CIPHER_AES_192_CBC, + PHP_OPENSSL_CIPHER_AES_256_CBC, PHP_OPENSSL_CIPHER_DEFAULT = PHP_OPENSSL_CIPHER_RC2_40 }; @@ -347,7 +354,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_encrypt, 0, 0, ZEND_ARG_INFO(0, data) ZEND_ARG_INFO(0, method) ZEND_ARG_INFO(0, password) - ZEND_ARG_INFO(0, raw_output) + ZEND_ARG_INFO(0, options) ZEND_ARG_INFO(0, iv) ZEND_END_ARG_INFO() @@ -355,7 +362,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_decrypt, 0, 0, ZEND_ARG_INFO(0, data) ZEND_ARG_INFO(0, method) ZEND_ARG_INFO(0, password) - ZEND_ARG_INFO(0, raw_input) + ZEND_ARG_INFO(0, options) ZEND_ARG_INFO(0, iv) ZEND_END_ARG_INFO() @@ -497,16 +504,13 @@ static void php_csr_free(zend_rsrc_list_entry *rsrc TS } /* }}} */ -/* {{{ openssl safe_mode & open_basedir checks */ -inline static int php_openssl_safe_mode_chk(char *filename TSRMLS_DC) +/* {{{ openssl open_basedir check */ +inline static int php_openssl_open_base_dir_chk(char *filename TSRMLS_DC) { - if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - return -1; - } if (php_check_open_basedir(filename TSRMLS_CC)) { return -1; } - + return 0; } /* }}} */ @@ -536,6 +540,8 @@ struct php_x509_request { /* {{{ */ int priv_key_encrypt; EVP_PKEY * priv_key; + + const EVP_CIPHER * priv_key_encrypt_cipher; }; /* }}} */ @@ -563,7 +569,7 @@ static void add_assoc_name_entry(zval * val, char * ke } else { subitem = val; } - + for (i = 0; i < X509_NAME_entry_count(name); i++) { unsigned char *to_add; int to_add_len; @@ -606,7 +612,7 @@ static void add_assoc_name_entry(zval * val, char * ke last = j; } i = last; - + if (obj_cnt > 1) { add_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries); } else { @@ -706,7 +712,7 @@ static inline int php_openssl_config_check_syntax(cons #endif { X509V3_CTX ctx; - + X509V3_set_ctx_test(&ctx); X509V3_set_conf_lhash(&ctx, config); if (!X509V3_EXT_add_conf(config, &ctx, (char *)section, NULL)) { @@ -766,6 +772,9 @@ static int add_oid_section(struct php_x509_request * r else \ varname = defval +static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo); + + static int php_openssl_parse_config(struct php_x509_request * req, zval * optional_args TSRMLS_DC) /* {{{ */ { char * str; @@ -782,7 +791,7 @@ static int php_openssl_parse_config(struct php_x509_re /* read in the oids */ str = CONF_get_string(req->req_config, NULL, "oid_file"); - if (str && !php_openssl_safe_mode_chk(str TSRMLS_CC)) { + if (str && !php_openssl_open_base_dir_chk(str TSRMLS_CC)) { BIO *oid_bio = BIO_new_file(str, "r"); if (oid_bio) { OBJ_create_objects(oid_bio); @@ -816,7 +825,22 @@ static int php_openssl_parse_config(struct php_x509_re req->priv_key_encrypt = 1; } } - + + if (req->priv_key_encrypt && optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), "encrypt_key_cipher", sizeof("encrypt_key_cipher"), (void**)&item) == SUCCESS) { + long cipher_algo = Z_LVAL_PP(item); + const EVP_CIPHER* cipher = php_openssl_get_evp_cipher_from_algo(cipher_algo); + if (cipher == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown cipher algorithm for private key."); + return FAILURE; + } else { + req->priv_key_encrypt_cipher = cipher; + } + } else { + req->priv_key_encrypt_cipher = NULL; + } + + + /* digest alg */ if (req->digest_name == NULL) { req->digest_name = CONF_get_string(req->req_config, req->section_name, "default_md"); @@ -838,7 +862,7 @@ static int php_openssl_parse_config(struct php_x509_re } PHP_SSL_CONFIG_SYNTAX_CHECK(request_extensions_section); - + return SUCCESS; } /* }}} */ @@ -860,12 +884,10 @@ static void php_openssl_dispose_config(struct php_x509 } /* }}} */ -static int php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded) /* {{{ */ +static int php_openssl_load_rand_file(const char * file, int *egdsocket, int *seeded TSRMLS_DC) /* {{{ */ { char buffer[MAXPATHLEN]; - TSRMLS_FETCH(); - *egdsocket = 0; *seeded = 0; @@ -962,6 +984,20 @@ static const EVP_CIPHER * php_openssl_get_evp_cipher_f return EVP_des_ede3_cbc(); break; #endif + +#ifndef OPENSSL_NO_AES + case PHP_OPENSSL_CIPHER_AES_128_CBC: + return EVP_aes_128_cbc(); + break; + case PHP_OPENSSL_CIPHER_AES_192_CBC: + return EVP_aes_192_cbc(); + break; + case PHP_OPENSSL_CIPHER_AES_256_CBC: + return EVP_aes_256_cbc(); + break; +#endif + + default: return NULL; break; @@ -984,17 +1020,15 @@ PHP_MINIT_FUNCTION(openssl) OpenSSL_add_all_digests(); OpenSSL_add_all_algorithms(); - ERR_load_ERR_strings(); - ERR_load_crypto_strings(); - ERR_load_EVP_strings(); + SSL_load_error_strings(); /* register a resource id number with OpenSSL so that we can map SSL -> stream structures in * OpenSSL callbacks */ ssl_stream_data_index = SSL_get_ex_new_index(0, "PHP stream index", NULL, NULL, NULL); - + REGISTER_STRING_CONSTANT("OPENSSL_VERSION_TEXT", OPENSSL_VERSION_TEXT, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_VERSION_NUMBER", OPENSSL_VERSION_NUMBER, CONST_CS|CONST_PERSISTENT); - + /* purposes for cert purpose checking */ REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_CLIENT", X509_PURPOSE_SSL_CLIENT, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("X509_PURPOSE_SSL_SERVER", X509_PURPOSE_SSL_SERVER, CONST_CS|CONST_PERSISTENT); @@ -1041,6 +1075,11 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_DES", PHP_OPENSSL_CIPHER_DES, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_3DES", PHP_OPENSSL_CIPHER_3DES, CONST_CS|CONST_PERSISTENT); #endif +#ifndef OPENSSL_NO_AES + REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_128_CBC", PHP_OPENSSL_CIPHER_AES_128_CBC, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_192_CBC", PHP_OPENSSL_CIPHER_AES_192_CBC, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_AES_256_CBC", PHP_OPENSSL_CIPHER_AES_256_CBC, CONST_CS|CONST_PERSISTENT); +#endif /* Values for key types */ REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_RSA", OPENSSL_KEYTYPE_RSA, CONST_CS|CONST_PERSISTENT); @@ -1052,6 +1091,9 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT); #endif + REGISTER_LONG_CONSTANT("OPENSSL_RAW_DATA", OPENSSL_RAW_DATA, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_ZERO_PADDING", OPENSSL_ZERO_PADDING, CONST_CS|CONST_PERSISTENT); + #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) /* SNI support included in OpenSSL >= 0.9.8j */ REGISTER_LONG_CONSTANT("OPENSSL_TLSEXT_SERVER_NAME", 1, CONST_CS|CONST_PERSISTENT); @@ -1084,7 +1126,7 @@ PHP_MINIT_FUNCTION(openssl) php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC); php_register_url_stream_wrapper("ftps", &php_stream_ftp_wrapper TSRMLS_CC); - + return SUCCESS; } /* }}} */ @@ -1174,7 +1216,7 @@ static X509 * php_openssl_x509_from_zval(zval ** val, /* read cert from the named file */ BIO *in; - if (php_openssl_safe_mode_chk(Z_STRVAL_PP(val) + (sizeof("file://") - 1) TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(Z_STRVAL_PP(val) + (sizeof("file://") - 1) TSRMLS_CC)) { return NULL; } @@ -1200,7 +1242,7 @@ static X509 * php_openssl_x509_from_zval(zval ** val, } if (cert && makeresource && resourceval) { - *resourceval = zend_list_insert(cert, le_x509); + *resourceval = zend_list_insert(cert, le_x509 TSRMLS_CC); } return cert; } @@ -1219,7 +1261,7 @@ PHP_FUNCTION(openssl_x509_export_to_file) char * filename; int filename_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs|b", &zcert, &filename, &filename_len, ¬ext) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zp|b", &zcert, &filename, &filename_len, ¬ext) == FAILURE) { return; } RETVAL_FALSE; @@ -1230,7 +1272,7 @@ PHP_FUNCTION(openssl_x509_export_to_file) return; } - if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) { return; } @@ -1304,14 +1346,14 @@ PHP_FUNCTION(openssl_x509_check_private_key) long certresource = -1, keyresource = -1; RETVAL_FALSE; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &zcert, &zkey) == FAILURE) { return; } cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC); if (cert == NULL) { RETURN_FALSE; - } + } key = php_openssl_evp_from_zval(zkey, 0, "", 1, &keyresource TSRMLS_CC); if (key) { RETVAL_BOOL(X509_check_private_key(cert, key)); @@ -1364,11 +1406,11 @@ PHP_FUNCTION(openssl_x509_parse) snprintf(buf, sizeof(buf), "%08lx", X509_subject_name_hash(cert)); add_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_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1); + 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)); @@ -1460,7 +1502,7 @@ static STACK_OF(X509) * load_all_certs_from_file(char goto end; } - if (php_openssl_safe_mode_chk(certfile TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(certfile TSRMLS_CC)) { sk_X509_free(stack); goto end; } @@ -1570,8 +1612,8 @@ clean_exit: if (certresource == 1 && cert) { X509_free(cert); } - if (cainfo) { - X509_STORE_free(cainfo); + if (cainfo) { + X509_STORE_free(cainfo); } if (untrustedchain) { sk_X509_pop_free(untrustedchain, X509_free); @@ -1624,7 +1666,7 @@ static X509_STORE * setup_verify(zval * calist TSRMLS_ dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, Z_STRVAL_PP(item), X509_FILETYPE_PEM)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "error loading directory %s", Z_STRVAL_PP(item)); - } else { + } else { ndirs++; } dir_lookup = NULL; @@ -1718,11 +1760,11 @@ static STACK_OF(X509) * php_array_to_X509_sk(zval ** z if (certresource != -1) { cert = X509_dup(cert); - + if (cert == NULL) { goto clean_exit; } - + } sk_X509_push(sk, cert); @@ -1731,7 +1773,7 @@ static STACK_OF(X509) * php_array_to_X509_sk(zval ** z } else { /* a single certificate */ cert = php_openssl_x509_from_zval(zcerts, 0, &certresource TSRMLS_CC); - + if (cert == NULL) { goto clean_exit; } @@ -1768,15 +1810,11 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file) 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) + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zpzs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE) return; RETVAL_FALSE; - if (strlen(filename) != filename_len) { - return; - } - 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"); @@ -1791,7 +1829,7 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file) 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)) { + if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) { goto cleanup; } @@ -1812,9 +1850,9 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file) p12 = PKCS12_create(pass, friendly_name, priv_key, cert, ca, 0, 0, 0, 0, 0); - bio_out = BIO_new_file(filename, "w"); + bio_out = BIO_new_file(filename, "w"); if (bio_out) { - + i2d_PKCS12_bio(bio_out, p12); RETVAL_TRUE; @@ -1825,13 +1863,13 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file) 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) { + if (certresource == -1 && cert) { X509_free(cert); } } @@ -1857,7 +1895,7 @@ PHP_FUNCTION(openssl_pkcs12_export) 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"); @@ -1880,7 +1918,7 @@ PHP_FUNCTION(openssl_pkcs12_export) 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()); @@ -1897,13 +1935,13 @@ PHP_FUNCTION(openssl_pkcs12_export) 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) { + if (certresource == -1 && cert) { X509_free(cert); } } @@ -1927,12 +1965,12 @@ PHP_FUNCTION(openssl_pkcs12_read) return; RETVAL_FALSE; - + bio_in = BIO_new(BIO_s_mem()); - + if(!BIO_write(bio_in, zp12, zp12_len)) goto cleanup; - + if(d2i_PKCS12_bio(bio_in, &p12)) { if(PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { BIO * bio_out; @@ -1962,12 +2000,12 @@ PHP_FUNCTION(openssl_pkcs12_read) 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; @@ -1975,7 +2013,7 @@ PHP_FUNCTION(openssl_pkcs12_read) MAKE_STD_ZVAL(zextracert); ZVAL_STRINGL(zextracert, bio_buf->data, bio_buf->length, 1); add_index_zval(zextracerts, i, zextracert); - + } BIO_free(bio_out); @@ -1987,13 +2025,13 @@ PHP_FUNCTION(openssl_pkcs12_read) } else { zval_dtor(zextracerts); } - + RETVAL_TRUE; - + PKCS12_free(p12); } } - + cleanup: if (bio_in) { BIO_free(bio_in); @@ -2001,7 +2039,7 @@ PHP_FUNCTION(openssl_pkcs12_read) if (pkey) { EVP_PKEY_free(pkey); } - if (cert) { + if (cert) { X509_free(cert); } } @@ -2020,7 +2058,7 @@ static int php_openssl_make_REQ(struct php_x509_reques return FAILURE; } dn_sk = CONF_get_section(req->req_config, dn_sect); - if (dn_sk == NULL) { + if (dn_sk == NULL) { return FAILURE; } attr_sect = CONF_get_string(req->req_config, req->section_name, "attributes"); @@ -2040,15 +2078,15 @@ static int php_openssl_make_REQ(struct php_x509_reques X509_NAME * subj; HashPosition hpos; zval ** item; - + subj = X509_REQ_get_subject_name(csr); /* apply values from the dn hash */ zend_hash_internal_pointer_reset_ex(HASH_OF(dn), &hpos); while(zend_hash_get_current_data_ex(HASH_OF(dn), (void**)&item, &hpos) == SUCCESS) { - char * strindex = NULL; + char * strindex = NULL; uint strindexlen = 0; ulong intindex; - + zend_hash_get_current_key_ex(HASH_OF(dn), &strindex, &strindexlen, &intindex, 0, &hpos); convert_to_string_ex(item); @@ -2058,10 +2096,14 @@ static int php_openssl_make_REQ(struct php_x509_reques nid = OBJ_txt2nid(strindex); if (nid != NID_undef) { - if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, + if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (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)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "dn: add_entry_by_NID %d -> %s (failed; check error" + " queue and value of string_mask OpenSSL option " + "if illegal characters are reported)", + nid, Z_STRVAL_PP(item)); return FAILURE; } } else { @@ -2075,10 +2117,10 @@ static int php_openssl_make_REQ(struct php_x509_reques for(i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { int len; char buffer[200 + 1]; /*200 + \0 !*/ - + v = sk_CONF_VALUE_value(dn_sk, i); type = v->name; - + len = strlen(type); if (len < sizeof("_default")) { continue; @@ -2093,7 +2135,7 @@ static int php_openssl_make_REQ(struct php_x509_reques memcpy(buffer, type, len); buffer[len] = '\0'; type = buffer; - + /* Skip past any leading X. X: X, etc to allow for multiple * instances */ for (str = type; *str; str++) { @@ -2110,7 +2152,7 @@ static int php_openssl_make_REQ(struct php_x509_reques if (X509_NAME_get_index_by_NID(subj, nid, -1) >= 0) { continue; } - if (!X509_NAME_add_entry_by_txt(subj, type, MBSTRING_ASC, (unsigned char*)v->value, -1, -1, 0)) { + if (!X509_NAME_add_entry_by_txt(subj, type, MBSTRING_UTF8, (unsigned char*)v->value, -1, -1, 0)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_entry_by_txt %s -> %s (failed)", type, v->value); return FAILURE; } @@ -2134,7 +2176,7 @@ static int php_openssl_make_REQ(struct php_x509_reques nid = OBJ_txt2nid(strindex); if (nid != NID_undef) { - if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_ASC, (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0)) { + if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (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)); return FAILURE; } @@ -2151,8 +2193,12 @@ static int php_openssl_make_REQ(struct php_x509_reques if (X509_REQ_get_attr_by_NID(csr, nid, -1) >= 0) { continue; } - if (!X509_REQ_add1_attr_by_txt(csr, v->name, MBSTRING_ASC, (unsigned char*)v->value, -1)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "add1_attr_by_txt %s -> %s (failed)", v->name, v->value); + if (!X509_REQ_add1_attr_by_txt(csr, v->name, MBSTRING_UTF8, (unsigned char*)v->value, -1)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "add1_attr_by_txt %s -> %s (failed; check error queue " + "and value of string_mask OpenSSL option if illegal " + "characters are reported)", + v->name, v->value); return FAILURE; } } @@ -2170,7 +2216,7 @@ static X509_REQ * php_openssl_csr_from_zval(zval ** va X509_REQ * csr = NULL; char * filename = NULL; BIO * in; - + if (resourceval) { *resourceval = -1; } @@ -2194,7 +2240,7 @@ static X509_REQ * php_openssl_csr_from_zval(zval ** va filename = Z_STRVAL_PP(val) + (sizeof("file://") - 1); } if (filename) { - if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) { return NULL; } in = BIO_new_file(filename, "r"); @@ -2219,22 +2265,18 @@ PHP_FUNCTION(openssl_csr_export_to_file) BIO * bio_out; long csr_resource; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|b", &zcsr, &filename, &filename_len, ¬ext) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp|b", &zcsr, &filename, &filename_len, ¬ext) == FAILURE) { return; } RETVAL_FALSE; - if (strlen(filename) != filename_len) { - return; - } - csr = php_openssl_csr_from_zval(&zcsr, 0, &csr_resource TSRMLS_CC); if (csr == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get CSR from parameter 1"); return; } - if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) { return; } @@ -2315,13 +2357,13 @@ PHP_FUNCTION(openssl_csr_sign) long csr_resource, certresource = 0, keyresource = -1; int i; struct php_x509_request req; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ!Zl|a!l", &zcsr, &zcert, &zpkey, &num_days, &args, &serial) == FAILURE) return; RETVAL_FALSE; PHP_SSL_REQ_INIT(&req); - + csr = php_openssl_csr_from_zval(zcsr, 0, &csr_resource TSRMLS_CC); if (csr == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get CSR from parameter 1"); @@ -2343,7 +2385,7 @@ PHP_FUNCTION(openssl_csr_sign) php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key does not correspond to signing cert"); goto cleanup; } - + if (PHP_SSL_REQ_PARSE(&req, args) == FAILURE) { goto cleanup; } @@ -2363,9 +2405,9 @@ PHP_FUNCTION(openssl_csr_sign) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Signature did not match the certificate request"); goto cleanup; } - + /* Now we can get on with it */ - + new_cert = X509_new(); if (new_cert == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "No memory"); @@ -2376,7 +2418,7 @@ PHP_FUNCTION(openssl_csr_sign) goto cleanup; ASN1_INTEGER_set(X509_get_serialNumber(new_cert), serial); - + X509_set_subject_name(new_cert, X509_REQ_get_subject_name(csr)); if (cert == NULL) { @@ -2393,7 +2435,7 @@ PHP_FUNCTION(openssl_csr_sign) } if (req.extensions_section) { X509V3_CTX ctx; - + X509V3_set_ctx(&ctx, cert, new_cert, csr, NULL, 0); X509V3_set_conf_lhash(&ctx, req.req_config); if (!X509V3_EXT_add_conf(req.req_config, &ctx, req.extensions_section, new_cert)) { @@ -2406,11 +2448,11 @@ PHP_FUNCTION(openssl_csr_sign) php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to sign it"); goto cleanup; } - + /* Succeeded; lets return the cert */ - RETVAL_RESOURCE(zend_list_insert(new_cert, le_x509)); + RETVAL_RESOURCE(zend_list_insert(new_cert, le_x509 TSRMLS_CC)); new_cert = NULL; - + cleanup: if (cert == new_cert) { @@ -2427,7 +2469,7 @@ cleanup: if (csr_resource == -1 && csr) { X509_REQ_free(csr); } - if (certresource == -1 && cert) { + if (certresource == -1 && cert) { X509_free(cert); } if (new_cert) { @@ -2446,12 +2488,12 @@ PHP_FUNCTION(openssl_csr_new) X509_REQ * csr = NULL; int we_made_the_key = 1; long key_resource; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) { return; } RETVAL_FALSE; - + PHP_SSL_REQ_INIT(&req); if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) { @@ -2483,10 +2525,10 @@ PHP_FUNCTION(openssl_csr_new) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error loading extension section %s", req.request_extensions_section); } else { RETVAL_TRUE; - + if (X509_REQ_sign(csr, req.priv_key, req.digest)) { - RETVAL_RESOURCE(zend_list_insert(csr, le_csr)); - csr = NULL; + RETVAL_RESOURCE(zend_list_insert(csr, le_csr TSRMLS_CC)); + csr = NULL; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error signing request"); } @@ -2494,7 +2536,7 @@ PHP_FUNCTION(openssl_csr_new) if (we_made_the_key) { /* and a resource for the private key */ zval_dtor(out_pkey); - ZVAL_RESOURCE(out_pkey, zend_list_insert(req.priv_key, le_key)); + ZVAL_RESOURCE(out_pkey, zend_list_insert(req.priv_key, le_key TSRMLS_CC)); req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */ } else if (key_resource != -1) { req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */ @@ -2567,7 +2609,7 @@ PHP_FUNCTION(openssl_csr_get_public_key) } tpubkey=X509_REQ_get_pubkey(csr); - RETVAL_RESOURCE(zend_list_insert(tpubkey, le_key)); + RETVAL_RESOURCE(zend_list_insert(tpubkey, le_key TSRMLS_CC)); return; } /* }}} */ @@ -2611,14 +2653,14 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** va } if (Z_TYPE_PP(val) == IS_ARRAY) { zval ** zphrase; - + /* get passphrase */ if (zend_hash_index_find(HASH_OF(*val), 1, (void **)&zphrase) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "key array must be of the form array(0 => key, 1 => phrase)"); return NULL; } - + if (Z_TYPE_PP(zphrase) == IS_STRING) { passphrase = Z_STRVAL_PP(zphrase); } else { @@ -2643,7 +2685,7 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** va if (!what) { TMP_CLEAN; } - if (resourceval) { + if (resourceval) { *resourceval = Z_LVAL_PP(val); } if (type == le_x509) { @@ -2677,8 +2719,8 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** va } } 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 - * See bug38255.phpt + /* passing non string values leaks, object uses toString, it returns NULL + * See bug38255.phpt */ if (!(Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_OBJECT)) { TMP_CLEAN; @@ -2712,7 +2754,7 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** va BIO *in; if (filename) { - if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) { TMP_CLEAN; } in = BIO_new_file(filename, "r"); @@ -2752,7 +2794,7 @@ static EVP_PKEY * php_openssl_generate_private_key(str char * randfile = NULL; int egdsocket, seeded; EVP_PKEY * return_val = NULL; - + if (req->priv_key_bits < MIN_KEY_LENGTH) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key length is too short; it needs to be at least %d bits, not %d", MIN_KEY_LENGTH, req->priv_key_bits); @@ -2760,8 +2802,8 @@ static EVP_PKEY * php_openssl_generate_private_key(str } randfile = CONF_get_string(req->req_config, req->section_name, "RANDFILE"); - php_openssl_load_rand_file(randfile, &egdsocket, &seeded); - + php_openssl_load_rand_file(randfile, &egdsocket, &seeded TSRMLS_CC); + if ((req->priv_key = EVP_PKEY_new()) != NULL) { switch(req->priv_key_type) { case OPENSSL_KEYTYPE_RSA: @@ -2811,13 +2853,13 @@ static EVP_PKEY * php_openssl_generate_private_key(str } php_openssl_write_rand_file(randfile, egdsocket, seeded); - + if (return_val == NULL) { EVP_PKEY_free(req->priv_key); req->priv_key = NULL; return NULL; } - + return return_val; } /* }}} */ @@ -2846,7 +2888,7 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey T case EVP_PKEY_DSA4: assert(pkey->pkey.dsa != NULL); - if (NULL == pkey->pkey.dsa->p || NULL == pkey->pkey.dsa->q || NULL == pkey->pkey.dsa->priv_key){ + if (NULL == pkey->pkey.dsa->p || NULL == pkey->pkey.dsa->q || NULL == pkey->pkey.dsa->priv_key){ return 0; } break; @@ -2921,7 +2963,7 @@ PHP_FUNCTION(openssl_pkey_new) OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, iqmp); if (rsa->n && rsa->d) { if (EVP_PKEY_assign_RSA(pkey, rsa)) { - RETURN_RESOURCE(zend_list_insert(pkey, le_key)); + RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC)); } } RSA_free(rsa); @@ -2945,7 +2987,7 @@ PHP_FUNCTION(openssl_pkey_new) DSA_generate_key(dsa); } if (EVP_PKEY_assign_DSA(pkey, dsa)) { - RETURN_RESOURCE(zend_list_insert(pkey, le_key)); + RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC)); } } DSA_free(dsa); @@ -2968,7 +3010,7 @@ PHP_FUNCTION(openssl_pkey_new) DH_generate_key(dh); } if (EVP_PKEY_assign_DH(pkey, dh)) { - RETURN_RESOURCE(zend_list_insert(pkey, le_key)); + RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC)); } } DH_free(dh); @@ -2977,7 +3019,7 @@ PHP_FUNCTION(openssl_pkey_new) } RETURN_FALSE; } - } + } PHP_SSL_REQ_INIT(&req); @@ -2985,7 +3027,7 @@ PHP_FUNCTION(openssl_pkey_new) { if (php_openssl_generate_private_key(&req TSRMLS_CC)) { /* pass back a key resource */ - RETVAL_RESOURCE(zend_list_insert(req.priv_key, le_key)); + RETVAL_RESOURCE(zend_list_insert(req.priv_key, le_key TSRMLS_CC)); /* make sure the cleanup code doesn't zap it! */ req.priv_key = NULL; } @@ -3006,34 +3048,34 @@ PHP_FUNCTION(openssl_pkey_export_to_file) EVP_PKEY * key; BIO * bio_out = NULL; const EVP_CIPHER * cipher; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) { + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zp|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) { return; } RETVAL_FALSE; - if (strlen(filename) != filename_len) { - return; - } - key = php_openssl_evp_from_zval(zpkey, 0, passphrase, 0, &key_resource TSRMLS_CC); if (key == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1"); RETURN_FALSE; } - - if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { + + if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) { RETURN_FALSE; } - + PHP_SSL_REQ_INIT(&req); if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) { bio_out = BIO_new_file(filename, "w"); if (passphrase && req.priv_key_encrypt) { - cipher = (EVP_CIPHER *) EVP_des_ede3_cbc(); + if (req.priv_key_encrypt_cipher) { + cipher = req.priv_key_encrypt_cipher; + } else { + cipher = (EVP_CIPHER *) EVP_des_ede3_cbc(); + } } else { cipher = NULL; } @@ -3065,7 +3107,7 @@ PHP_FUNCTION(openssl_pkey_export) EVP_PKEY * key; BIO * bio_out = NULL; const EVP_CIPHER * cipher; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) { return; } @@ -3077,14 +3119,18 @@ PHP_FUNCTION(openssl_pkey_export) php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get key from parameter 1"); RETURN_FALSE; } - + PHP_SSL_REQ_INIT(&req); if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) { bio_out = BIO_new(BIO_s_mem()); if (passphrase && req.priv_key_encrypt) { - cipher = (EVP_CIPHER *) EVP_des_ede3_cbc(); + if (req.priv_key_encrypt_cipher) { + cipher = req.priv_key_encrypt_cipher; + } else { + cipher = (EVP_CIPHER *) EVP_des_ede3_cbc(); + } } else { cipher = NULL; } @@ -3193,7 +3239,7 @@ PHP_FUNCTION(openssl_pkey_get_details) array_init(return_value); add_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey)); add_assoc_stringl(return_value, "key", pbio, pbio_len, 1); - /*TODO: Use the real values once the openssl constants are used + /*TODO: Use the real values once the openssl constants are used * See the enum at the top of this file */ switch (EVP_PKEY_type(pkey->type)) { @@ -3217,7 +3263,7 @@ PHP_FUNCTION(openssl_pkey_get_details) add_assoc_zval(return_value, "rsa", rsa); } - break; + break; case EVP_PKEY_DSA: case EVP_PKEY_DSA2: case EVP_PKEY_DSA3: @@ -3238,7 +3284,7 @@ PHP_FUNCTION(openssl_pkey_get_details) } break; case EVP_PKEY_DH: - + ktype = OPENSSL_KEYTYPE_DH; if (pkey->pkey.dh != NULL) { @@ -3254,7 +3300,7 @@ PHP_FUNCTION(openssl_pkey_get_details) } break; -#ifdef EVP_PKEY_EC +#ifdef EVP_PKEY_EC case EVP_PKEY_EC: ktype = OPENSSL_KEYTYPE_EC; break; @@ -3288,15 +3334,15 @@ PHP_FUNCTION(openssl_pkcs7_verify) char * extracerts = NULL; int extracerts_len = 0; char * signersfilename = NULL; int signersfilename_len = 0; char * datafilename = NULL; int datafilename_len = 0; - + RETVAL_LONG(-1); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|sass", &filename, &filename_len, + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pl|papp", &filename, &filename_len, &flags, &signersfilename, &signersfilename_len, &cainfo, &extracerts, &extracerts_len, &datafilename, &datafilename_len) == FAILURE) { return; } - + if (extracerts) { others = load_all_certs_from_file(extracerts); if (others == NULL) { @@ -3311,7 +3357,7 @@ PHP_FUNCTION(openssl_pkcs7_verify) if (!store) { goto clean_exit; } - if (php_openssl_safe_mode_chk(filename TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) { goto clean_exit; } @@ -3329,7 +3375,7 @@ PHP_FUNCTION(openssl_pkcs7_verify) if (datafilename) { - if (php_openssl_safe_mode_chk(datafilename TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(datafilename TSRMLS_CC)) { goto clean_exit; } @@ -3348,11 +3394,11 @@ PHP_FUNCTION(openssl_pkcs7_verify) if (signersfilename) { BIO *certout; - - if (php_openssl_safe_mode_chk(signersfilename TSRMLS_CC)) { + + if (php_openssl_open_base_dir_chk(signersfilename TSRMLS_CC)) { goto clean_exit; } - + certout = BIO_new_file(signersfilename, "w"); if (certout) { int i; @@ -3401,32 +3447,25 @@ PHP_FUNCTION(openssl_pkcs7_encrypt) char * strindex; char * infilename = NULL; int infilename_len; char * outfilename = NULL; int outfilename_len; - + RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZa!|ll", &infilename, &infilename_len, + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZa!|ll", &infilename, &infilename_len, &outfilename, &outfilename_len, &zrecipcerts, &zheaders, &flags, &cipherid) == FAILURE) return; - if (strlen(infilename) != infilename_len) { - return; - } - if (strlen(outfilename) != outfilename_len) { + if (php_openssl_open_base_dir_chk(infilename TSRMLS_CC) || php_openssl_open_base_dir_chk(outfilename TSRMLS_CC)) { return; } - if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) { - return; - } - infile = BIO_new_file(infilename, "r"); if (infile == NULL) { goto clean_exit; } outfile = BIO_new_file(outfilename, "w"); - if (outfile == NULL) { + if (outfile == NULL) { goto clean_exit; } @@ -3547,25 +3586,18 @@ PHP_FUNCTION(openssl_pkcs7_sign) char * outfilename; int outfilename_len; char * extracertsfilename = NULL; int extracertsfilename_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZZa!|ls", + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZZa!|lp", &infilename, &infilename_len, &outfilename, &outfilename_len, &zcert, &zprivkey, &zheaders, &flags, &extracertsfilename, &extracertsfilename_len) == FAILURE) { return; } + RETVAL_FALSE; - if (strlen(infilename) != infilename_len) { - return; - } - - if (strlen(outfilename) != outfilename_len) { - return; - } - if (extracertsfilename) { others = load_all_certs_from_file(extracertsfilename); - if (others == NULL) { + if (others == NULL) { goto clean_exit; } } @@ -3582,7 +3614,7 @@ PHP_FUNCTION(openssl_pkcs7_sign) goto clean_exit; } - if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) { + if (php_openssl_open_base_dir_chk(infilename TSRMLS_CC) || php_openssl_open_base_dir_chk(outfilename TSRMLS_CC)) { goto clean_exit; } @@ -3658,21 +3690,13 @@ PHP_FUNCTION(openssl_pkcs7_decrypt) char * infilename; int infilename_len; char * outfilename; int outfilename_len; - RETVAL_FALSE; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|Z", &infilename, &infilename_len, + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZ|Z", &infilename, &infilename_len, &outfilename, &outfilename_len, &recipcert, &recipkey) == FAILURE) { return; } - if (strlen(infilename) != infilename_len) { - return; - } + RETVAL_FALSE; - if (strlen(outfilename) != outfilename_len) { - return; - } - cert = php_openssl_x509_from_zval(recipcert, 0, &certresval TSRMLS_CC); if (cert == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to coerce parameter 3 to x509 cert"); @@ -3684,8 +3708,8 @@ PHP_FUNCTION(openssl_pkcs7_decrypt) php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to get private key"); goto clean_exit; } - - if (php_openssl_safe_mode_chk(infilename TSRMLS_CC) || php_openssl_safe_mode_chk(outfilename TSRMLS_CC)) { + + if (php_openssl_open_base_dir_chk(infilename TSRMLS_CC) || php_openssl_open_base_dir_chk(outfilename TSRMLS_CC)) { goto clean_exit; } @@ -3703,7 +3727,7 @@ PHP_FUNCTION(openssl_pkcs7_decrypt) if (p7 == NULL) { goto clean_exit; } - if (PKCS7_decrypt(p7, key, cert, out, PKCS7_DETACHED)) { + if (PKCS7_decrypt(p7, key, cert, out, PKCS7_DETACHED)) { RETVAL_TRUE; } clean_exit: @@ -3736,7 +3760,7 @@ PHP_FUNCTION(openssl_private_encrypt) int data_len; long padding = RSA_PKCS1_PADDING; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { return; } RETVAL_FALSE; @@ -3754,10 +3778,10 @@ PHP_FUNCTION(openssl_private_encrypt) switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - successful = (RSA_private_encrypt(data_len, - (unsigned char *)data, - cryptedbuf, - pkey->pkey.rsa, + successful = (RSA_private_encrypt(data_len, + (unsigned char *)data, + cryptedbuf, + pkey->pkey.rsa, padding) == cryptedlen); break; default: @@ -3774,7 +3798,7 @@ PHP_FUNCTION(openssl_private_encrypt) if (cryptedbuf) { efree(cryptedbuf); } - if (keyresource == -1) { + if (keyresource == -1) { EVP_PKEY_free(pkey); } } @@ -3812,10 +3836,10 @@ PHP_FUNCTION(openssl_private_decrypt) switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - cryptedlen = RSA_private_decrypt(data_len, - (unsigned char *)data, - crypttemp, - pkey->pkey.rsa, + cryptedlen = RSA_private_decrypt(data_len, + (unsigned char *)data, + crypttemp, + pkey->pkey.rsa, padding); if (cryptedlen != -1) { cryptedbuf = emalloc(cryptedlen + 1); @@ -3840,7 +3864,7 @@ PHP_FUNCTION(openssl_private_decrypt) if (keyresource == -1) { EVP_PKEY_free(pkey); } - if (cryptedbuf) { + if (cryptedbuf) { efree(cryptedbuf); } } @@ -3864,7 +3888,7 @@ PHP_FUNCTION(openssl_public_encrypt) return; RETVAL_FALSE; - + pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC); if (pkey == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "key parameter is not a valid public key"); @@ -3877,10 +3901,10 @@ PHP_FUNCTION(openssl_public_encrypt) switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - successful = (RSA_public_encrypt(data_len, - (unsigned char *)data, - cryptedbuf, - pkey->pkey.rsa, + successful = (RSA_public_encrypt(data_len, + (unsigned char *)data, + cryptedbuf, + pkey->pkey.rsa, padding) == cryptedlen); break; default: @@ -3923,7 +3947,7 @@ PHP_FUNCTION(openssl_public_decrypt) return; } RETVAL_FALSE; - + pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC); if (pkey == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "key parameter is not a valid public key"); @@ -3936,10 +3960,10 @@ PHP_FUNCTION(openssl_public_decrypt) switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - cryptedlen = RSA_public_decrypt(data_len, - (unsigned char *)data, - crypttemp, - pkey->pkey.rsa, + cryptedlen = RSA_public_decrypt(data_len, + (unsigned char *)data, + crypttemp, + pkey->pkey.rsa, padding); if (cryptedlen != -1) { cryptedbuf = emalloc(cryptedlen + 1); @@ -3947,10 +3971,10 @@ PHP_FUNCTION(openssl_public_decrypt) successful = 1; } break; - + default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!"); - + } efree(crypttemp); @@ -4068,7 +4092,7 @@ PHP_FUNCTION(openssl_verify) char * signature; int signature_len; zval *method = NULL; long signature_algo = OPENSSL_ALGO_SHA1; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|z", &data, &data_len, &signature, &signature_len, &key, &method) == FAILURE) { return; } @@ -4127,7 +4151,7 @@ PHP_FUNCTION(openssl_seal) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) { return; } - + pubkeysht = HASH_OF(pubkeys); nkeys = pubkeysht ? zend_hash_num_elements(pubkeysht) : 0; if (!nkeys) { @@ -4222,7 +4246,7 @@ clean_exit: if (key_resources[i] == -1) { EVP_PKEY_free(pkeys[i]); } - if (eks[i]) { + if (eks[i]) { efree(eks[i]); } } @@ -4268,13 +4292,13 @@ PHP_FUNCTION(openssl_open) } else { cipher = EVP_rc4(); } - + buf = emalloc(data_len + 1); if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) { if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) { efree(buf); - if (keyresource == -1) { + if (keyresource == -1) { EVP_PKEY_free(pkey); } RETURN_FALSE; @@ -4511,7 +4535,7 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff); return NULL; - } + } } tmpssl = SSL_new(ctx); @@ -4568,7 +4592,7 @@ PHP_FUNCTION(openssl_get_md_methods) } array_init(return_value); OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, - aliases ? openssl_add_method_or_alias: openssl_add_method, + aliases ? openssl_add_method_or_alias: openssl_add_method, return_value); } /* }}} */ @@ -4584,7 +4608,7 @@ PHP_FUNCTION(openssl_get_cipher_methods) } array_init(return_value); OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, - aliases ? openssl_add_method_or_alias: openssl_add_method, + aliases ? openssl_add_method_or_alias: openssl_add_method, return_value); } /* }}} */ @@ -4668,20 +4692,20 @@ static zend_bool php_openssl_validate_iv(char **piv, i } -/* {{{ proto string openssl_encrypt(string data, string method, string password [, bool raw_output=false [, string $iv='']]) +/* {{{ proto string openssl_encrypt(string data, string method, string password [, long options=0 [, string $iv='']]) Encrypts given data with given method and key, returns raw or base64 encoded string */ PHP_FUNCTION(openssl_encrypt) { - zend_bool raw_output = 0; + long options = 0; char *data, *method, *password, *iv = ""; int data_len, method_len, password_len, iv_len = 0, max_iv_len; const EVP_CIPHER *cipher_type; EVP_CIPHER_CTX cipher_ctx; - int i, outlen, keylen; + int i=0, outlen, keylen; unsigned char *outbuf, *key; zend_bool free_iv; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|bs", &data, &data_len, &method, &method_len, &password, &password_len, &raw_output, &iv, &iv_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) { return; } cipher_type = EVP_get_cipherbyname(method); @@ -4713,13 +4737,16 @@ PHP_FUNCTION(openssl_encrypt) EVP_CIPHER_CTX_set_key_length(&cipher_ctx, password_len); } EVP_EncryptInit_ex(&cipher_ctx, NULL, NULL, key, (unsigned char *)iv); + if (options & OPENSSL_ZERO_PADDING) { + EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0); + } if (data_len > 0) { EVP_EncryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len); } outlen = i; if (EVP_EncryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) { outlen += i; - if (raw_output) { + if (options & OPENSSL_RAW_DATA) { outbuf[outlen] = '\0'; RETVAL_STRINGL((char *)outbuf, outlen, 0); } else { @@ -4744,11 +4771,11 @@ PHP_FUNCTION(openssl_encrypt) } /* }}} */ -/* {{{ proto string openssl_decrypt(string data, string method, string password [, bool raw_input=false [, string $iv = '']]) +/* {{{ proto string openssl_decrypt(string data, string method, string password [, long options=0 [, string $iv = '']]) Takes raw or base64 encoded string and dectupt it using given method and key */ PHP_FUNCTION(openssl_decrypt) { - zend_bool raw_input = 0; + long options = 0; char *data, *method, *password, *iv = ""; int data_len, method_len, password_len, iv_len = 0; const EVP_CIPHER *cipher_type; @@ -4759,7 +4786,7 @@ PHP_FUNCTION(openssl_decrypt) char *base64_str = NULL; zend_bool free_iv; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|bs", &data, &data_len, &method, &method_len, &password, &password_len, &raw_input, &iv, &iv_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) { return; } @@ -4774,8 +4801,12 @@ PHP_FUNCTION(openssl_decrypt) RETURN_FALSE; } - if (!raw_input) { + if (!(options & OPENSSL_RAW_DATA)) { base64_str = (char*)php_base64_decode((unsigned char*)data, data_len, &base64_str_len); + if (!base64_str) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to base64 decode the input"); + RETURN_FALSE; + } data_len = base64_str_len; data = base64_str; } @@ -4799,6 +4830,9 @@ PHP_FUNCTION(openssl_decrypt) EVP_CIPHER_CTX_set_key_length(&cipher_ctx, password_len); } EVP_DecryptInit_ex(&cipher_ctx, NULL, NULL, key, (unsigned char *)iv); + if (options & OPENSSL_ZERO_PADDING) { + EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0); + } EVP_DecryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len); outlen = i; if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) { @@ -4910,10 +4944,25 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) buffer = emalloc(buffer_length + 1); +#ifdef PHP_WIN32 + strong_result = 1; + /* random/urandom equivalent on Windows */ + if (php_win32_get_random_bytes(buffer, (size_t) buffer_length) == FAILURE) { + efree(buffer); + if (zstrong_result_returned) { + ZVAL_BOOL(zstrong_result_returned, 0); + } + RETURN_FALSE; + } +#else if ((strong_result = RAND_pseudo_bytes(buffer, buffer_length)) < 0) { efree(buffer); + if (zstrong_result_returned) { + ZVAL_BOOL(zstrong_result_returned, 0); + } RETURN_FALSE; } +#endif buffer[buffer_length] = 0; RETVAL_STRINGL((char *)buffer, buffer_length, 0);