Commit: b34ce97417ffe7269a340982fe8b0f86983e12e7
Author: Jakub Zelenka <bu...@php.net> Sun, 1 Dec 2013 19:53:45 +0000
Parents: 215811e3fdb7b4f2786576851c8687c6249c4725
Branches: str_size_and_int64
Link:
http://git.php.net/?p=php-src.git;a=commitdiff;h=b34ce97417ffe7269a340982fe8b0f86983e12e7
Log:
add some overflow checks and use correct msg formatting in openssl
Changed paths:
M ext/openssl/openssl.c
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index fb11458..2fe8341 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -812,7 +812,7 @@ static int add_oid_section(struct php_x509_request * req
TSRMLS_DC) /* {{{ */
else \
varname = defval
-static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo);
+static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(php_int_t algo);
int openssl_spki_cleanup(const char *src, char *dest);
@@ -1302,6 +1302,9 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int
makeresource, php_int_
} else {
BIO *in;
+ if (Z_STRSIZE_PP(val) > INT_MAX) {
+ return NULL;
+ }
in = BIO_new_mem_buf(Z_STRVAL_PP(val), (int)Z_STRSIZE_PP(val));
if (in == NULL) {
return NULL;
@@ -1417,6 +1420,11 @@ PHP_FUNCTION(openssl_spki_new)
}
if (challenge) {
+ if (challenge_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Challenge
is too long; it needs to be at most %d bytes, not " ZEND_UINT_FMT,
+ INT_MAX, challenge_len);
+ goto cleanup;
+ }
ASN1_STRING_set(spki->spkac->challenge, challenge,
(int)challenge_len);
}
@@ -1468,8 +1476,8 @@ cleanup:
Verifies spki returns boolean */
PHP_FUNCTION(openssl_spki_verify)
{
- int i = 0;
zend_str_size_int spkstr_len;
+ int i = 0;
char *spkstr = NULL, * spkstr_cleaned = NULL;
EVP_PKEY *pkey = NULL;
@@ -2289,7 +2297,7 @@ static STACK_OF(X509) * php_array_to_X509_sk(zval **
zcerts TSRMLS_DC) /* {{{ */
HashPosition hpos;
zval ** zcertval;
STACK_OF(X509) * sk = NULL;
- X509 * cert;
+ X509 * cert;
php_int_t certresource;
sk = sk_X509_new_null();
@@ -2790,6 +2798,8 @@ static X509_REQ * php_openssl_csr_from_zval(zval ** val,
int makeresource, php_i
return NULL;
}
in = BIO_new_file(filename, "r");
+ } else if (Z_STRSIZE_PP(val) > INT_MAX) {
+ return NULL;
} else {
in = BIO_new_mem_buf(Z_STRVAL_PP(val), (int)Z_STRSIZE_PP(val));
}
@@ -2964,6 +2974,10 @@ PHP_FUNCTION(openssl_csr_sign)
if (!X509_set_version(new_cert, 2))
goto cleanup;
+ if (serial > LONG_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The serial number
is too high");
+ goto cleanup;
+ }
ASN1_INTEGER_set(X509_get_serialNumber(new_cert), (long)serial);
X509_set_subject_name(new_cert, X509_REQ_get_subject_name(csr));
@@ -2975,6 +2989,11 @@ PHP_FUNCTION(openssl_csr_sign)
goto cleanup;
}
X509_gmtime_adj(X509_get_notBefore(new_cert), 0);
+ if (num_days > (LONG_MAX / (60*60*24 + 1))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The number of days
is too high; expected at most %ld days, not " ZEND_INT_FMT,
+ LONG_MAX / (60*60*24 + 1), num_days);
+ goto cleanup;
+ }
X509_gmtime_adj(X509_get_notAfter(new_cert),
(long)60*60*24*(long)num_days);
i = X509_set_pubkey(new_cert, key);
if (!i) {
@@ -3287,6 +3306,8 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val,
int public_key, char *
BIO* in;
if (filename) {
in = BIO_new_file(filename, "r");
+ } else if (Z_STRSIZE_PP(val) > INT_MAX) {
+ TMP_CLEAN;
} else {
in = BIO_new_mem_buf(Z_STRVAL_PP(val),
(int)Z_STRSIZE_PP(val));
}
@@ -3305,6 +3326,8 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val,
int public_key, char *
TMP_CLEAN;
}
in = BIO_new_file(filename, "r");
+ } else if (Z_STRSIZE_PP(val) > INT_MAX) {
+ TMP_CLEAN;
} else {
in = BIO_new_mem_buf(Z_STRVAL_PP(val),
(int)Z_STRSIZE_PP(val));
}
@@ -3343,10 +3366,15 @@ static EVP_PKEY *
php_openssl_generate_private_key(struct php_x509_request * req
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 %ld",
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key length
is too short; it needs to be at least %d bits, not " ZEND_INT_FMT,
MIN_KEY_LENGTH, req->priv_key_bits);
return NULL;
}
+ if (req->priv_key_bits > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "private key length
is too long; it needs to be at most %d bits, not " ZEND_INT_FMT,
+ INT_MAX, req->priv_key_bits);
+ return NULL;
+ }
randfile = CONF_get_string(req->req_config, req->section_name,
"RANDFILE");
php_openssl_load_rand_file(randfile, &egdsocket, &seeded TSRMLS_CC);
@@ -3354,14 +3382,14 @@ static EVP_PKEY *
php_openssl_generate_private_key(struct php_x509_request * req
if ((req->priv_key = EVP_PKEY_new()) != NULL) {
switch(req->priv_key_type) {
case OPENSSL_KEYTYPE_RSA:
- if (EVP_PKEY_assign_RSA(req->priv_key,
RSA_generate_key(req->priv_key_bits, 0x10001, NULL, NULL))) {
+ if (EVP_PKEY_assign_RSA(req->priv_key,
RSA_generate_key((int)req->priv_key_bits, 0x10001, NULL, NULL))) {
return_val = req->priv_key;
}
break;
#if !defined(NO_DSA) && defined(HAVE_DSA_DEFAULT_METHOD)
case OPENSSL_KEYTYPE_DSA:
{
- DSA *dsapar =
DSA_generate_parameters(req->priv_key_bits, NULL, 0, NULL, NULL, NULL, NULL);
+ DSA *dsapar =
DSA_generate_parameters((int)req->priv_key_bits, NULL, 0, NULL, NULL, NULL,
NULL);
if (dsapar) {
DSA_set_method(dsapar,
DSA_get_default_method());
if (DSA_generate_key(dsapar)) {
@@ -3378,7 +3406,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct
php_x509_request * req
#if !defined(NO_DH)
case OPENSSL_KEYTYPE_DH:
{
- DH *dhpar =
DH_generate_parameters(req->priv_key_bits, 2, NULL, NULL);
+ DH *dhpar =
DH_generate_parameters((int)req->priv_key_bits, 2, NULL, NULL);
int codes = 0;
if (dhpar) {
@@ -3603,6 +3631,12 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
}
RETVAL_FALSE;
+ if (passphrase_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The passphrase is
too long; expected at most %d characters, not " ZEND_UINT_FMT,
+ INT_MAX, passphrase_len);
+ return;
+ }
+
key = php_openssl_evp_from_zval(zpkey, 0, passphrase, 0, &key_resource
TSRMLS_CC);
if (key == NULL) {
@@ -3663,6 +3697,12 @@ PHP_FUNCTION(openssl_pkey_export)
}
RETVAL_FALSE;
+ if (passphrase_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The passphrase is
too long; expected at most %d characters, not " ZEND_UINT_FMT,
+ INT_MAX, passphrase_len);
+ return;
+ }
+
key = php_openssl_evp_from_zval(zpkey, 0, passphrase, 0, &key_resource
TSRMLS_CC);
if (key == NULL) {
@@ -3894,9 +3934,24 @@ PHP_FUNCTION(openssl_pbkdf2)
return;
}
+ if (password_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Password is too
long; it needs to be at most %d bytes, not " ZEND_UINT_FMT,
+ INT_MAX, password_len);
+ RETURN_FALSE;
+ }
+ if (salt_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Salt is too long;
it needs to be at most %d bytes, not " ZEND_UINT_FMT,
+ INT_MAX, salt_len);
+ RETURN_FALSE;
+ }
if (key_length <= 0) {
RETURN_FALSE;
}
+ if (key_length > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key length is too
high; it needs to be at most %d bytes, not " ZEND_INT_FMT,
+ INT_MAX, key_length);
+ RETURN_FALSE;
+ }
if (method_len) {
digest = EVP_get_digestbyname(method);
@@ -4245,7 +4300,7 @@ PHP_FUNCTION(openssl_pkcs7_sign)
goto clean_exit;
}
- p7 = PKCS7_sign(cert, privkey, others, infile, (int) flags);
+ p7 = PKCS7_sign(cert, privkey, others, infile, (int)flags);
if (p7 == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "error creating
PKCS7 structure!");
goto clean_exit;
@@ -4271,7 +4326,7 @@ PHP_FUNCTION(openssl_pkcs7_sign)
}
}
/* write the signed data */
- SMIME_write_PKCS7(outfile, p7, infile, (int) flags);
+ SMIME_write_PKCS7(outfile, p7, infile, (int)flags);
RETVAL_TRUE;
@@ -4382,6 +4437,12 @@ PHP_FUNCTION(openssl_private_encrypt)
}
RETVAL_FALSE;
+ if (data_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Data is too long;
it needs to be at most %d bytes, not " ZEND_UINT_FMT,
+ INT_MAX, data_len);
+ return;
+ }
+
pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource TSRMLS_CC);
if (pkey == NULL) {
@@ -4437,6 +4498,12 @@ PHP_FUNCTION(openssl_private_decrypt)
}
RETVAL_FALSE;
+ if (data_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Data is too long;
it needs to be at most %d bytes, not " ZEND_UINT_FMT,
+ INT_MAX, data_len);
+ return;
+ }
+
pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource TSRMLS_CC);
if (pkey == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "key parameter is
not a valid private key");
@@ -4497,6 +4564,12 @@ PHP_FUNCTION(openssl_public_encrypt)
return;
RETVAL_FALSE;
+
+ if (data_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Data is too long;
it needs to be at most %d bytes, not " ZEND_UINT_FMT,
+ INT_MAX, data_len);
+ return;
+ }
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource
TSRMLS_CC);
if (pkey == NULL) {
@@ -4552,6 +4625,12 @@ PHP_FUNCTION(openssl_public_decrypt)
return;
}
RETVAL_FALSE;
+
+ if (data_len > INT_MAX) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Data is too long;
it needs to be at most %d bytes, not " ZEND_UINT_FMT,
+ INT_MAX, data_len);
+ return;
+ }
pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource
TSRMLS_CC);
if (pkey == NULL) {
@@ -4636,6 +4715,7 @@ PHP_FUNCTION(openssl_sign)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "SzZ|z", &data,
&data_len, &signature, &key, &method) == FAILURE) {
return;
}
+
pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource TSRMLS_CC);
if (pkey == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied key param
cannot be coerced into a private key");
@@ -4777,7 +4857,7 @@ PHP_FUNCTION(openssl_seal)
eksl = safe_emalloc(nkeys, sizeof(*eksl), 0);
eks = safe_emalloc(nkeys, sizeof(*eks), 0);
memset(eks, 0, sizeof(*eks) * nkeys);
- key_resources = safe_emalloc(nkeys, sizeof(long), 0);
+ key_resources = safe_emalloc(nkeys, sizeof(php_int_t), 0);
memset(key_resources, 0, sizeof(*key_resources) * nkeys);
/* get the public keys we are using to seal this data */
@@ -4971,7 +5051,8 @@ static int verify_callback(int preverify_ok,
X509_STORE_CTX *ctx) /* {{{ */
static zend_bool matches_wildcard_name(const char *subjectname, const char
*certname)
{
char *wildcard;
- int prefix_len, suffix_len, subject_len;
+ ptrdiff_t prefix_len;
+ size_t suffix_len, subject_len;
if (strcasecmp(subjectname, certname) == 0) {
return 1;
@@ -5119,13 +5200,13 @@ static int passwd_callback(char *buf, int num, int
verify, void *data) /* {{{ */
GET_VER_OPT_STRING("passphrase", passphrase);
- if (passphrase) {
+ if (passphrase) {
if (Z_STRSIZE_PP(val) < num - 1) {
memcpy(buf, Z_STRVAL_PP(val), Z_STRSIZE_PP(val)+1);
return (int) Z_STRSIZE_PP(val);
- }
- }
- return 0;
+ }
+ }
+ return 0;
}
/* }}} */
@@ -5352,14 +5433,14 @@ static zend_bool php_openssl_validate_iv(char **piv,
zend_str_size_int *piv_len,
}
if (*piv_len < iv_required_len) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "IV passed is only
%lu bytes long, cipher expects an IV of precisely %lu bytes, padding with \\0",
*piv_len, iv_required_len);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "IV passed is only
"ZEND_UINT_FMT" bytes long, cipher expects an IV of precisely "ZEND_UINT_FMT"
bytes, padding with \\0", *piv_len, iv_required_len);
memcpy(iv_new, *piv, *piv_len);
*piv_len = iv_required_len;
*piv = iv_new;
return 1;
}
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "IV passed is %lu bytes
long which is longer than the %lu expected by selected cipher, truncating",
*piv_len, iv_required_len);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "IV passed is
"ZEND_UINT_FMT" bytes long which is longer than the "ZEND_UINT_FMT" expected by
selected cipher, truncating", *piv_len, iv_required_len);
memcpy(iv_new, *piv, iv_required_len);
*piv_len = iv_required_len;
*piv = iv_new;
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php