"Fossies" - the Fresh Open Source Software Archive

Member "hitch-1.5.2/src/foreign/asn_gentm.c" (27 Aug 2019, 5578 Bytes) of package /linux/www/hitch-1.5.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "asn_gentm.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
    3  *
    4  * Licensed under the OpenSSL license (the "License").  You may not use
    5  * this file except in compliance with the License.  You can obtain a copy
    6  * in the file LICENSE in the source distribution or at
    7  * https://www.openssl.org/source/license.html
    8  */
    9 
   10 /* This code is borrowed from the openssl library, which conveniently
   11  * doesn't expose any functions for converting an ASN1_GENERALIZEDTIME
   12  * to a sane timestamp format.
   13  */
   14 
   15 #include <stdio.h>
   16 #include <time.h>
   17 #include <openssl/asn1.h>
   18 
   19 /*
   20  * Convert date to and from julian day Uses Fliegel & Van Flandern algorithm
   21  */
   22 
   23 static void
   24 julian_to_date(long jd, int *y, int *m, int *d)
   25 {
   26     long L = jd + 68569;
   27     long n = (4 * L) / 146097;
   28     long i, j;
   29 
   30     L = L - (146097 * n + 3) / 4;
   31     i = (4000 * (L + 1)) / 1461001;
   32     L = L - (1461 * i) / 4 + 31;
   33     j = (80 * L) / 2447;
   34     *d = L - (2447 * j) / 80;
   35     L = j / 11;
   36     *m = j + 2 - (12 * L);
   37     *y = 100 * (n - 49) + i + L;
   38 }
   39 
   40 static long
   41 date_to_julian(int y, int m, int d)
   42 {
   43     return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
   44         (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
   45         (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
   46 }
   47 
   48 
   49 #define SECS_PER_DAY (24 * 60 * 60)
   50 
   51 /* Convert tm structure and offset into julian day and seconds */
   52 static int
   53 julian_adj(const struct tm *tm, int off_day, long offset_sec,
   54     long *pday, int *psec)
   55 {
   56     int offset_hms, offset_day;
   57     long time_jd;
   58     int time_year, time_month, time_day;
   59     /* split offset into days and day seconds */
   60     offset_day = offset_sec / SECS_PER_DAY;
   61     /* Avoid sign issues with % operator */
   62     offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
   63     offset_day += off_day;
   64     /* Add current time seconds to offset */
   65     offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
   66     /* Adjust day seconds if overflow */
   67     if (offset_hms >= SECS_PER_DAY) {
   68         offset_day++;
   69         offset_hms -= SECS_PER_DAY;
   70     } else if (offset_hms < 0) {
   71         offset_day--;
   72         offset_hms += SECS_PER_DAY;
   73     }
   74 
   75     /*
   76      * Convert date of time structure into a Julian day number.
   77      */
   78 
   79     time_year = tm->tm_year + 1900;
   80     time_month = tm->tm_mon + 1;
   81     time_day = tm->tm_mday;
   82 
   83     time_jd = date_to_julian(time_year, time_month, time_day);
   84 
   85     /* Work out Julian day of new date */
   86     time_jd += offset_day;
   87 
   88     if (time_jd < 0)
   89         return 0;
   90 
   91     *pday = time_jd;
   92     *psec = offset_hms;
   93     return 1;
   94 }
   95 
   96 static
   97 int openssl_gmtime_adj(struct tm *tm, int off_day, long offset_sec)
   98 {
   99     int time_sec, time_year, time_month, time_day;
  100     long time_jd;
  101 
  102     /* Convert time and offset into Julian day and seconds */
  103     if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec))
  104         return 0;
  105 
  106     /* Convert Julian day back to date */
  107 
  108     julian_to_date(time_jd, &time_year, &time_month, &time_day);
  109 
  110     if (time_year < 1900 || time_year > 9999)
  111         return 0;
  112 
  113     /* Update tm structure */
  114 
  115     tm->tm_year = time_year - 1900;
  116     tm->tm_mon = time_month - 1;
  117     tm->tm_mday = time_day;
  118 
  119     tm->tm_hour = time_sec / 3600;
  120     tm->tm_min = (time_sec / 60) % 60;
  121     tm->tm_sec = time_sec % 60;
  122 
  123     return 1;
  124 
  125 }
  126 
  127 static
  128 int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
  129 {
  130     static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
  131     static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
  132     char *a;
  133     int n, i, l, o;
  134 
  135     if (d->type != V_ASN1_GENERALIZEDTIME)
  136         return (0);
  137     l = d->length;
  138     a = (char *)d->data;
  139     o = 0;
  140     /*
  141      * GENERALIZEDTIME is similar to UTCTIME except the year is represented
  142      * as YYYY. This stuff treats everything as a two digit field so make
  143      * first two fields 00 to 99
  144      */
  145     if (l < 13)
  146         goto err;
  147     for (i = 0; i < 7; i++) {
  148         if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
  149             i++;
  150             if (tm)
  151                 tm->tm_sec = 0;
  152             break;
  153         }
  154         if ((a[o] < '0') || (a[o] > '9'))
  155             goto err;
  156         n = a[o] - '0';
  157         if (++o > l)
  158             goto err;
  159 
  160         if ((a[o] < '0') || (a[o] > '9'))
  161             goto err;
  162         n = (n * 10) + a[o] - '0';
  163         if (++o > l)
  164             goto err;
  165 
  166         if ((n < min[i]) || (n > max[i]))
  167             goto err;
  168         if (tm) {
  169             switch (i) {
  170             case 0:
  171                 tm->tm_year = n * 100 - 1900;
  172                 break;
  173             case 1:
  174                 tm->tm_year += n;
  175                 break;
  176             case 2:
  177                 tm->tm_mon = n - 1;
  178                 break;
  179             case 3:
  180                 tm->tm_mday = n;
  181                 break;
  182             case 4:
  183                 tm->tm_hour = n;
  184                 break;
  185             case 5:
  186                 tm->tm_min = n;
  187                 break;
  188             case 6:
  189                 tm->tm_sec = n;
  190                 break;
  191             }
  192         }
  193     }
  194     /*
  195      * Optional fractional seconds: decimal point followed by one or more
  196      * digits.
  197      */
  198     if (a[o] == '.') {
  199         if (++o > l)
  200             goto err;
  201         i = o;
  202         while ((o <= l) && (a[o] >= '0') && (a[o] <= '9'))
  203             o++;
  204         /* Must have at least one digit after decimal point */
  205         if (i == o)
  206             goto err;
  207     }
  208 
  209     if (a[o] == 'Z')
  210         o++;
  211     else if ((a[o] == '+') || (a[o] == '-')) {
  212         int offsign = a[o] == '-' ? -1 : 1, offset = 0;
  213         o++;
  214         if (o + 4 > l)
  215             goto err;
  216         for (i = 7; i < 9; i++) {
  217             if ((a[o] < '0') || (a[o] > '9'))
  218                 goto err;
  219             n = a[o] - '0';
  220             o++;
  221             if ((a[o] < '0') || (a[o] > '9'))
  222                 goto err;
  223             n = (n * 10) + a[o] - '0';
  224             if ((n < min[i]) || (n > max[i]))
  225                 goto err;
  226             if (tm) {
  227                 if (i == 7)
  228                     offset = n * 3600;
  229                 else if (i == 8)
  230                     offset += n * 60;
  231             }
  232             o++;
  233         }
  234         if (offset && !openssl_gmtime_adj(tm, 0, offset * offsign))
  235             return 0;
  236     } else if (a[o]) {
  237         /* Missing time zone information. */
  238         goto err;
  239     }
  240     return (o == l);
  241 err:
  242     return (0);
  243 }
  244 
  245 double
  246 asn1_gentime_parse(const ASN1_GENERALIZEDTIME *d) {
  247     struct tm tm = { .tm_min = 0 };
  248 
  249     if (d == NULL)
  250         return (-1.0);
  251 
  252     if (asn1_generalizedtime_to_tm(&tm, d) == 0)
  253         return (-1.0);
  254 
  255     return (double) (mktime(&tm));
  256 }