]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Remove timegm() and tm_gmtoff
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Mon, 2 Oct 2023 16:20:27 +0000 (10:20 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Mon, 2 Oct 2023 16:22:35 +0000 (10:22 -0600)
Perfects portability. Still missing some testing.

I hope this is not too aggressive. If there are RPKI objects not using
Zulu, this is going to need further tweaking.

src/asn1/asn1c/GeneralizedTime.c
src/asn1/asn1c/GeneralizedTime.h
src/asn1/asn1c/UTCTime.c
src/asn1/asn1c/UTCTime.h
src/object/manifest.c

index 69b7a0981bc78926f924d7d3ce352f4bf7eff368..badade4adc00c4d334d562c1b3b0027a52a01f0f 100644 (file)
@@ -6,7 +6,6 @@
 #define        _REENTRANT                      /* for Sun */
 #define __EXTENSIONS__                  /* for Sun */
 
-#define _DEFAULT_SOURCE 1 /* timegm() */
 #define _XOPEN_SOURCE 600 /* snprintf(), timezone */
 #define _POSIX_C_SOURCE 200112L /* gmtime_r(), localtime_r(), tzset() */
 
 #include <assert.h>
 #include <errno.h>
 
-#if    defined(sun) || defined(__sun) || defined(__solaris__)
-#define        _EMULATE_TIMEGM
-#endif
-
-/*
- * Where to look for offset from GMT, Phase I.
- * Several platforms are known.
- */
-#if defined(__FreeBSD__) || defined(__OpenBSD__)    \
-       || (defined(__GNUC__) && defined(__APPLE_CC__)) \
-       || (defined __GLIBC__ && __GLIBC__ >= 2)
-#undef HAVE_TM_GMTOFF
-#define        HAVE_TM_GMTOFF
-#endif /* BSDs and newer glibc */
-
-/*
- * Where to look for offset from GMT, Phase II.
- */
-#ifdef HAVE_TM_GMTOFF
-#define        GMTOFF(tm)      ((tm).tm_gmtoff)
-#else  /* HAVE_TM_GMTOFF */
-#define        GMTOFF(tm)      (-timezone)
-#endif /* HAVE_TM_GMTOFF */
-
-#if    (defined(_EMULATE_TIMEGM) || !defined(HAVE_TM_GMTOFF))
-#warning "PLEASE STOP AND READ!"
-#warning "  timegm() is implemented via getenv(\"TZ\")/setenv(\"TZ\"), which may be not thread-safe."
-#warning "  "
-#warning "  You must fix the code by inserting appropriate locking"
-#warning "  if you want to use asn_GT2time() or asn_UT2time()."
-#warning "PLEASE STOP AND READ!"
-#endif /* _EMULATE_TIMEGM */
-
 #define        ATZVARS do {                                                    \
        char tzoldbuf[64];                                              \
        char *tzold
        tzset();                                                        \
 } while(0); } while(0);
 
-#ifndef HAVE_TIMEGM
-#ifdef _EMULATE_TIMEGM
-static time_t timegm(struct tm *tm) {
-       time_t tloc;
-       ATZVARS;
-       ATZSAVETZ;
-       tloc = mktime(tm);
-       ATZOLDTZ;
-       return tloc;
-}
-#endif /* _EMULATE_TIMEGM */
-#endif
-
-
 #ifndef        ASN___INTERNAL_TEST_MODE
 
 /*
@@ -158,11 +110,12 @@ GeneralizedTime_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
                            asn_app_constraint_failed_f *ctfailcb,
                            void *app_key) {
     const GeneralizedTime_t *st = (const GeneralizedTime_t *)sptr;
-       time_t tloc;
 
-       errno = EPERM;                  /* Just an unlikely error code */
-       tloc = asn_GT2time(st, 0, 0);
-       if(tloc == -1 && errno != EPERM) {
+       /* asn_GT2time() no longer supports NULL tm and no GMT */
+       fprintf(stderr, "GeneralizedTime_constraint() is not implemented for now.\n");
+       abort();
+
+       if(asn_GT2time(st, 0) != 0) {
                ASN__CTFAIL(app_key, td, sptr,
                        "%s: Invalid time format: %s (%s:%d)",
                        td->name, strerror(errno), __FILE__, __LINE__);
@@ -180,20 +133,16 @@ GeneralizedTime_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
        asn_enc_rval_t erval;
        int fv, fd;     /* seconds fraction value and number of digits */
        struct tm tm;
-       time_t tloc;
 
        /*
         * Encode as a canonical DER.
         */
-    errno = EPERM;
-    tloc = asn_GT2time_frac((const GeneralizedTime_t *)sptr, &fv, &fd, &tm,
-                            1); /* Recognize time */
-    if(tloc == -1 && errno != EPERM) {
+    if(asn_GT2time_frac((const GeneralizedTime_t *)sptr, &fv, &fd, &tm) != 0) {
         /* Failed to recognize time. Fail completely. */
                ASN__ENCODE_FAILED;
     }
 
-    st = asn_time2GT_frac(0, &tm, fv, fd, 1); /* Save time canonically */
+    st = asn_time2GT_frac(0, &tm, fv, fd); /* Save time */
     if(!st) ASN__ENCODE_FAILED;               /* Memory allocation failure. */
 
     erval = OCTET_STRING_encode_der(td, st, tag_mode, tag, cb, app_key);
@@ -215,13 +164,11 @@ GeneralizedTime_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
                int fv, fd;             /* fractional parts */
                struct tm tm;
 
-               errno = EPERM;
                if(asn_GT2time_frac((const GeneralizedTime_t *)sptr,
-                                       &fv, &fd, &tm, 1) == -1
-                               && errno != EPERM)
+                                       &fv, &fd, &tm) != 0)
                        ASN__ENCODE_FAILED;
 
-               gt = asn_time2GT_frac(0, &tm, fv, fd, 1);
+               gt = asn_time2GT_frac(0, &tm, fv, fd);
                if(!gt) ASN__ENCODE_FAILED;
        
                rv = OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
@@ -249,8 +196,7 @@ GeneralizedTime_print(const asn_TYPE_descriptor_t *td, const void *sptr,
                struct tm tm;
                int ret;
 
-               errno = EPERM;
-               if(asn_GT2time(st, &tm, 1) == -1 && errno != EPERM)
+               if(asn_GT2time(st, &tm) != 0)
                        return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
 
                ret = snprintf(buf, sizeof(buf),
@@ -264,20 +210,20 @@ GeneralizedTime_print(const asn_TYPE_descriptor_t *td, const void *sptr,
        }
 }
 
-time_t
-asn_GT2time(const GeneralizedTime_t *st, struct tm *ret_tm, int as_gmt) {
-       return asn_GT2time_frac(st, 0, 0, ret_tm, as_gmt);
+int
+asn_GT2time(const GeneralizedTime_t *st, struct tm *ret_tm) {
+       return asn_GT2time_frac(st, 0, 0, ret_tm);
 }
 
 time_t
-asn_GT2time_prec(const GeneralizedTime_t *st, int *frac_value, int frac_digits, struct tm *ret_tm, int as_gmt) {
+asn_GT2time_prec(const GeneralizedTime_t *st, int *frac_value, int frac_digits, struct tm *ret_tm) {
        time_t tloc;
        int fv, fd = 0;
 
        if(frac_value)
-               tloc = asn_GT2time_frac(st, &fv, &fd, ret_tm, as_gmt);
+               tloc = asn_GT2time_frac(st, &fv, &fd, ret_tm);
        else
-               return asn_GT2time_frac(st, 0, 0, ret_tm, as_gmt);
+               return asn_GT2time_frac(st, 0, 0, ret_tm);
        if(fd == 0 || frac_digits <= 0) {
                *frac_value = 0;
        } else {
@@ -300,31 +246,46 @@ asn_GT2time_prec(const GeneralizedTime_t *st, int *frac_value, int frac_digits,
        return tloc;
 }
 
-time_t
-asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits, struct tm *ret_tm, int as_gmt) {
+/*
+ * I had to tighten this up because timegm() is not standard.
+ * This outright means time_t is out of reach, which is a nightmare.
+ *
+ * rfc6486#section-4.2.1:
+ *
+ *    The manifestNumber, thisUpdate, and nextUpdate fields are modeled
+ *    after the corresponding fields in X.509 CRLs (see [RFC5280]).
+ *
+ * rfc5280#section-4.1.2.5.2:
+ *
+ *    GeneralizedTime values MUST be
+ *    expressed in Greenwich Mean Time (Zulu) and MUST include seconds
+ *    (i.e., times are YYYYMMDDHHMMSSZ)
+ *
+ * This requirement makes the problem more pallatable, because it means we can
+ * convert the Generalized Time to a simple CST struct tm, and use that instead
+ * of time_t.
+ *
+ * I left fractional seconds in place for now.
+ *
+ * The resulting tm is always in CST.
+ */
+int
+asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits,
+                struct tm *ret_tm) {
        struct tm tm_s;
        uint8_t *buf;
        uint8_t *end;
-       int gmtoff_h = 0;
-       int gmtoff_m = 0;
-       int gmtoff = 0; /* h + m */
-       int offset_specified = 0;
        int fvalue = 0;
        int fdigits = 0;
-       time_t tloc;
 
-       if(!st || !st->buf) {
-               errno = EINVAL;
-               return -1;
-       } else {
-               buf = st->buf;
-               end = buf + st->size;
-       }
+       if(!st || !st->buf)
+               goto garbage;
 
-       if(st->size < 10) {
-               errno = EINVAL;
-               return -1;
-       }
+       buf = st->buf;
+       end = buf + st->size;
+
+       if(st->size < 10)
+               goto garbage;
 
        /*
         * Decode first 10 bytes: "AAAAMMJJhh"
@@ -335,8 +296,7 @@ asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits,
 #define        B2F(var)        do {                                    \
                unsigned ch = *buf;                             \
                if(ch < 0x30 || ch > 0x39) {                    \
-                       errno = EINVAL;                         \
-                       return -1;                              \
+                       goto garbage;                           \
                } else {                                        \
                        var = var * 10 + (ch - 0x30);           \
                        buf++;                                  \
@@ -355,7 +315,7 @@ asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits,
        B2T(tm_hour);   /* 9: h */
        B2T(tm_hour);   /* 0: h */
 
-       if(buf == end) goto local_finish;
+       if(buf == end) goto garbage;
 
        /*
         * Parse [mm[ss[(.|,)ffff]]]
@@ -365,19 +325,14 @@ asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits,
        case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
        case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
                tm_s.tm_min = (*buf++) - 0x30;
-               if(buf == end) { errno = EINVAL; return -1; }
+               if(buf == end) goto garbage;
                B2T(tm_min);
                break;
-       case 0x2B: case 0x2D:   /* +, - */
-               goto offset;
-       case 0x5A:              /* Z */
-               goto utc_finish;
-       default:
-               errno = EINVAL;
-               return -1;
+       default:                /* +, -, Z */
+               goto garbage;
        }
 
-       if(buf == end) goto local_finish;
+       if(buf == end) goto garbage;
 
        /*
         * Parse [mm[ss[(.|,)ffff]]]
@@ -387,19 +342,14 @@ asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits,
        case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
        case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
                tm_s.tm_sec = (*buf++) - 0x30;
-               if(buf == end) { errno = EINVAL; return -1; }
+               if(buf == end) goto garbage;
                B2T(tm_sec);
                break;
-       case 0x2B: case 0x2D:   /* +, - */
-               goto offset;
-       case 0x5A:              /* Z */
-               goto utc_finish;
-       default:
-               errno = EINVAL;
-               return -1;
+       default:                /* +, -, Z */
+               goto garbage;
        }
 
-       if(buf == end) goto local_finish;
+       if(buf == end) goto garbage;
 
        /*
         * Parse [mm[ss[(.|,)ffff]]]
@@ -430,121 +380,44 @@ asn_GT2time_frac(const GeneralizedTime_t *st, int *frac_value, int *frac_digits,
                }
        }
 
-       if(buf == end) goto local_finish;
-
-       switch(*buf) {
-       case 0x2B: case 0x2D:   /* +, - */
-               goto offset;
-       case 0x5A:              /* Z */
-               goto utc_finish;
-       default:
-               errno = EINVAL;
-               return -1;
-       }
-
+       if(buf == end) goto garbage;
 
-offset:
+       if ((*buf) != 0x5A) /* Zulu */
+               goto garbage;
 
-       if(end - buf < 3) {
-               errno = EINVAL;
-               return -1;
-       }
-       buf++;
-       B2F(gmtoff_h);
-       B2F(gmtoff_h);
-       if(buf[-3] == 0x2D)     /* Negative */
-               gmtoff = -1;
-       else
-               gmtoff = 1;
-
-       if((end - buf) == 2) {
-               B2F(gmtoff_m);
-               B2F(gmtoff_m);
-       } else if(end != buf) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       gmtoff = gmtoff * (3600 * gmtoff_h + 60 * gmtoff_m);
-
-       /* Fall through */
-utc_finish:
-
-       offset_specified = 1;
-
-       /* Fall through */
-local_finish:
-
-       /*
-        * Validation.
-        */
+       /* Validation */
        if((tm_s.tm_mon > 12 || tm_s.tm_mon < 1)
        || (tm_s.tm_mday > 31 || tm_s.tm_mday < 1)
        || (tm_s.tm_hour > 23)
        || (tm_s.tm_sec > 60)
-       ) {
-               errno = EINVAL;
-               return -1;
-       }
+       )
+               goto garbage;
 
        /* Canonicalize */
        tm_s.tm_mon -= 1;       /* 0 - 11 */
        tm_s.tm_year -= 1900;
-       tm_s.tm_isdst = -1;
-
-       tm_s.tm_sec -= gmtoff;
-
-       /*** AT THIS POINT tm_s is either GMT or local (unknown) ****/
-
-       if(offset_specified) {
-               tloc = timegm(&tm_s);
-       } else {
-               /*
-                * Without an offset (or "Z"),
-                * we can only guess that it is a local zone.
-                * Interpret it in this fashion.
-                */
-               tloc = mktime(&tm_s);
-       }
-       if(tloc == -1) {
-               errno = EINVAL;
-               return -1;
-       }
+       tm_s.tm_isdst = 0;
 
-       if(ret_tm) {
-               if(as_gmt) {
-                       if(offset_specified) {
-                               *ret_tm = tm_s;
-                       } else {
-                               if(gmtime_r(&tloc, ret_tm) == 0) {
-                                       errno = EINVAL;
-                                       return -1;
-                               }
-                       }
-               } else {
-                       if(localtime_r(&tloc, ret_tm) == 0) {
-                               errno = EINVAL;
-                               return -1;
-                       }
-               }
-       }
+       *ret_tm = tm_s;
 
        /* Fractions of seconds */
        if(frac_value) *frac_value = fvalue;
        if(frac_digits) *frac_digits = fdigits;
 
-       return tloc;
+       return 0;
+
+garbage:
+       errno = EINVAL;
+       return -1;
 }
 
 GeneralizedTime_t *
-asn_time2GT(GeneralizedTime_t *opt_gt, const struct tm *tm, int force_gmt) {
-       return asn_time2GT_frac(opt_gt, tm, 0, 0, force_gmt);
+asn_time2GT(GeneralizedTime_t *opt_gt, const struct tm *tm) {
+       return asn_time2GT_frac(opt_gt, tm, 0, 0);
 }
 
 GeneralizedTime_t *
-asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, int frac_value, int frac_digits, int force_gmt) {
-       struct tm tm_s;
-       long gmtoff;
+asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, int frac_value, int frac_digits) {
        const unsigned int buf_size =
                4 + 2 + 2       /* yyyymmdd */
                + 2 + 2 + 2     /* hhmmss */
@@ -566,20 +439,6 @@ asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, int frac_value,
        buf = (char *)MALLOC(buf_size);
        if(!buf) return 0;
 
-       gmtoff = GMTOFF(*tm);
-
-       if(force_gmt && gmtoff) {
-               tm_s = *tm;
-               tm_s.tm_sec -= gmtoff;
-               timegm(&tm_s);  /* Fix the time */
-               tm = &tm_s;
-#ifdef HAVE_TM_GMTOFF
-               assert(!GMTOFF(tm_s));  /* Will fix itself */
-#else  /* !HAVE_TM_GMTOFF */
-               gmtoff = 0;
-#endif
-       }
-
        size = snprintf(buf, buf_size, "%04d%02d%02d%02d%02d%02d",
                tm->tm_year + 1900,
                tm->tm_mon + 1,
@@ -628,22 +487,9 @@ asn_time2GT_frac(GeneralizedTime_t *opt_gt, const struct tm *tm, int frac_value,
                }
        }
 
-       if(force_gmt) {
-               *p++ = 0x5a;    /* "Z" */
-               *p++ = 0;
-               size++;
-       } else {
-               int ret;
-               gmtoff %= 86400;
-               ret = snprintf(p, buf_size - size, "%+03ld%02ld",
-                       gmtoff / 3600, labs(gmtoff % 3600) / 60);
-               if(ret != 5) {
-                       FREEMEM(buf);
-                       errno = EINVAL;
-                       return 0;
-               }
-               size += ret;
-       }
+       *p++ = 0x5a;    /* "Z" */
+       *p++ = 0;
+       size++;
 
        if(opt_gt) {
                if(opt_gt->buf)
@@ -699,6 +545,10 @@ GeneralizedTime_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
 
     (void)td;
 
+    /* asn_GT2time_frac() no longer supports NULL tm and no GMT. */
+    fprintf(stderr, "GeneralizedTime_compare() is not implemented for now.\n");
+    abort();
+
     if(a && b) {
         int afrac_value, afrac_digits;
         int bfrac_value, bfrac_digits;
@@ -706,10 +556,10 @@ GeneralizedTime_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
         time_t at, bt;
 
         errno = EPERM;
-        at = asn_GT2time_frac(a, &afrac_value, &afrac_digits, 0, 0);
+        at = asn_GT2time_frac(a, &afrac_value, &afrac_digits, 0);
         aerr = errno;
         errno = EPERM;
-        bt = asn_GT2time_frac(b, &bfrac_value, &bfrac_digits, 0, 0);
+        bt = asn_GT2time_frac(b, &bfrac_value, &bfrac_digits, 0);
         berr = errno;
 
         if(at == -1 && aerr != EPERM) {
index 471f2830a8011c3a4860401972b85defc1e73320..be517c410053b57eefc1dca2e46346db6eda087b 100644 (file)
@@ -35,8 +35,6 @@ asn_random_fill_f  GeneralizedTime_random_fill;
  * Some handy helpers. *
  ***********************/
 
-struct tm;     /* <time.h> */
-
 /*
  * Convert a GeneralizedTime structure into time_t
  * and optionally into struct tm.
@@ -44,13 +42,12 @@ struct tm;  /* <time.h> */
  * instead of default local one.
  * On error returns -1 and errno set to EINVAL
  */
-time_t asn_GT2time(const GeneralizedTime_t *, struct tm *_optional_tm4fill,
-       int as_gmt);
+int asn_GT2time(const GeneralizedTime_t *, struct tm *_optional_tm4fill);
 
 /* A version of the above function also returning the fractions of seconds */
-time_t asn_GT2time_frac(const GeneralizedTime_t *,
+int asn_GT2time_frac(const GeneralizedTime_t *,
        int *frac_value, int *frac_digits,      /* (value / (10 ^ digits)) */
-       struct tm *_optional_tm4fill, int as_gmt);
+       struct tm *_optional_tm4fill);
 
 /*
  * Another version returning fractions with defined precision
@@ -59,7 +56,7 @@ time_t asn_GT2time_frac(const GeneralizedTime_t *,
  */
 time_t asn_GT2time_prec(const GeneralizedTime_t *,
        int *frac_value, int frac_digits,
-       struct tm *_optional_tm4fill, int as_gmt);
+       struct tm *_optional_tm4fill);
 
 /*
  * Convert a struct tm into GeneralizedTime.
@@ -69,9 +66,9 @@ time_t asn_GT2time_prec(const GeneralizedTime_t *,
  * On error, this function returns 0 and sets errno.
  */
 GeneralizedTime_t *asn_time2GT(GeneralizedTime_t *_optional_gt,
-       const struct tm *, int force_gmt);
+       const struct tm *);
 GeneralizedTime_t *asn_time2GT_frac(GeneralizedTime_t *_optional_gt,
-       const struct tm *, int frac_value, int frac_digits, int force_gmt);
+       const struct tm *, int frac_value, int frac_digits);
 
 #ifdef __cplusplus
 }
index 1c1d8790102b2857b166c88542b25529e649c7fd..cf8df4f5d4663c9bbaff3cb25ee219159af2a58d 100644 (file)
@@ -76,11 +76,12 @@ int
 UTCTime_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
                    asn_app_constraint_failed_f *ctfailcb, void *app_key) {
     const UTCTime_t *st = (const UTCTime_t *)sptr;
-       time_t tloc;
 
-       errno = EPERM;                  /* Just an unlikely error code */
-       tloc = asn_UT2time(st, 0, 0);
-       if(tloc == -1 && errno != EPERM) {
+    /* asn_UT2time() no longer supports NULL tm and no GMT. */
+    fprintf(stderr, "UTCTime_constraint() is not implemented for now.\n");
+    abort();
+
+       if(asn_UT2time(st, 0) != 0) {
         ASN__CTFAIL(app_key, td, sptr, "%s: Invalid time format: %s (%s:%d)",
                     td->name, strerror(errno), __FILE__, __LINE__);
         return -1;
@@ -100,13 +101,11 @@ UTCTime_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
                UTCTime_t *ut;
                struct tm tm;
 
-               errno = EPERM;
-               if(asn_UT2time((const UTCTime_t *)sptr, &tm, 1) == -1
-                               && errno != EPERM)
+               if(asn_UT2time((const UTCTime_t *)sptr, &tm) != 0)
                        ASN__ENCODE_FAILED;
 
                /* Fractions are not allowed in UTCTime */
-               ut = asn_time2UT(0, &tm, 1);
+               ut = asn_time2UT(0, &tm);
                if(!ut) ASN__ENCODE_FAILED;
 
                rv = OCTET_STRING_encode_xer_utf8(td, sptr, ilevel, flags,
@@ -134,8 +133,7 @@ UTCTime_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
                struct tm tm;
                int ret;
 
-               errno = EPERM;
-               if(asn_UT2time(st, &tm, 1) == -1 && errno != EPERM)
+               if(asn_UT2time(st, &tm) != 0)
                        return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
 
                ret = snprintf(buf, sizeof(buf),
@@ -150,7 +148,7 @@ UTCTime_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 }
 
 time_t
-asn_UT2time(const UTCTime_t *st, struct tm *_tm, int as_gmt) {
+asn_UT2time(const UTCTime_t *st, struct tm *_tm) {
        char buf[24];   /* "AAMMJJhhmmss+hhmm" + cushion */
        GeneralizedTime_t gt;
 
@@ -173,14 +171,14 @@ asn_UT2time(const UTCTime_t *st, struct tm *_tm, int as_gmt) {
                gt.buf[1] = 0x30;
        }
 
-       return asn_GT2time(&gt, _tm, as_gmt);
+       return asn_GT2time(&gt, _tm);
 }
 
 UTCTime_t *
-asn_time2UT(UTCTime_t *opt_ut, const struct tm *tm, int force_gmt) {
+asn_time2UT(UTCTime_t *opt_ut, const struct tm *tm) {
        GeneralizedTime_t *gt = (GeneralizedTime_t *)opt_ut;
 
-       gt = asn_time2GT(gt, tm, force_gmt);
+       gt = asn_time2GT(gt, tm);
        if(gt == 0) return 0;
 
        assert(gt->size >= 2);
@@ -231,15 +229,19 @@ UTCTime_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
 
     (void)td;
 
+    /* asn_UT2time() no longer supports NULL tm and no GMT. */
+    fprintf(stderr, "UTCTime_compare() is not implemented for now.\n");
+    abort();
+
     if(a && b) {
         time_t at, bt;
         int aerr, berr;
 
         errno = EPERM;
-        at = asn_UT2time(a, 0, 0);
+        at = asn_UT2time(a, 0);
         aerr = errno;
         errno = EPERM;
-        bt = asn_UT2time(b, 0, 0);
+        bt = asn_UT2time(b, 0);
         berr = errno;
 
         if(at == -1 && aerr != EPERM) {
index 04ba958be26c0754e16cccde59c5c189a75a682d..33318cf8ee91ad3abb7e807899504d45d5500f87 100644 (file)
@@ -38,10 +38,10 @@ asn_random_fill_f  UTCTime_random_fill;
 struct tm;     /* <time.h> */
 
 /* See asn_GT2time() in GeneralizedTime.h */
-time_t asn_UT2time(const UTCTime_t *, struct tm *_optional_tm4fill, int as_gmt);
+time_t asn_UT2time(const UTCTime_t *, struct tm *_optional_tm4fill);
 
 /* See asn_time2GT() in GeneralizedTime.h */
-UTCTime_t *asn_time2UT(UTCTime_t *__opt_ut, const struct tm *, int force_gmt);
+UTCTime_t *asn_time2UT(UTCTime_t *__opt_ut, const struct tm *);
 
 #ifdef __cplusplus
 }
index 07cb74eba8209340b3c7935935da34d2d88d174a..bf6df56d4aa074c85db609063a0a9a4992620087 100644 (file)
@@ -41,6 +41,29 @@ decode_manifest(struct signed_object *sobj, struct Manifest **result)
        );
 }
 
+/*
+ * Expects both arguments to be normalized and CST.
+ */
+static int
+tm_cmp(struct tm *tm1, struct tm *tm2)
+{
+#define TM_CMP(field)                                                  \
+       if (tm1->field < tm2->field)                                    \
+               return -1;                                              \
+       if (tm1->field > tm2->field)                                    \
+               return 1;                                               \
+
+       TM_CMP(tm_year);
+       TM_CMP(tm_mon);
+       TM_CMP(tm_mday);
+       TM_CMP(tm_hour);
+       TM_CMP(tm_min);
+       TM_CMP(tm_sec);
+       return 0;
+
+#undef TM_CMP
+}
+
 static int
 validate_dates(GeneralizedTime_t *this, GeneralizedTime_t *next)
 {
@@ -49,44 +72,46 @@ validate_dates(GeneralizedTime_t *this, GeneralizedTime_t *next)
        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,                   \
        tm.tm_hour, tm.tm_min, tm.tm_sec
 
-       time_t thisUpdate;
-       time_t nextUpdate;
-       time_t now;
-       struct tm thisUpdate_tm;
-       struct tm nextUpdate_tm;
+       time_t now_tt;
+       struct tm now;
+       struct tm thisUpdate;
+       struct tm nextUpdate;
        int error;
 
-       /*
-        * BTW: We only need the tm variables for error messages, which are
-        * rarely needed.
-        * So maybe we could get a small performance boost by postponing the
-        * calls to localtime_r().
-        */
-       thisUpdate = asn_GT2time(this, &thisUpdate_tm, false);
-       nextUpdate = asn_GT2time(next, &nextUpdate_tm, false);
+       error = asn_GT2time(this, &thisUpdate);
+       if (error)
+               return pr_val_err("Manifest's thisUpdate date is unparseable.");
+       error = asn_GT2time(next, &nextUpdate);
+       if (error)
+               return pr_val_err("Manifest's nextUpdate date is unparseable.");
 
-       if (difftime(thisUpdate, nextUpdate) > 0) {
+       if (tm_cmp(&thisUpdate, &nextUpdate) > 0) {
                return pr_val_err(
                    "Manifest's thisUpdate (" TM_FMT ") > nextUpdate ("
                        TM_FMT ").",
-                   TM_ARGS(thisUpdate_tm),
-                   TM_ARGS(nextUpdate_tm));
+                   TM_ARGS(thisUpdate),
+                   TM_ARGS(nextUpdate));
        }
 
-       now = 0;
-       error = get_current_time(&now);
+       now_tt = 0;
+       error = get_current_time(&now_tt);
        if (error)
                return error;
+       if (gmtime_r(&now_tt, &now) == NULL) {
+               error = errno;
+               return pr_val_err("gmtime_r(now) error %d: %s", error,
+                   strerror(error));
+       }
 
-       if (difftime(now, thisUpdate) < 0) {
+       if (tm_cmp(&now, &thisUpdate) < 0) {
                return pr_val_err(
                    "Manifest is not valid yet. (thisUpdate: " TM_FMT ")",
-                   TM_ARGS(thisUpdate_tm));
+                   TM_ARGS(thisUpdate));
        }
-       if (difftime(now, nextUpdate) > 0) {
+       if (tm_cmp(&now, &nextUpdate) > 0) {
                return incidence(INID_MFT_STALE,
                    "Manifest is stale. (nextUpdate: " TM_FMT ")",
-                   TM_ARGS(nextUpdate_tm));
+                   TM_ARGS(nextUpdate));
        }
 
        return 0;