root/src/eventer/OETS_asn1_helper.c

Revision 72c5b0be5471b0ebbb782fba28a4f6f1cd00a6f1, 8.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 5 years ago)

closes #173

  • Property mode set to 100644
Line 
1 /* Copyright (c) 2002 The OpenEvidence Project.  All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions
5  * are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions, the following disclaimer,
9  *    and the original OpenSSL and SSLeay Licences below.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions, the following disclaimer
13  *    and the original OpenSSL and SSLeay Licences below in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgments:
19  *    "This product includes software developed by the Openevidence Project
20  *    for use in the OpenEvidence Toolkit. (http://www.openevidence.org/)"
21  *    This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
23  *    This product includes cryptographic software written by Eric Young
24  *    (eay@cryptsoft.com).  This product includes software written by Tim
25  *    Hudson (tjh@cryptsoft.com)."
26  *
27  * 4. The names "OpenEvidence Toolkit" and "OpenEvidence Project" must not be
28  *    used to endorse or promote products derived from this software without
29  *    prior written permission. For written permission, please contact
30  *    openevidence-core@openevidence.org.
31  *
32  * 5. Products derived from this software may not be called "OpenEvidence"
33  *    nor may "OpenEvidence" appear in their names without prior written
34  *    permission of the OpenEvidence Project.
35  *
36  * 6. Redistributions of any form whatsoever must retain the following
37  *    acknowledgments:
38  *    "This product includes software developed by the OpenEvidence Project
39  *    for use in the OpenEvidence Toolkit (http://www.openevidence.org/)
40  *    This product includes software developed by the OpenSSL Project
41  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
42  *    This product includes cryptographic software written by Eric Young
43  *    (eay@cryptsoft.com).  This product includes software written by Tim
44  *    Hudson (tjh@cryptsoft.com)."
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE OpenEvidence PROJECT ``AS IS'' AND ANY
47  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenEvidence PROJECT OR
50  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
55  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
57  * OF THE POSSIBILITY OF SUCH DAMAGE.
58  * ====================================================================
59  *
60  * This product includes software developed by the OpenSSL Project
61  * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
62  * This product includes cryptographic software written by Eric Young
63  * (eay@cryptsoft.com).  This product includes software written by Tim
64  * Hudson (tjh@cryptsoft.com).
65  */
66
67 #include <time.h>
68 #include <openssl/x509.h>
69
70 static char days[2][12] = {
71     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
72     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
73 };
74
75 static int pint(const char **s, int n, int min, int max, int *e)
76 {
77     int retval = 0;
78     while (n) {
79         if (**s < '0' || **s > '9') { *e = 1; return 0; }
80         retval *= 10;
81         retval += **s - '0';
82         --n; ++(*s);
83     }
84     if (retval < min || retval > max) *e = 1;
85     return retval;
86 }
87
88 time_t OETS_ASN1_TIME_get(ASN1_TIME *a, int *err)
89 {
90     int dummy;
91     const char *s;
92     int generalized;
93     struct tm t;
94     int i, year, isleap, offset;
95     time_t retval;
96    
97     if (err == NULL) err = &dummy;
98     if (a->type == V_ASN1_GENERALIZEDTIME) {
99         generalized = 1;
100     } else if (a->type == V_ASN1_UTCTIME) {
101         generalized = 0;
102     } else {
103         *err = 1;
104         return 0;
105     }
106     s = (char *)a->data; // Data should be always null terminated
107     if (s == NULL || s[a->length] != '\0') {
108         *err = 1;
109         return 0;
110     }
111
112     *err = 0;
113     if (generalized) {
114         t.tm_year = pint(&s, 4, 0, 9999, err) - 1900;
115     } else {
116         t.tm_year = pint(&s, 2, 0, 99, err);
117         if (t.tm_year < 50) t.tm_year += 100;
118     }
119     t.tm_mon = pint(&s, 2, 1, 12, err) - 1;
120     t.tm_mday = pint(&s, 2, 1, 31, err);
121     // NOTE: It's not yet clear, if this implementation is 100% correct
122     // for GeneralizedTime... but at least misinterpretation is
123     // impossible --- we just throw an exception
124     t.tm_hour = pint(&s, 2, 0, 23, err);
125     t.tm_min = pint(&s, 2, 0, 59, err);
126     if (*s >= '0' && *s <= '9') {
127         t.tm_sec = pint(&s, 2, 0, 59, err);
128     } else {
129         t.tm_sec = 0;
130     }
131     if (*err) return 0; // Format violation
132     if (generalized) {
133         // skip fractional seconds if any
134         while (*s == '.' || *s == ',' || (*s >= '0' && *s <= '9')) ++s;
135         // special treatment for local time
136         if (*s == 0) {
137             t.tm_isdst = -1;
138             retval = mktime(&t); // Local time is easy :)
139             if (retval == (time_t)-1) {
140                 *err = 2;
141                 retval = 0;
142             }
143             return retval;
144         }
145     }
146     if (*s == 'Z') {
147         offset = 0;
148         ++s;
149     } else if (*s == '-' || *s == '+') {
150         i = (*s++ == '-');
151         offset = pint(&s, 2, 0, 12, err);
152         offset *= 60;
153         offset += pint(&s, 2, 0, 59, err);
154         if (*err) return 0; // Format violation
155         if (i) offset = -offset;
156     } else {
157         *err = 1;
158         return 0;
159     }
160     if (*s) {
161         *err = 1;
162         return 0;
163     }
164
165     // And here comes the hard part --- there's no standard function to
166     // convert struct tm containing UTC time into time_t without
167     // messing global timezone settings (breaks multithreading and may
168     // cause other problems) and thus we have to do this "by hand"
169     //
170     // NOTE: Overflow check does not detect too big overflows, but is
171     // sufficient thanks to the fact that year numbers are limited to four
172     // digit non-negative values.
173     retval = t.tm_sec;
174     retval += (t.tm_min - offset) * 60;
175     retval += t.tm_hour * 3600;
176     retval += (t.tm_mday - 1) * 86400;
177     year = t.tm_year + 1900;
178     if (sizeof(time_t) == 4) {
179         // This is just to avoid too big overflows being undetected, finer
180         // overflow detection is done below.
181         if (year < 1900 || year > 2040) *err = 2;
182     }
183     // FIXME: Does POSIX really say, that all years divisible by 4 are
184     // leap years (for consistency)??? Fortunately, this problem does
185     // not exist for 32-bit time_t and we should'nt be worried about
186     // this until the year of 2100 :)
187     isleap = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
188     for (i = t.tm_mon - 1; i >= 0; --i) retval += days[isleap][i] * 86400;
189     retval += (year - 1970) * 31536000;
190     if (year < 1970) {
191         retval -= ((1970 - year + 2) / 4) * 86400;
192         if (sizeof(time_t) > 4) {
193             for (i = 1900; i >= year; i -= 100) {
194                 if (i % 400 == 0) continue;
195                 retval += 86400;
196             }
197         }
198         if (retval >= 0) *err = 2;
199     } else {
200         retval += ((year - 1970 + 1) / 4) * 86400;
201         if (sizeof(time_t) > 4) {
202             for (i = 2100; i < year; i += 100) {
203                 // The following condition is the reason to
204                 // start with 2100 instead of 2000
205                 if (i % 400 == 0) continue;
206                 retval -= 86400;
207             }
208         }
209         if (retval < 0) *err = 2;
210     }
211
212     if (*err) retval = 0;
213     return retval;
214 }
Note: See TracBrowser for help on using the browser.