Diff for /embedaddon/php/ext/openssl/openssl.c between versions 1.1.1.3 and 1.1.1.5

version 1.1.1.3, 2013/07/22 01:31:57 version 1.1.1.5, 2014/06/15 20:03:52
Line 2 Line 2
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | PHP Version 5                                                        |     | PHP Version 5                                                        |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
   | Copyright (c) 1997-2013 The PHP Group                                |   | Copyright (c) 1997-2014 The PHP Group                                |
    +----------------------------------------------------------------------+     +----------------------------------------------------------------------+
    | This source file is subject to version 3.01 of the PHP license,      |     | 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        |     | that is bundled with this package in the file LICENSE, and is        |
Line 78 Line 78
 #endif  #endif
 #define DEBUG_SMIME     0  #define DEBUG_SMIME     0
   
   #if !defined(OPENSSL_NO_EC) && defined(EVP_PKEY_EC)
   #define HAVE_EVP_PKEY_EC 1
   #endif
   
 /* FIXME: Use the openssl constants instead of  /* FIXME: Use the openssl constants instead of
  * enum. It is now impossible to match real values   * enum. It is now impossible to match real values
  * against php constants. Also sorry to break the   * against php constants. Also sorry to break the
Line 88  enum php_openssl_key_type { Line 92  enum php_openssl_key_type {
         OPENSSL_KEYTYPE_DSA,          OPENSSL_KEYTYPE_DSA,
         OPENSSL_KEYTYPE_DH,          OPENSSL_KEYTYPE_DH,
         OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA,          OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA,
#ifdef EVP_PKEY_EC#ifdef HAVE_EVP_PKEY_EC
         OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH +1          OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH +1
 #endif  #endif
 };  };
Line 561  static EVP_PKEY * php_openssl_generate_private_key(str Line 565  static EVP_PKEY * php_openssl_generate_private_key(str
   
 static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */  static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */
 {  {
           zval **data;
         zval *subitem, *subentries;          zval *subitem, *subentries;
         int i, j = -1, last = -1, obj_cnt = 0;          int i, j = -1, last = -1, obj_cnt = 0;
         char *sname;          char *sname;
Line 578  static void add_assoc_name_entry(zval * val, char * ke Line 583  static void add_assoc_name_entry(zval * val, char * ke
   
         for (i = 0; i < X509_NAME_entry_count(name); i++) {          for (i = 0; i < X509_NAME_entry_count(name); i++) {
                 unsigned char *to_add;                  unsigned char *to_add;
                int to_add_len;                int to_add_len = 0;
   
   
                 ne  = X509_NAME_get_entry(name, i);                  ne  = X509_NAME_get_entry(name, i);
Line 592  static void add_assoc_name_entry(zval * val, char * ke Line 597  static void add_assoc_name_entry(zval * val, char * ke
                         sname = (char *) OBJ_nid2ln(nid);                          sname = (char *) OBJ_nid2ln(nid);
                 }                  }
   
                MAKE_STD_ZVAL(subentries);                str = X509_NAME_ENTRY_get_data(ne);
                array_init(subentries);                if (ASN1_STRING_type(str) != V_ASN1_UTF8STRING) {
                         to_add_len = ASN1_STRING_to_UTF8(&to_add, str);
                 } else {
                         to_add = ASN1_STRING_data(str);
                         to_add_len = ASN1_STRING_length(str);
                 }
   
                last = -1;                if (to_add_len != -1) {
                for (;;) {                        if (zend_hash_find(Z_ARRVAL_P(subitem), sname, strlen(sname)+1, (void**)&data) == SUCCESS) {
                        j = X509_NAME_get_index_by_OBJ(name, obj, last);                                if (Z_TYPE_PP(data) == IS_ARRAY) {
                        if (j < 0) {                                        subentries = *data;
                                if (last != -1) break; 
                        } else { 
                                obj_cnt++; 
                                ne  = X509_NAME_get_entry(name, j); 
                                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); 
                                        if (to_add_len != -1) { 
                                                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);                                          add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1);
                                   } else if (Z_TYPE_PP(data) == IS_STRING) {
                                           MAKE_STD_ZVAL(subentries);
                                           array_init(subentries);
                                           add_next_index_stringl(subentries, Z_STRVAL_PP(data), Z_STRLEN_PP(data), 1);
                                           add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1);
                                           zend_hash_update(Z_ARRVAL_P(subitem), sname, strlen(sname)+1, &subentries, sizeof(zval*), NULL);
                                 }                                  }
                        }                        } else {
                        last = j; 
                } 
                i = last; 
 
                if (obj_cnt > 1) { 
                        add_assoc_zval_ex(subitem, sname, strlen(sname) + 1, subentries); 
                } else { 
                        zval_dtor(subentries); 
                        FREE_ZVAL(subentries); 
                        if (obj_cnt && str && to_add_len > -1) { 
                                 add_assoc_stringl(subitem, sname, (char *)to_add, to_add_len, 1);                                  add_assoc_stringl(subitem, sname, (char *)to_add, to_add_len, 1);
                         }                          }
                 }                  }
Line 656  static time_t asn1_time_to_time_t(ASN1_UTCTIME * times Line 649  static time_t asn1_time_to_time_t(ASN1_UTCTIME * times
         char * thestr;          char * thestr;
         long gmadjust = 0;          long gmadjust = 0;
   
        if (timestr->length < 13) {        if (ASN1_STRING_type(timestr) != V_ASN1_UTCTIME) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "extension author too lazy to parse %s correctly", timestr->data);                php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal ASN1 data type for timestamp");
                 return (time_t)-1;                  return (time_t)-1;
         }          }
   
        strbuf = estrdup((char *)timestr->data);        if (ASN1_STRING_length(timestr) != strlen(ASN1_STRING_data(timestr))) {
                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal length in timestamp");
                 return (time_t)-1;
         }
   
           if (ASN1_STRING_length(timestr) < 13) {
                   php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to parse time string %s correctly", timestr->data);
                   return (time_t)-1;
           }
   
           strbuf = estrdup((char *)ASN1_STRING_data(timestr));
   
         memset(&thetime, 0, sizeof(thetime));          memset(&thetime, 0, sizeof(thetime));
   
         /* we work backwards so that we can use atoi more easily */          /* we work backwards so that we can use atoi more easily */
   
        thestr = strbuf + timestr->length - 3;        thestr = strbuf + ASN1_STRING_length(timestr) - 3;
   
         thetime.tm_sec = atoi(thestr);          thetime.tm_sec = atoi(thestr);
         *thestr = '\0';          *thestr = '\0';
Line 855  static int php_openssl_parse_config(struct php_x509_re Line 858  static int php_openssl_parse_config(struct php_x509_re
                 req->digest = req->md_alg = EVP_get_digestbyname(req->digest_name);                  req->digest = req->md_alg = EVP_get_digestbyname(req->digest_name);
         }          }
         if (req->md_alg == NULL) {          if (req->md_alg == NULL) {
                req->md_alg = req->digest = EVP_md5();                req->md_alg = req->digest = EVP_sha1();
         }          }
   
         PHP_SSL_CONFIG_SYNTAX_CHECK(extensions_section);          PHP_SSL_CONFIG_SYNTAX_CHECK(extensions_section);
Line 1117  PHP_MINIT_FUNCTION(openssl) Line 1120  PHP_MINIT_FUNCTION(openssl)
         REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DSA", OPENSSL_KEYTYPE_DSA, CONST_CS|CONST_PERSISTENT);          REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DSA", OPENSSL_KEYTYPE_DSA, CONST_CS|CONST_PERSISTENT);
 #endif  #endif
         REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DH", OPENSSL_KEYTYPE_DH, CONST_CS|CONST_PERSISTENT);          REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DH", OPENSSL_KEYTYPE_DH, CONST_CS|CONST_PERSISTENT);
#ifdef EVP_PKEY_EC#ifdef HAVE_EVP_PKEY_EC
         REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT);          REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT);
 #endif  #endif
   
Line 1398  PHP_FUNCTION(openssl_x509_check_private_key) Line 1401  PHP_FUNCTION(openssl_x509_check_private_key)
 }  }
 /* }}} */  /* }}} */
   
   /* Special handling of subjectAltName, see CVE-2013-4073
    * Christian Heimes
    */
   
   static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
   {
           GENERAL_NAMES *names;
           const X509V3_EXT_METHOD *method = NULL;
           long i, length, num;
           const unsigned char *p;
   
           method = X509V3_EXT_get(extension);
           if (method == NULL) {
                   return -1;
           }
   
           p = extension->value->data;
           length = extension->value->length;
           if (method->it) {
                   names = (GENERAL_NAMES*)(ASN1_item_d2i(NULL, &p, length,
                                                          ASN1_ITEM_ptr(method->it)));
           } else {
                   names = (GENERAL_NAMES*)(method->d2i(NULL, &p, length));
           }
           if (names == NULL) {
                   return -1;
           }
   
           num = sk_GENERAL_NAME_num(names);
           for (i = 0; i < num; i++) {
                           GENERAL_NAME *name;
                           ASN1_STRING *as;
                           name = sk_GENERAL_NAME_value(names, i);
                           switch (name->type) {
                                   case GEN_EMAIL:
                                           BIO_puts(bio, "email:");
                                           as = name->d.rfc822Name;
                                           BIO_write(bio, ASN1_STRING_data(as),
                                                     ASN1_STRING_length(as));
                                           break;
                                   case GEN_DNS:
                                           BIO_puts(bio, "DNS:");
                                           as = name->d.dNSName;
                                           BIO_write(bio, ASN1_STRING_data(as),
                                                     ASN1_STRING_length(as));
                                           break;
                                   case GEN_URI:
                                           BIO_puts(bio, "URI:");
                                           as = name->d.uniformResourceIdentifier;
                                           BIO_write(bio, ASN1_STRING_data(as),
                                                     ASN1_STRING_length(as));
                                           break;
                                   default:
                                           /* use builtin print for GEN_OTHERNAME, GEN_X400,
                                            * GEN_EDIPARTY, GEN_DIRNAME, GEN_IPADD and GEN_RID
                                            */
                                           GENERAL_NAME_print(bio, name);
                           }
                           /* trailing ', ' except for last element */
                           if (i < (num - 1)) {
                                   BIO_puts(bio, ", ");
                           }
           }
           sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
   
           return 0;
   }
   
 /* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true])  /* {{{ proto array openssl_x509_parse(mixed x509 [, bool shortnames=true])
    Returns an array of the fields/values of the CERT */     Returns an array of the fields/values of the CERT */
 PHP_FUNCTION(openssl_x509_parse)  PHP_FUNCTION(openssl_x509_parse)
Line 1494  PHP_FUNCTION(openssl_x509_parse) Line 1565  PHP_FUNCTION(openssl_x509_parse)
   
   
         for (i = 0; i < X509_get_ext_count(cert); i++) {          for (i = 0; i < X509_get_ext_count(cert); i++) {
                   int nid;
                 extension = X509_get_ext(cert, i);                  extension = X509_get_ext(cert, i);
                if (OBJ_obj2nid(X509_EXTENSION_get_object(extension)) != NID_undef) {                nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
                 if (nid != NID_undef) {
                         extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension)));                          extname = (char *)OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(extension)));
                 } else {                  } else {
                         OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1);                          OBJ_obj2txt(buf, sizeof(buf)-1, X509_EXTENSION_get_object(extension), 1);
                         extname = buf;                          extname = buf;
                 }                  }
                 bio_out = BIO_new(BIO_s_mem());                  bio_out = BIO_new(BIO_s_mem());
                if (X509V3_EXT_print(bio_out, extension, 0, 0)) {                if (nid == NID_subject_alt_name) {
                         if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) {
                                 BIO_get_mem_ptr(bio_out, &bio_buf);
                                 add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1);
                         } else {
                                 zval_dtor(return_value);
                                 if (certresource == -1 && cert) {
                                         X509_free(cert);
                                 }
                                 BIO_free(bio_out);
                                 RETURN_FALSE;
                         }
                 }
                 else if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
                         BIO_get_mem_ptr(bio_out, &bio_buf);                          BIO_get_mem_ptr(bio_out, &bio_buf);
                         add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1);                          add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length, 1);
                 } else {                  } else {
Line 2932  static int php_openssl_is_private_key(EVP_PKEY* pkey T Line 3018  static int php_openssl_is_private_key(EVP_PKEY* pkey T
                         }                          }
                         break;                          break;
 #endif  #endif
   #ifdef HAVE_EVP_PKEY_EC
                   case EVP_PKEY_EC:
                           assert(pkey->pkey.ec != NULL);
   
                           if ( NULL == EC_KEY_get0_private_key(pkey->pkey.ec)) {
                                   return 0;
                           }
                           break;
   #endif
                 default:                  default:
                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!");                          php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!");
                         break;                          break;
Line 3332  PHP_FUNCTION(openssl_pkey_get_details) Line 3427  PHP_FUNCTION(openssl_pkey_get_details)
                         }                          }
   
                         break;                          break;
#ifdef EVP_PKEY_EC#ifdef HAVE_EVP_PKEY_EC
                 case EVP_PKEY_EC:                  case EVP_PKEY_EC:
                         ktype = OPENSSL_KEYTYPE_EC;                          ktype = OPENSSL_KEYTYPE_EC;
                         break;                          break;
Line 4226  PHP_FUNCTION(openssl_seal) Line 4321  PHP_FUNCTION(openssl_seal)
   
         if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) {          if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) {
                 RETVAL_FALSE;                  RETVAL_FALSE;
                   EVP_CIPHER_CTX_cleanup(&ctx);
                 goto clean_exit;                  goto clean_exit;
         }          }
   
Line 4236  PHP_FUNCTION(openssl_seal) Line 4332  PHP_FUNCTION(openssl_seal)
 #endif  #endif
         /* allocate one byte extra to make room for \0 */          /* allocate one byte extra to make room for \0 */
         buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(&ctx));          buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(&ctx));
           EVP_CIPHER_CTX_cleanup(&ctx);
   
         if (!EVP_SealInit(&ctx, cipher, eks, eksl, NULL, pkeys, nkeys) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {          if (!EVP_SealInit(&ctx, cipher, eks, eksl, NULL, pkeys, nkeys) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {
                 RETVAL_FALSE;                  RETVAL_FALSE;
                 efree(buf);                  efree(buf);
                   EVP_CIPHER_CTX_cleanup(&ctx);
                 goto clean_exit;                  goto clean_exit;
         }          }
   
Line 4272  PHP_FUNCTION(openssl_seal) Line 4370  PHP_FUNCTION(openssl_seal)
                 efree(buf);                  efree(buf);
         }          }
         RETVAL_LONG(len1 + len2);          RETVAL_LONG(len1 + len2);
           EVP_CIPHER_CTX_cleanup(&ctx);
   
 clean_exit:  clean_exit:
         for (i=0; i<nkeys; i++) {          for (i=0; i<nkeys; i++) {
Line 4330  PHP_FUNCTION(openssl_open) Line 4429  PHP_FUNCTION(openssl_open)
         if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) {          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)) {                  if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) {
                         efree(buf);                          efree(buf);
                        if (keyresource == -1) {                        RETVAL_FALSE;
                                EVP_PKEY_free(pkey);                } else {
                        }                        zval_dtor(opendata);
                        RETURN_FALSE;                        buf[len1 + len2] = '\0';
                         ZVAL_STRINGL(opendata, erealloc(buf, len1 + len2 + 1), len1 + len2, 0);
                         RETVAL_TRUE;
                 }                  }
         } else {          } else {
                 efree(buf);                  efree(buf);
                if (keyresource == -1) {                RETVAL_FALSE;
                        EVP_PKEY_free(pkey); 
                } 
                RETURN_FALSE; 
         }          }
         if (keyresource == -1) {          if (keyresource == -1) {
                 EVP_PKEY_free(pkey);                  EVP_PKEY_free(pkey);
         }          }
        zval_dtor(opendata);        EVP_CIPHER_CTX_cleanup(&ctx);
        buf[len1 + len2] = '\0'; 
        ZVAL_STRINGL(opendata, erealloc(buf, len1 + len2 + 1), len1 + len2, 0); 
        RETURN_TRUE; 
 }  }
 /* }}} */  /* }}} */
   
Line 4541  SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream Line 4636  SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream
   
         GET_VER_OPT_STRING("local_cert", certfile);          GET_VER_OPT_STRING("local_cert", certfile);
         if (certfile) {          if (certfile) {
                 X509 *cert = NULL;  
                 EVP_PKEY *key = NULL;  
                 SSL *tmpssl;  
                 char resolved_path_buff[MAXPATHLEN];                  char resolved_path_buff[MAXPATHLEN];
                 const char * private_key = NULL;                  const char * private_key = NULL;
   
Line 4570  SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream Line 4662  SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream
                                 }                                  }
                         }                          }
   
                        tmpssl = SSL_new(ctx);#if OPENSSL_VERSION_NUMBER < 0x10001001L
                        cert = SSL_get_certificate(tmpssl);                        do {
                                 /* Unnecessary as of OpenSSLv1.0.1 (will segfault if used with >= 10001001 ) */
                                 X509 *cert = NULL;
                                 EVP_PKEY *key = NULL;
                                 SSL *tmpssl = SSL_new(ctx);
                                 cert = SSL_get_certificate(tmpssl);
   
                        if (cert) {                                if (cert) {
                                key = X509_get_pubkey(cert);                                        key = X509_get_pubkey(cert);
                                EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));                                        EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
                                EVP_PKEY_free(key);                                        EVP_PKEY_free(key);
                        }                                }
                        SSL_free(tmpssl);                                SSL_free(tmpssl);
                        } while (0);
 #endif
                         if (!SSL_CTX_check_private_key(ctx)) {                          if (!SSL_CTX_check_private_key(ctx)) {
                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Private key does not match certificate!");                                  php_error_docref(NULL TSRMLS_CC, E_WARNING, "Private key does not match certificate!");
                         }                          }
Line 4916  PHP_FUNCTION(openssl_cipher_iv_length) Line 5014  PHP_FUNCTION(openssl_cipher_iv_length)
   
   
 /* {{{ proto string openssl_dh_compute_key(string pub_key, resource dh_key)  /* {{{ proto string openssl_dh_compute_key(string pub_key, resource dh_key)
   Computes shared sicret for public value of remote DH key and local DH key */   Computes shared secret for public value of remote DH key and local DH key */
 PHP_FUNCTION(openssl_dh_compute_key)  PHP_FUNCTION(openssl_dh_compute_key)
 {  {
         zval *key;          zval *key;

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.5


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>