hitch  1.5.2
About: Hitch is a libev-based high performance SSL/TLS proxy that terminates TLS/SSL connections and forwards the unencrypted traffic to some backend.
  Fossies Dox: hitch-1.5.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

asn_gentm.c
Go to the documentation of this file.
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 }
asn1_gentime_parse
double asn1_gentime_parse(const ASN1_GENERALIZEDTIME *d)
Definition: asn_gentm.c:246
SECS_PER_DAY
#define SECS_PER_DAY
Definition: asn_gentm.c:49
openssl_gmtime_adj
static int openssl_gmtime_adj(struct tm *tm, int off_day, long offset_sec)
Definition: asn_gentm.c:97
julian_to_date
static void julian_to_date(long jd, int *y, int *m, int *d)
Definition: asn_gentm.c:24
date_to_julian
static long date_to_julian(int y, int m, int d)
Definition: asn_gentm.c:41
julian_adj
static int julian_adj(const struct tm *tm, int off_day, long offset_sec, long *pday, int *psec)
Definition: asn_gentm.c:53
asn1_generalizedtime_to_tm
static int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
Definition: asn_gentm.c:128