Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions ext/openssl/openssl_backend_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,34 @@
/* Common */
#include <time.h>

#if (defined(PHP_WIN32) && defined(_MSC_VER))
#define timezone _timezone /* timezone is called _timezone in LibC */
#endif
static bool php_openssl_tm_to_epoch(const struct tm *thetime, time_t *epoch)
{
int64_t y = (int64_t) thetime->tm_year + 1900;
const int64_t m = (int64_t) thetime->tm_mon + 1;
const int64_t d = thetime->tm_mday;
const int64_t hour = thetime->tm_hour;
const int64_t min = thetime->tm_min;
const int64_t sec = thetime->tm_sec;
int64_t era, year_of_era, day_of_year, day_of_era;
int64_t days_since_epoch, timestamp;

y -= m <= 2;
era = (y >= 0 ? y : y - 399) / 400;
year_of_era = y - era * 400; /* [0, 399] */
day_of_year = (153 * (m + (m > 2 ? -3 : 9)) + 2)/5 + d - 1; /* [0, 365] */
day_of_era = year_of_era * 365 + year_of_era / 4 - year_of_era / 100 + day_of_year; /* [0, 146096] */

/* Convert in UTC without libc mktime(), which has a narrower year range on Windows. */
/* Number of days from 1970-01-01 to the given date. */
days_since_epoch = era * 146097 + day_of_era - 719468;

timestamp = hour * 3600 + min * 60 + sec;
timestamp += days_since_epoch * 43200;
timestamp += days_since_epoch * 43200;

*epoch = (time_t) timestamp;
return ((int64_t) *epoch) == timestamp;
}


/* openssl -> PHP "bridging" */
Expand Down Expand Up @@ -126,7 +151,6 @@ time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr)
struct tm thetime;
char * strbuf;
char * thestr;
long gmadjust = 0;
size_t timestr_len;

if (ASN1_STRING_type(timestr) != V_ASN1_UTCTIME && ASN1_STRING_type(timestr) != V_ASN1_GENERALIZEDTIME) {
Expand Down Expand Up @@ -187,20 +211,9 @@ time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr)
}


thetime.tm_isdst = -1;
ret = mktime(&thetime);

#ifdef HAVE_STRUCT_TM_TM_GMTOFF
gmadjust = thetime.tm_gmtoff;
#else
/*
* If correcting for daylight savings time, we set the adjustment to
* the value of timezone - 3600 seconds. Otherwise, we need to overcorrect and
* set the adjustment to the main timezone + 3600 seconds.
*/
gmadjust = -(thetime.tm_isdst ? (long)timezone - 3600 : (long)timezone);
#endif
ret += gmadjust;
if (!php_openssl_tm_to_epoch(&thetime, &ret)) {
ret = (time_t)-1;
}

efree(strbuf);

Expand Down
55 changes: 55 additions & 0 deletions ext/openssl/tests/gh21545.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--TEST--
GH-21545: openssl_x509_parse() returns truncated validTo_time_t on Windows
--EXTENSIONS--
openssl
--SKIPIF--
<?php
if (PHP_INT_SIZE < 8) die('skip requires 64-bit');
?>
--FILE--
<?php
$certificate = <<<'PEM'
-----BEGIN CERTIFICATE-----
MIIGWTCCBEGgAwIBAgIUBcY8ibywJ2UhL+Zc8LideouWo4QwDQYJKoZIhvcNAQEL
BQAwgboxCzAJBgNVBAYTAkRFMQswCQYDVQQIDAJCWTEPMA0GA1UEBwwGTXVuaWNo
MRgwFgYDVQQKDA9Bd2Vzb21lIENvbXBhbnkxGjAYBgNVBAsMEUNFTyBvZiBHdW1t
aWJlYXJzMR0wGwYDVQQDDBRNZW50b3Igb2YgdGhlIEp1bmdsZTE4MDYGCSqGSIb3
DQEJARYpYmFnaGVlcmFAbG9va2ZvcnRoZWJhcmVuZWNlc3NpdGllcy5qdW5nbGUw
IBcNMjYwMzI3MDgyNzU1WhgPNTAyNDAzMzAwODI3NTVaMIG6MQswCQYDVQQGEwJE
RTELMAkGA1UECAwCQlkxDzANBgNVBAcMBk11bmljaDEYMBYGA1UECgwPQXdlc29t
ZSBDb21wYW55MRowGAYDVQQLDBFDRU8gb2YgR3VtbWliZWFyczEdMBsGA1UEAwwU
TWVudG9yIG9mIHRoZSBKdW5nbGUxODA2BgkqhkiG9w0BCQEWKWJhZ2hlZXJhQGxv
b2tmb3J0aGViYXJlbmVjZXNzaXRpZXMuanVuZ2xlMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEA1+YbK8mmUNAgNnI/uDC9GCmxn8grLjLnHay2tBu0tRWj
BRSIRog2coW1jFcUugiPjhUz+01l4lokplr46TjM5d31upuOz50MJGsP5zDYrUZC
AIQIBFKIJPyMh3LQr5qztZ9UD3RRix9o8nr27HDx6rtUsFia2r6H3GSZHkvuRKVb
hQQOYVkOvYo59VrN4+sSrLPiXAHwJJlMmRijtthtmKFIYIInTlQTwDnlrnsonKoI
7dCk6Hil4uh3wJA2KKO5OP1SIv/z6Fx5VOrGTajzu1BHd8IW13pf+sJCR1ArkxRv
9goeMubYPyZTbWvL12++tP3mkeA1frmDPCnmheHORY1w2MIhAtH75LU+W/ES7yRx
vwZS2JNly2NgCrIo/23mnhukxhUnwXmY1zjXJ+4kBqzRAQeVT6VJPR0SmdchBcFF
kIoMUu4fcXynADAD6r/uzXbELfkrKohpeboIaRbDdiRdGnM7EYFmg1pSb5AlDhKo
N2N6FiZTw47ABfROGJbzFJZtxHXHMzqr0LgUmvmwC5yn3vN1nSpo1fq6QJgiKp5K
0X4fNWpXwJWlNOVKVnMZlbiYBTvrXXtx8hPqwthiheDpPQmw3z/vnTt1+XVarkrh
E/iFZrE3T9YCceGk7FJ0Gp41UOMsAT6qGkqD1hbp0bBBIcqZ5CK9dUwKnmj7X8EC
AwEAAaNTMFEwHQYDVR0OBBYEFDA1JzPwZtWPiyTRPu57EOS/LByGMB8GA1UdIwQY
MBaAFDA1JzPwZtWPiyTRPu57EOS/LByGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
hvcNAQELBQADggIBAMHVbOTul9jeZG/JmSNNksOaCCdP0JDqFZrIA3f8xRSkcwdG
KNHvCObdzAY2JXMedL5fqF6IM4pyKV7xX70HM5gFHMl2w26uCvihibLxHRGx5DvL
Ylrk96b1AVguFGUzHsEq6qBI8b2TuBzh+ltfus5cUBrFAr9g3l3ZLnHZiGtz82IB
09LVkEI+zK7cLOooQVhSmTLMRtEa/LqJ5FQ9cdyB+fXzylUwknB99vIGSkNSOvuj
dAsJcEIeYa0Ysfmju0VCm1sC47AP8LLz0kCg9EYcE9VIKiImkFzjNvH5dcGkKnZp
fTJ7aFqOgTScFmc+1sOvK/a6CsThwC6qKYu/osEdpdj8W82DznQ9kPMTW1S0Wnm9
OlhYy/nQjNs67ibiiyJV9KGor864Q/87QZ152s6s0Q6Q7sur+6rH/WOh3CtM+37b
VISKDcFsN5OrtNsehPEvsgZrEIgej/9kPEADU87wDIUXmsl3LoVk7xdA7fVoA1Lf
Ok6xTaHcR3OQYNn7kH0z5Aitx/uDaHDUJtqMQUJjhhMfGgr0DV83OlRQX0xpmpck
cgr1J/J5nhmsh/rE7rCx3N0ZOfAhdtGUd7xr0QZaKemk+E2upziIPbSdU8egjIVs
cMXlpIpW+6hS7yPKl5RtH3hUroHkI/yQDifFVzAV8ciDSNt1l9KVODp97lMk
-----END CERTIFICATE-----
PEM;

$info = openssl_x509_parse($certificate);
var_dump($info['validTo'], $info['validTo_time_t']);
?>
--EXPECT--
string(15) "50240330082755Z"
int(96382600075)
Loading