diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libcrypto/o_time.c | 153 |
1 files changed, 151 insertions, 2 deletions
diff --git a/src/lib/libcrypto/o_time.c b/src/lib/libcrypto/o_time.c index e29091d650..eecbdd19f0 100644 --- a/src/lib/libcrypto/o_time.c +++ b/src/lib/libcrypto/o_time.c | |||
| @@ -2,6 +2,9 @@ | |||
| 2 | /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL | 2 | /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL |
| 3 | * project 2001. | 3 | * project 2001. |
| 4 | */ | 4 | */ |
| 5 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | ||
| 6 | * project 2008. | ||
| 7 | */ | ||
| 5 | /* ==================================================================== | 8 | /* ==================================================================== |
| 6 | * Copyright (c) 2001 The OpenSSL Project. All rights reserved. | 9 | * Copyright (c) 2001 The OpenSSL Project. All rights reserved. |
| 7 | * | 10 | * |
| @@ -73,7 +76,7 @@ struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) | |||
| 73 | { | 76 | { |
| 74 | struct tm *ts = NULL; | 77 | struct tm *ts = NULL; |
| 75 | 78 | ||
| 76 | #if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_OS2) && !defined(__CYGWIN32__) && (!defined(OPENSSL_SYS_VMS) || defined(gmtime_r)) && !defined(OPENSSL_SYS_MACOSX) && !defined(OPENSSL_SYS_SUNOS) | 79 | #if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_OS2) && (!defined(OPENSSL_SYS_VMS) || defined(gmtime_r)) && !defined(OPENSSL_SYS_MACOSX) && !defined(OPENSSL_SYS_SUNOS) |
| 77 | /* should return &data, but doesn't on some systems, | 80 | /* should return &data, but doesn't on some systems, |
| 78 | so we don't even look at the return value */ | 81 | so we don't even look at the return value */ |
| 79 | gmtime_r(timer,result); | 82 | gmtime_r(timer,result); |
| @@ -214,4 +217,150 @@ struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) | |||
| 214 | } | 217 | } |
| 215 | #endif | 218 | #endif |
| 216 | return ts; | 219 | return ts; |
| 217 | } | 220 | } |
| 221 | |||
| 222 | /* Take a tm structure and add an offset to it. This avoids any OS issues | ||
| 223 | * with restricted date types and overflows which cause the year 2038 | ||
| 224 | * problem. | ||
| 225 | */ | ||
| 226 | |||
| 227 | #define SECS_PER_DAY (24 * 60 * 60) | ||
| 228 | |||
| 229 | static long date_to_julian(int y, int m, int d); | ||
| 230 | static void julian_to_date(long jd, int *y, int *m, int *d); | ||
| 231 | |||
| 232 | int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) | ||
| 233 | { | ||
| 234 | int offset_hms, offset_day; | ||
| 235 | long time_jd; | ||
| 236 | int time_year, time_month, time_day; | ||
| 237 | /* split offset into days and day seconds */ | ||
| 238 | offset_day = offset_sec / SECS_PER_DAY; | ||
| 239 | /* Avoid sign issues with % operator */ | ||
| 240 | offset_hms = offset_sec - (offset_day * SECS_PER_DAY); | ||
| 241 | offset_day += off_day; | ||
| 242 | /* Add current time seconds to offset */ | ||
| 243 | offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; | ||
| 244 | /* Adjust day seconds if overflow */ | ||
| 245 | if (offset_hms >= SECS_PER_DAY) | ||
| 246 | { | ||
| 247 | offset_day++; | ||
| 248 | offset_hms -= SECS_PER_DAY; | ||
| 249 | } | ||
| 250 | else if (offset_hms < 0) | ||
| 251 | { | ||
| 252 | offset_day--; | ||
| 253 | offset_hms += SECS_PER_DAY; | ||
| 254 | } | ||
| 255 | |||
| 256 | /* Convert date of time structure into a Julian day number. | ||
| 257 | */ | ||
| 258 | |||
| 259 | time_year = tm->tm_year + 1900; | ||
| 260 | time_month = tm->tm_mon + 1; | ||
| 261 | time_day = tm->tm_mday; | ||
| 262 | |||
| 263 | time_jd = date_to_julian(time_year, time_month, time_day); | ||
| 264 | |||
| 265 | /* Work out Julian day of new date */ | ||
| 266 | time_jd += offset_day; | ||
| 267 | |||
| 268 | if (time_jd < 0) | ||
| 269 | return 0; | ||
| 270 | |||
| 271 | /* Convert Julian day back to date */ | ||
| 272 | |||
| 273 | julian_to_date(time_jd, &time_year, &time_month, &time_day); | ||
| 274 | |||
| 275 | if (time_year < 1900 || time_year > 9999) | ||
| 276 | return 0; | ||
| 277 | |||
| 278 | /* Update tm structure */ | ||
| 279 | |||
| 280 | tm->tm_year = time_year - 1900; | ||
| 281 | tm->tm_mon = time_month - 1; | ||
| 282 | tm->tm_mday = time_day; | ||
| 283 | |||
| 284 | tm->tm_hour = offset_hms / 3600; | ||
| 285 | tm->tm_min = (offset_hms / 60) % 60; | ||
| 286 | tm->tm_sec = offset_hms % 60; | ||
| 287 | |||
| 288 | return 1; | ||
| 289 | |||
| 290 | } | ||
| 291 | |||
| 292 | /* Convert date to and from julian day | ||
| 293 | * Uses Fliegel & Van Flandern algorithm | ||
| 294 | */ | ||
| 295 | static long date_to_julian(int y, int m, int d) | ||
| 296 | { | ||
| 297 | return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + | ||
| 298 | (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - | ||
| 299 | (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + | ||
| 300 | d - 32075; | ||
| 301 | } | ||
| 302 | |||
| 303 | static void julian_to_date(long jd, int *y, int *m, int *d) | ||
| 304 | { | ||
| 305 | long L = jd + 68569; | ||
| 306 | long n = (4 * L) / 146097; | ||
| 307 | long i, j; | ||
| 308 | |||
| 309 | L = L - (146097 * n + 3) / 4; | ||
| 310 | i = (4000 * (L + 1)) / 1461001; | ||
| 311 | L = L - (1461 * i) / 4 + 31; | ||
| 312 | j = (80 * L) / 2447; | ||
| 313 | *d = L - (2447 * j) / 80; | ||
| 314 | L = j / 11; | ||
| 315 | *m = j + 2 - (12 * L); | ||
| 316 | *y = 100 * (n - 49) + i + L; | ||
| 317 | } | ||
| 318 | |||
| 319 | #ifdef OPENSSL_TIME_TEST | ||
| 320 | |||
| 321 | #include <stdio.h> | ||
| 322 | |||
| 323 | /* Time checking test code. Check times are identical for a wide range of | ||
| 324 | * offsets. This should be run on a machine with 64 bit time_t or it will | ||
| 325 | * trigger the very errors the routines fix. | ||
| 326 | */ | ||
| 327 | |||
| 328 | int main(int argc, char **argv) | ||
| 329 | { | ||
| 330 | long offset; | ||
| 331 | for (offset = 0; offset < 1000000; offset++) | ||
| 332 | { | ||
| 333 | check_time(offset); | ||
| 334 | check_time(-offset); | ||
| 335 | check_time(offset * 1000); | ||
| 336 | check_time(-offset * 1000); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | int check_time(long offset) | ||
| 341 | { | ||
| 342 | struct tm tm1, tm2; | ||
| 343 | time_t t1, t2; | ||
| 344 | time(&t1); | ||
| 345 | t2 = t1 + offset; | ||
| 346 | OPENSSL_gmtime(&t2, &tm2); | ||
| 347 | OPENSSL_gmtime(&t1, &tm1); | ||
| 348 | OPENSSL_gmtime_adj(&tm1, 0, offset); | ||
| 349 | if ((tm1.tm_year == tm2.tm_year) && | ||
| 350 | (tm1.tm_mon == tm2.tm_mon) && | ||
| 351 | (tm1.tm_mday == tm2.tm_mday) && | ||
| 352 | (tm1.tm_hour == tm2.tm_hour) && | ||
| 353 | (tm1.tm_min == tm2.tm_min) && | ||
| 354 | (tm1.tm_sec == tm2.tm_sec)) | ||
| 355 | return 1; | ||
| 356 | fprintf(stderr, "TIME ERROR!!\n"); | ||
| 357 | fprintf(stderr, "Time1: %d/%d/%d, %d:%02d:%02d\n", | ||
| 358 | tm2.tm_mday, tm2.tm_mon + 1, tm2.tm_year + 1900, | ||
| 359 | tm2.tm_hour, tm2.tm_min, tm2.tm_sec); | ||
| 360 | fprintf(stderr, "Time2: %d/%d/%d, %d:%02d:%02d\n", | ||
| 361 | tm1.tm_mday, tm1.tm_mon + 1, tm1.tm_year + 1900, | ||
| 362 | tm1.tm_hour, tm1.tm_min, tm1.tm_sec); | ||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | #endif | ||
