~ubuntu-branches/ubuntu/karmic/gnupg2/karmic-security

« back to all changes in this revision

Viewing changes to common/gettime.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* gettime.c - Wrapper for time functions
2
 
 *      Copyright (C) 1998, 2002 Free Software Foundation, Inc.
 
2
 *      Copyright (C) 1998, 2002, 2007 Free Software Foundation, Inc.
3
3
 *
4
4
 * This file is part of GnuPG.
5
5
 *
6
6
 * GnuPG is free software; you can redistribute it and/or modify
7
7
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * the Free Software Foundation; either version 3 of the License, or
9
9
 * (at your option) any later version.
10
10
 *
11
11
 * GnuPG is distributed in the hope that it will be useful,
14
14
 * GNU General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
18
 */
20
19
 
21
20
#include <config.h>
22
21
#include <stdlib.h>
23
22
#include <time.h>
 
23
#include <ctype.h>
24
24
#ifdef HAVE_LANGINFO_H
25
25
#include <langinfo.h>
26
26
#endif
30
30
static unsigned long timewarp;
31
31
static enum { NORMAL = 0, FROZEN, FUTURE, PAST } timemode;
32
32
 
 
33
/* Correction used to map to real Julian days. */
 
34
#define JD_DIFF 1721060L
 
35
 
 
36
 
33
37
/* Wrapper for the time(3).  We use this here so we can fake the time
34
38
   for tests */
35
39
time_t 
65
69
#else
66
70
      tp = gmtime (&atime);
67
71
#endif
68
 
      sprintf (timebuf,"%04d%02d%02dT%02d%02d%02d",
69
 
               1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
70
 
               tp->tm_hour, tp->tm_min, tp->tm_sec);
 
72
      snprintf (timebuf, 16, "%04d%02d%02dT%02d%02d%02d",
 
73
                1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
 
74
                tp->tm_hour, tp->tm_min, tp->tm_sec);
71
75
    }
72
76
}
73
77
 
74
78
 
75
 
/* set the time to NEWTIME so that gnupg_get_time returns a time
 
79
/* Set the time to NEWTIME so that gnupg_get_time returns a time
76
80
   starting with this one.  With FREEZE set to 1 the returned time
77
81
   will never change.  Just for completeness, a value of (time_t)-1
78
 
   for NEWTIME gets you back to rality. Note that this is obviously
 
82
   for NEWTIME gets you back to reality.  Note that this is obviously
79
83
   not thread-safe but this is not required. */
80
84
void
81
85
gnupg_set_time (time_t newtime, int freeze)
165
169
    return stamp;
166
170
}
167
171
 
 
172
/* Scan am ISO timestamp and return an Epoch based timestamp.  The only
 
173
   supported format is "yyyymmddThhmmss" delimited by white space, nul, a
 
174
   colon or a comma.  Returns (time_t)(-1) for an invalid string.  */
 
175
time_t
 
176
isotime2epoch (const char *string)
 
177
{
 
178
  const char *s;
 
179
  int year, month, day, hour, minu, sec;
 
180
  struct tm tmbuf;
 
181
  int i;
 
182
 
 
183
  if (!*string)
 
184
    return (time_t)(-1);
 
185
  for (s=string, i=0; i < 8; i++, s++)
 
186
    if (!digitp (s))
 
187
      return (time_t)(-1);
 
188
  if (*s != 'T')
 
189
      return (time_t)(-1);
 
190
  for (s++, i=9; i < 15; i++, s++)
 
191
    if (!digitp (s))
 
192
      return (time_t)(-1);
 
193
  if ( !(!*s || (isascii (*s) && isspace(*s)) || *s == ':' || *s == ','))
 
194
    return (time_t)(-1);  /* Wrong delimiter.  */
 
195
 
 
196
  year  = atoi_4 (string);
 
197
  month = atoi_2 (string + 4);
 
198
  day   = atoi_2 (string + 6);
 
199
  hour  = atoi_2 (string + 9);
 
200
  minu  = atoi_2 (string + 11);
 
201
  sec   = atoi_2 (string + 13);
 
202
 
 
203
  /* Basic checks.  */
 
204
  if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31
 
205
      || hour > 23 || minu > 59 || sec > 61 )
 
206
    return (time_t)(-1);
 
207
 
 
208
  memset (&tmbuf, 0, sizeof tmbuf);
 
209
  tmbuf.tm_sec  = sec;
 
210
  tmbuf.tm_min  = minu;
 
211
  tmbuf.tm_hour = hour;
 
212
  tmbuf.tm_mday = day;
 
213
  tmbuf.tm_mon  = month-1;
 
214
  tmbuf.tm_year = year - 1900;
 
215
  tmbuf.tm_isdst = -1;
 
216
  return timegm (&tmbuf);
 
217
}
 
218
 
 
219
 
 
220
/* Convert an Epoch time to an iso time stamp. */
 
221
void
 
222
epoch2isotime (gnupg_isotime_t timebuf, time_t atime)
 
223
{
 
224
  if (atime < 0)
 
225
    *timebuf = 0;
 
226
  else 
 
227
    {
 
228
      struct tm *tp;
 
229
#ifdef HAVE_GMTIME_R
 
230
      struct tm tmbuf;
 
231
      
 
232
      tp = gmtime_r (&atime, &tmbuf);
 
233
#else
 
234
      tp = gmtime (&atime);
 
235
#endif
 
236
      snprintf (timebuf, 16, "%04d%02d%02dT%02d%02d%02d",
 
237
                1900 + tp->tm_year, tp->tm_mon+1, tp->tm_mday,
 
238
                tp->tm_hour, tp->tm_min, tp->tm_sec);
 
239
    }
 
240
}
 
241
 
 
242
 
 
243
 
168
244
 
169
245
u32
170
246
add_days_to_timestamp( u32 stamp, u16 days )
201
277
}
202
278
 
203
279
 
204
 
/****************
 
280
/*
205
281
 * Note: this function returns GMT
206
282
 */
207
283
const char *
222
298
    return buffer;
223
299
}
224
300
 
 
301
 
 
302
/*
 
303
 * Note: this function returns GMT
 
304
 */
 
305
const char *
 
306
isotimestamp (u32 stamp)
 
307
{
 
308
  static char buffer[25+5];
 
309
  struct tm *tp;
 
310
  time_t atime = stamp;
 
311
  
 
312
  if (atime < 0)
 
313
    {
 
314
      strcpy (buffer, "????" "-??" "-??" " " "??" ":" "??" ":" "??");
 
315
    }
 
316
  else
 
317
    {
 
318
      tp = gmtime ( &atime );
 
319
      sprintf (buffer,"%04d-%02d-%02d %02d:%02d:%02d",
 
320
               1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
 
321
               tp->tm_hour, tp->tm_min, tp->tm_sec);
 
322
    }
 
323
  return buffer;
 
324
}
 
325
 
 
326
 
225
327
/****************
226
328
 * Note: this function returns local time
227
329
 */
265
367
 
266
368
 
267
369
 
268
 
 
269
 
 
270
 
 
271
 
 
272
 
 
273
 
 
274
 
 
275
 
 
276
 
 
277
 
 
278
 
 
 
370
static int
 
371
days_per_year (int y)
 
372
{
 
373
  int s ;
 
374
 
 
375
  s = !(y % 4);
 
376
  if ( !(y % 100))
 
377
    if ((y%400))
 
378
      s = 0;
 
379
  return s ? 366 : 365;
 
380
}
 
381
 
 
382
static int
 
383
days_per_month (int y, int m)
 
384
{
 
385
  int s;
 
386
    
 
387
  switch(m)
 
388
    {
 
389
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
 
390
      return 31 ;
 
391
    case 2:
 
392
      s = !(y % 4);
 
393
      if (!(y % 100))
 
394
        if ((y % 400))
 
395
          s = 0;
 
396
      return s? 29 : 28 ;
 
397
    case 4: case 6: case 9: case 11:
 
398
      return 30;
 
399
    }
 
400
  BUG();
 
401
}
 
402
 
 
403
 
 
404
/* Convert YEAR, MONTH and DAY into the Julian date.  We assume that
 
405
   it is already noon; we dont; support dates before 1582-10-15. */
 
406
static unsigned long
 
407
date2jd (int year, int month, int day)
 
408
{
 
409
  unsigned long jd;
 
410
 
 
411
  jd = 365L * year + 31 * (month-1) + day + JD_DIFF;
 
412
  if (month < 3)
 
413
    year-- ;
 
414
  else
 
415
    jd -= (4 * month + 23) / 10;
 
416
 
 
417
  jd += year / 4 - ((year / 100 + 1) *3) / 4;
 
418
 
 
419
  return jd ;
 
420
}
 
421
 
 
422
/* Convert a Julian date back to YEAR, MONTH and DAY.  Return day of
 
423
   the year or 0 on error.  This function uses some more or less
 
424
   arbitrary limits, most important is that days before 1582 are not
 
425
   supported. */
 
426
static int
 
427
jd2date (unsigned long jd, int *year, int *month, int *day)
 
428
{
 
429
  int y, m, d;
 
430
  long delta;
 
431
 
 
432
  if (!jd)
 
433
    return 0 ;
 
434
  if (jd < 1721425 || jd > 2843085)
 
435
    return 0;
 
436
 
 
437
  y = (jd - JD_DIFF) / 366;
 
438
  d = m = 1;
 
439
 
 
440
  while ((delta = jd - date2jd (y, m, d)) > days_per_year (y))
 
441
    y++;
 
442
 
 
443
  m = (delta / 31) + 1;
 
444
  while( (delta = jd - date2jd (y, m, d)) > days_per_month (y,m))
 
445
    if (++m > 12)
 
446
      { 
 
447
        m = 1;
 
448
        y++;
 
449
      }
 
450
 
 
451
  d = delta + 1 ;
 
452
  if (d > days_per_month (y, m))
 
453
    { 
 
454
      d = 1;
 
455
      m++;
 
456
    }
 
457
  if (m > 12)
 
458
    { 
 
459
      m = 1;
 
460
      y++;
 
461
    }
 
462
 
 
463
  if (year)
 
464
    *year = y;
 
465
  if (month)
 
466
    *month = m;
 
467
  if (day)
 
468
    *day = d ;
 
469
 
 
470
  return (jd - date2jd (y, 1, 1)) + 1;
 
471
}
 
472
 
 
473
 
 
474
/* Check that the 15 bytes in ATIME represent a valid ISO time.  Note
 
475
   that this function does not expect a string but a plain 15 byte
 
476
   isotime buffer. */
 
477
gpg_error_t
 
478
check_isotime (const gnupg_isotime_t atime)
 
479
{
 
480
  int i;
 
481
  const char *s;
 
482
 
 
483
  if (!*atime)
 
484
    return gpg_error (GPG_ERR_NO_VALUE);
 
485
  
 
486
  for (s=atime, i=0; i < 8; i++, s++)
 
487
    if (!digitp (s))
 
488
      return gpg_error (GPG_ERR_INV_TIME);
 
489
  if (*s != 'T')
 
490
      return gpg_error (GPG_ERR_INV_TIME);
 
491
  for (s++, i=9; i < 15; i++, s++)
 
492
    if (!digitp (s))
 
493
      return gpg_error (GPG_ERR_INV_TIME);
 
494
  return 0;
 
495
}
 
496
 
 
497
 
 
498
 
 
499
/* Add SECONDS to ATIME.  SECONDS may not be negative and is limited
 
500
   to about the equivalent of 62 years which should be more then
 
501
   enough for our purposes. */
 
502
gpg_error_t
 
503
add_seconds_to_isotime (gnupg_isotime_t atime, int nseconds)
 
504
{
 
505
  gpg_error_t err;
 
506
  int year, month, day, hour, minute, sec, ndays;
 
507
  unsigned long jd;
 
508
 
 
509
  err = check_isotime (atime);
 
510
  if (err)
 
511
    return err;
 
512
 
 
513
  if (nseconds < 0 || nseconds >= (0x7fffffff - 61) )
 
514
    return gpg_error (GPG_ERR_INV_VALUE);
 
515
 
 
516
  year  = atoi_4 (atime+0);
 
517
  month = atoi_2 (atime+4);
 
518
  day   = atoi_2 (atime+6);
 
519
  hour  = atoi_2 (atime+9);
 
520
  minute= atoi_2 (atime+11);
 
521
  sec   = atoi_2 (atime+13);
 
522
 
 
523
  if (year <= 1582) /* The julian date functions don't support this. */
 
524
    return gpg_error (GPG_ERR_INV_VALUE); 
 
525
 
 
526
  sec    += nseconds;
 
527
  minute += sec/60;
 
528
  sec    %= 60;
 
529
  hour   += minute/60;
 
530
  minute %= 60;
 
531
  ndays  = hour/24;
 
532
  hour   %= 24;
 
533
  
 
534
  jd = date2jd (year, month, day) + ndays;
 
535
  jd2date (jd, &year, &month, &day);
 
536
 
 
537
  if (year > 9999 || month > 12 || day > 31
 
538
      || year < 0 || month < 1 || day < 1)
 
539
    return gpg_error (GPG_ERR_INV_VALUE); 
 
540
    
 
541
  snprintf (atime, 16, "%04d%02d%02dT%02d%02d%02d",
 
542
            year, month, day, hour, minute, sec);
 
543
  return 0;
 
544
}
 
545
 
 
546
 
 
547
gpg_error_t
 
548
add_days_to_isotime (gnupg_isotime_t atime, int ndays)
 
549
{
 
550
  gpg_error_t err;
 
551
  int year, month, day, hour, minute, sec;
 
552
  unsigned long jd;
 
553
 
 
554
  err = check_isotime (atime);
 
555
  if (err)
 
556
    return err;
 
557
 
 
558
  if (ndays < 0 || ndays >= 9999*366 )
 
559
    return gpg_error (GPG_ERR_INV_VALUE);
 
560
 
 
561
  year  = atoi_4 (atime+0);
 
562
  month = atoi_2 (atime+4);
 
563
  day   = atoi_2 (atime+6);
 
564
  hour  = atoi_2 (atime+9);
 
565
  minute= atoi_2 (atime+11);
 
566
  sec   = atoi_2 (atime+13);
 
567
 
 
568
  if (year <= 1582) /* The julian date functions don't support this. */
 
569
    return gpg_error (GPG_ERR_INV_VALUE); 
 
570
 
 
571
  jd = date2jd (year, month, day) + ndays;
 
572
  jd2date (jd, &year, &month, &day);
 
573
 
 
574
  if (year > 9999 || month > 12 || day > 31
 
575
      || year < 0 || month < 1 || day < 1)
 
576
    return gpg_error (GPG_ERR_INV_VALUE); 
 
577
    
 
578
  snprintf (atime, 16, "%04d%02d%02dT%02d%02d%02d",
 
579
            year, month, day, hour, minute, sec);
 
580
  return 0;
 
581
}