Skip to content

Commit 2bdf2f9

Browse files
committed
Fix GH-16433: Large values for openssl_csr_sign() $days overflow
The `offset_sec` parameter of `X509_gmtime_adj()` expects a `long`, but the `$days` parameter of `openssl_csr_sign()` a `zend_long`. We must avoid signed integer overflow (UB), but also must not silently truncate. Thus we check the given `$days` for the permissible range, and bail out otherwise. Closes GH-16437.
1 parent ab595c0 commit 2bdf2f9

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ PHP NEWS
4747
- OpenSSL:
4848
. Fixed bug GH-16357 (openssl may modify member types of certificate arrays).
4949
(cmb)
50+
. Fixed bug GH-16433 (Large values for openssl_csr_sign() $days overflow).
51+
(cmb)
5052

5153
- PHPDBG:
5254
. Fixed bug GH-16174 (Empty string is an invalid expression for ev). (cmb)

ext/openssl/openssl.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,11 @@ PHP_FUNCTION(openssl_csr_sign)
32003200
goto cleanup;
32013201
}
32023202

3203+
if (num_days < 0 || num_days > LONG_MAX / 86400) {
3204+
php_error_docref(NULL, E_WARNING, "Days must be between 0 and %ld", LONG_MAX / 86400);
3205+
goto cleanup;
3206+
}
3207+
32033208
if (PHP_SSL_REQ_PARSE(&req, args) == FAILURE) {
32043209
goto cleanup;
32053210
}
@@ -3251,7 +3256,7 @@ PHP_FUNCTION(openssl_csr_sign)
32513256
goto cleanup;
32523257
}
32533258
X509_gmtime_adj(X509_getm_notBefore(new_cert), 0);
3254-
X509_gmtime_adj(X509_getm_notAfter(new_cert), 60*60*24*(long)num_days);
3259+
X509_gmtime_adj(X509_getm_notAfter(new_cert), 60*60*24*num_days);
32553260
i = X509_set_pubkey(new_cert, key);
32563261
if (!i) {
32573262
php_openssl_store_errors();

ext/openssl/tests/gh16433.phpt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
GH-16433 (Large values for openssl_csr_sign() $days overflow)
3+
--EXTENSIONS--
4+
openssl
5+
--FILE--
6+
<?php
7+
$privkey = openssl_pkey_new();
8+
$csr = openssl_csr_new([], $privkey);
9+
var_dump(openssl_csr_sign($csr, null, $privkey, PHP_INT_MAX));
10+
var_dump(openssl_csr_sign($csr, null, $privkey, -1));
11+
?>
12+
--EXPECTF--
13+
Warning: openssl_csr_sign(): Days must be between 0 and %d in %s on line %d
14+
bool(false)
15+
16+
Warning: openssl_csr_sign(): Days must be between 0 and %d in %s on line %d
17+
bool(false)

0 commit comments

Comments
 (0)