Replace ASN1_GENERALIZEDTIME_adj(), ASN1_UTCTIME_adj() and
authormiod <miod@openbsd.org>
Thu, 15 May 2014 21:06:10 +0000 (21:06 +0000)
committermiod <miod@openbsd.org>
Thu, 15 May 2014 21:06:10 +0000 (21:06 +0000)
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
lib/libcrypto/asn1/a_time.c
lib/libcrypto/asn1/a_utctm.c
lib/libssl/src/crypto/asn1/a_gentm.c
lib/libssl/src/crypto/asn1/a_time.c
lib/libssl/src/crypto/asn1/a_utctm.c

index f331bff..7f8bc2f 100644 (file)
@@ -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;
+
+}
index 8db2163..574c99b 100644 (file)
@@ -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)
 {
index e4db9f8..35f2b7f 100644 (file)
@@ -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)
 {
index f331bff..7f8bc2f 100644 (file)
@@ -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;
+
+}
index 8db2163..574c99b 100644 (file)
@@ -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)
 {
index e4db9f8..35f2b7f 100644 (file)
@@ -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)
 {