From c992fba3db033361472a235146e93729fd6f7f99 Mon Sep 17 00:00:00 2001 From: miod Date: Thu, 15 May 2014 21:06:10 +0000 Subject: [PATCH] Replace ASN1_GENERALIZEDTIME_adj(), ASN1_UTCTIME_adj() and ASN1_TIME_to_generalizedtime() with wrappers around their former implementations, making sure memory allocated is freed in all failure cases. help and ok from beck@ and Brendan MacDonell. --- lib/libcrypto/asn1/a_gentm.c | 32 ++++++++++++++++++------ lib/libcrypto/asn1/a_time.c | 37 ++++++++++++++++++++-------- lib/libcrypto/asn1/a_utctm.c | 29 ++++++++++++++++------ lib/libssl/src/crypto/asn1/a_gentm.c | 32 ++++++++++++++++++------ lib/libssl/src/crypto/asn1/a_time.c | 37 ++++++++++++++++++++-------- lib/libssl/src/crypto/asn1/a_utctm.c | 29 ++++++++++++++++------ 6 files changed, 146 insertions(+), 50 deletions(-) diff --git a/lib/libcrypto/asn1/a_gentm.c b/lib/libcrypto/asn1/a_gentm.c index f331bff3202..7f8bc2fef72 100644 --- a/lib/libcrypto/asn1/a_gentm.c +++ b/lib/libcrypto/asn1/a_gentm.c @@ -208,20 +208,15 @@ ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t) return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); } -ASN1_GENERALIZEDTIME * -ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, - long offset_sec) +static ASN1_GENERALIZEDTIME * +ASN1_GENERALIZEDTIME_adj_internal(ASN1_GENERALIZEDTIME *s, time_t t, + int offset_day, long offset_sec) { char *p; struct tm *ts; struct tm data; size_t len = 20; - if (s == NULL) - s = M_ASN1_GENERALIZEDTIME_new(); - if (s == NULL) - return (NULL); - ts = gmtime_r(&t, &data); if (ts == NULL) return (NULL); @@ -250,3 +245,24 @@ ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, s->type = V_ASN1_GENERALIZEDTIME; return (s); } + +ASN1_GENERALIZEDTIME * +ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, + long offset_sec) +{ + ASN1_GENERALIZEDTIME *tmp = NULL, *ret; + + if (s == NULL) { + tmp = M_ASN1_GENERALIZEDTIME_new(); + if (tmp == NULL) + return NULL; + s = tmp; + } + + ret = ASN1_GENERALIZEDTIME_adj_internal(s, t, offset_day, offset_sec); + if (ret == NULL && tmp != NULL) + M_ASN1_GENERALIZEDTIME_free(tmp); + + return ret; + +} diff --git a/lib/libcrypto/asn1/a_time.c b/lib/libcrypto/asn1/a_time.c index 8db21636228..574c99bbf8e 100644 --- a/lib/libcrypto/asn1/a_time.c +++ b/lib/libcrypto/asn1/a_time.c @@ -120,8 +120,8 @@ ASN1_TIME_check(ASN1_TIME *t) } /* Convert an ASN1_TIME structure to GeneralizedTime */ -ASN1_GENERALIZEDTIME * -ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) +static ASN1_GENERALIZEDTIME * +ASN1_TIME_to_generalizedtime_internal(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) { ASN1_GENERALIZEDTIME *ret; char *str; @@ -131,13 +131,7 @@ ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) if (!ASN1_TIME_check(t)) return NULL; - if (!out || !*out) { - if (!(ret = ASN1_GENERALIZEDTIME_new ())) - return NULL; - if (out) - *out = ret; - } else - ret = *out; + ret = *out; /* If already GeneralizedTime just copy across */ if (t->type == V_ASN1_GENERALIZEDTIME) { @@ -152,15 +146,38 @@ ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) /* ASN1_STRING_set() allocated 'len + 1' bytes. */ newlen = t->length + 2 + 1; str = (char *)ret->data; + /* XXX ASN1_TIME is not Y2050 compatible */ i = snprintf(str, newlen, "%s%s", (t->data[0] >= '5') ? "19" : "20", (char *) t->data); if (i == -1 || i >= newlen) { - ASN1_STRING_free(ret); + M_ASN1_GENERALIZEDTIME_free(ret); + *out = NULL; return NULL; } return ret; } +ASN1_GENERALIZEDTIME * +ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) +{ + ASN1_GENERALIZEDTIME *tmp = NULL, *ret; + + if (!out || !*out) { + if (!(tmp = ASN1_GENERALIZEDTIME_new())) + return NULL; + if (out != NULL) + *out = tmp; + else + out = &tmp; + } + + ret = ASN1_TIME_to_generalizedtime_internal(t, out); + if (ret == NULL && tmp != NULL) + ASN1_GENERALIZEDTIME_free(tmp); + + return ret; +} + int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) { diff --git a/lib/libcrypto/asn1/a_utctm.c b/lib/libcrypto/asn1/a_utctm.c index e4db9f8a994..35f2b7fd668 100644 --- a/lib/libcrypto/asn1/a_utctm.c +++ b/lib/libcrypto/asn1/a_utctm.c @@ -149,19 +149,15 @@ ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) return ASN1_UTCTIME_adj(s, t, 0, 0); } -ASN1_UTCTIME * -ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) +static ASN1_UTCTIME * +ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, + long offset_sec) { char *p; struct tm *ts; struct tm data; size_t len = 20; - if (s == NULL) - s = M_ASN1_UTCTIME_new(); - if (s == NULL) - return (NULL); - ts = gmtime_r(&t, &data); if (ts == NULL) return (NULL); @@ -193,6 +189,25 @@ ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) return (s); } +ASN1_UTCTIME * +ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) +{ + ASN1_UTCTIME *tmp = NULL, *ret; + + if (s == NULL) { + tmp = M_ASN1_UTCTIME_new(); + if (tmp == NULL) + return NULL; + s = tmp; + } + + ret = ASN1_UTCTIME_adj_internal(s, t, offset_day, offset_sec); + if (ret == NULL && tmp != NULL) + M_ASN1_UTCTIME_free(tmp); + + return ret; +} + int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) { diff --git a/lib/libssl/src/crypto/asn1/a_gentm.c b/lib/libssl/src/crypto/asn1/a_gentm.c index f331bff3202..7f8bc2fef72 100644 --- a/lib/libssl/src/crypto/asn1/a_gentm.c +++ b/lib/libssl/src/crypto/asn1/a_gentm.c @@ -208,20 +208,15 @@ ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t) return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); } -ASN1_GENERALIZEDTIME * -ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, - long offset_sec) +static ASN1_GENERALIZEDTIME * +ASN1_GENERALIZEDTIME_adj_internal(ASN1_GENERALIZEDTIME *s, time_t t, + int offset_day, long offset_sec) { char *p; struct tm *ts; struct tm data; size_t len = 20; - if (s == NULL) - s = M_ASN1_GENERALIZEDTIME_new(); - if (s == NULL) - return (NULL); - ts = gmtime_r(&t, &data); if (ts == NULL) return (NULL); @@ -250,3 +245,24 @@ ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, s->type = V_ASN1_GENERALIZEDTIME; return (s); } + +ASN1_GENERALIZEDTIME * +ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, + long offset_sec) +{ + ASN1_GENERALIZEDTIME *tmp = NULL, *ret; + + if (s == NULL) { + tmp = M_ASN1_GENERALIZEDTIME_new(); + if (tmp == NULL) + return NULL; + s = tmp; + } + + ret = ASN1_GENERALIZEDTIME_adj_internal(s, t, offset_day, offset_sec); + if (ret == NULL && tmp != NULL) + M_ASN1_GENERALIZEDTIME_free(tmp); + + return ret; + +} diff --git a/lib/libssl/src/crypto/asn1/a_time.c b/lib/libssl/src/crypto/asn1/a_time.c index 8db21636228..574c99bbf8e 100644 --- a/lib/libssl/src/crypto/asn1/a_time.c +++ b/lib/libssl/src/crypto/asn1/a_time.c @@ -120,8 +120,8 @@ ASN1_TIME_check(ASN1_TIME *t) } /* Convert an ASN1_TIME structure to GeneralizedTime */ -ASN1_GENERALIZEDTIME * -ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) +static ASN1_GENERALIZEDTIME * +ASN1_TIME_to_generalizedtime_internal(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) { ASN1_GENERALIZEDTIME *ret; char *str; @@ -131,13 +131,7 @@ ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) if (!ASN1_TIME_check(t)) return NULL; - if (!out || !*out) { - if (!(ret = ASN1_GENERALIZEDTIME_new ())) - return NULL; - if (out) - *out = ret; - } else - ret = *out; + ret = *out; /* If already GeneralizedTime just copy across */ if (t->type == V_ASN1_GENERALIZEDTIME) { @@ -152,15 +146,38 @@ ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) /* ASN1_STRING_set() allocated 'len + 1' bytes. */ newlen = t->length + 2 + 1; str = (char *)ret->data; + /* XXX ASN1_TIME is not Y2050 compatible */ i = snprintf(str, newlen, "%s%s", (t->data[0] >= '5') ? "19" : "20", (char *) t->data); if (i == -1 || i >= newlen) { - ASN1_STRING_free(ret); + M_ASN1_GENERALIZEDTIME_free(ret); + *out = NULL; return NULL; } return ret; } +ASN1_GENERALIZEDTIME * +ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out) +{ + ASN1_GENERALIZEDTIME *tmp = NULL, *ret; + + if (!out || !*out) { + if (!(tmp = ASN1_GENERALIZEDTIME_new())) + return NULL; + if (out != NULL) + *out = tmp; + else + out = &tmp; + } + + ret = ASN1_TIME_to_generalizedtime_internal(t, out); + if (ret == NULL && tmp != NULL) + ASN1_GENERALIZEDTIME_free(tmp); + + return ret; +} + int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) { diff --git a/lib/libssl/src/crypto/asn1/a_utctm.c b/lib/libssl/src/crypto/asn1/a_utctm.c index e4db9f8a994..35f2b7fd668 100644 --- a/lib/libssl/src/crypto/asn1/a_utctm.c +++ b/lib/libssl/src/crypto/asn1/a_utctm.c @@ -149,19 +149,15 @@ ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) return ASN1_UTCTIME_adj(s, t, 0, 0); } -ASN1_UTCTIME * -ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) +static ASN1_UTCTIME * +ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, + long offset_sec) { char *p; struct tm *ts; struct tm data; size_t len = 20; - if (s == NULL) - s = M_ASN1_UTCTIME_new(); - if (s == NULL) - return (NULL); - ts = gmtime_r(&t, &data); if (ts == NULL) return (NULL); @@ -193,6 +189,25 @@ ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) return (s); } +ASN1_UTCTIME * +ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec) +{ + ASN1_UTCTIME *tmp = NULL, *ret; + + if (s == NULL) { + tmp = M_ASN1_UTCTIME_new(); + if (tmp == NULL) + return NULL; + s = tmp; + } + + ret = ASN1_UTCTIME_adj_internal(s, t, offset_day, offset_sec); + if (ret == NULL && tmp != NULL) + M_ASN1_UTCTIME_free(tmp); + + return ret; +} + int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) { -- 2.20.1