On Thu, May 18, 2017 at 7:31 AM, Kyle J. McKay <[email protected]> wrote:
> RFC 5280 section 4.1.2.5 states: > > To indicate that a certificate has no well-defined expiration date, > the notAfter SHOULD be assigned the GeneralizedTime value of > 99991231235959Z. > > True enough. > Unfortunately, if sizeof(time_t) == 4, 9999-12-31T23:59:59Z cannot be > represented as a time_t value causing valid certificates to be rejected > just because the notAfter value is after 2038-01-19T03:14:07Z. > Correct So, I'll ask - what is the platform you are using that needs this? OpenBSD does not, nor do most modern unix systems - So what platform are we doing this for? I'm not asking it to be nasty, but to put it in a slightly different context "OMG, windows 98 does not support this, but if you add this code I can support windows 98". You and I both know what your answer would probably be for the person with Windows 98, which is "Here's a nickel kid, get a modern operating system". We ripped out support for a lot of moribund platforms for a reason. What platform are you using with 32 bit time where this is an issue? I'm not saying no, I'm saying "convince me this matters for anything relevant please", and I am open to being convinced. Fix this problem by disabling the restriction in the X509_cmp_time function > and "wrap" far in the future notAfter values to 2038-01-19T03:14:07Z in the > tls_get_peer_cert_times function. > > With both of these changes certificates with "no well-defined expiration > date" as specified by RFC 5280 are again accepted on platforms where the > sizeof(time_t) == 4. > > In general, there's no reason that a notAfter value should not be wrapped > to 2038-01-19T03:14:07Z on a system with a 32-bit time_t. The system > itself > can never have a time after 2038-01-19T03:14:07Z because of the size of the > time_t type and so wrapping a notAfter date that is after > 2038-01-19T03:14:07Z > to 2038-01-19T03:14:07Z can never result in any additional certificates > being > accepted on such a system. > > Signed-off-by: Kyle J. McKay <[email protected]> > --- > > For those using the libressl-2.5.4.tar.gz distribution, an equivalent > patch that updates the tarball files instead can be found here: > > https://gist.github.com/7d4d59bbae9e4d18444b86aa79d6f350 > > Without this patch (or an equivalent), libressl-portable is not a viable > alternative to OpenSSL on systems with a 32-bit time_t. > > It rejects valid TLS connections to any site that contains a notAfter date > after 2038-01-19T03:14:07Z in any certificate in the chain. > > Besides the special case date mentioned above, there are many root > certificates > already in use today that have notAfter dates beyond 2038-01-19. > > These patches have been tested with libressl-portable 2.5.4 on a system > with > a 32-bit time_t. With both of these patches the "nc -c" command > successfully > connects to sites with certificates that include notAfter dates after > 2038-01-19. > > If either patch is omitted, "nc -c" fails to connect. > > src/lib/libcrypto/x509/x509_vfy.c | 3 ++- > src/lib/libtls/tls_conninfo.c | 8 ++++++-- > 2 files changed, 8 insertions(+), 3 deletions(-) > > diff --git a/src/lib/libcrypto/x509/x509_vfy.c > b/src/lib/libcrypto/x509/x509_vfy.c > index d8c09a12..c59bd258 100644 > --- a/src/lib/libcrypto/x509/x509_vfy.c > +++ b/src/lib/libcrypto/x509/x509_vfy.c > @@ -1882,7 +1882,8 @@ X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) > * a time_t. A time_t must be sane if you care about times after > * Jan 19 2038. > */ > - if ((time1 = timegm(&tm1)) == -1) > + if (((time1 = timegm(&tm1)) == -1) && > + ((sizeof(time_t) != 4) || tm1.tm_year < 138)) > goto out; > > if (gmtime_r(&time2, &tm2) == NULL) > diff --git a/src/lib/libtls/tls_conninfo.c b/src/lib/libtls/tls_conninfo.c > index 5cdd0f77..a59b4ba2 100644 > --- a/src/lib/libtls/tls_conninfo.c > +++ b/src/lib/libtls/tls_conninfo.c > @@ -142,8 +142,12 @@ tls_get_peer_cert_times(struct tls *ctx, time_t > *notbefore, > goto err; > if ((*notbefore = timegm(&before_tm)) == -1) > goto err; > - if ((*notafter = timegm(&after_tm)) == -1) > - goto err; > + if ((*notafter = timegm(&after_tm)) == -1) { > + if (sizeof(time_t) == 4 && after_tm.tm_year >= 138) > + *notafter = 2147483647; > + else > + goto err; > + } > > return (0); > > --- > >
