示例#1
0
int
main(int argc, char **argv)
{
  uint32_t *time_map;
  struct tlsdate_time start_time, end_time, warp_time;
  int status;
  pid_t ssl_child;
  long long rt_time_ms;
  uint32_t server_time_s;
  int setclock;
  int showtime;
  int showtime_raw;
  int timewarp;
  int leap;
  int http;

  if (argc != 13)
    return 1;
  host = argv[1];
  hostname_to_verify = argv[1];
  port = argv[2];
  protocol = argv[3];
  ca_cert_container = argv[6];
  ca_racket = (0 != strcmp ("unchecked", argv[4]));
  verbose = (0 != strcmp ("quiet", argv[5]));
  verbose_debug = (0 != strcmp ("verbose", argv[5]));
  setclock = (0 == strcmp ("setclock", argv[7]));
  showtime = (0 == strcmp ("showtime", argv[8]));
  showtime_raw = (0 == strcmp ("showtime=raw", argv[8]));
  timewarp = (0 == strcmp ("timewarp", argv[9]));
  leap = (0 == strcmp ("leapaway", argv[10]));
  proxy = (0 == strcmp ("none", argv[11]) ? NULL : argv[11]);
  http = (0 == (strcmp("http", argv[12])));

  /* Initalize warp_time with RECENT_COMPILE_DATE */
  clock_init_time(&warp_time, RECENT_COMPILE_DATE, 0);

  verb ("V: RECENT_COMPILE_DATE is %lu.%06lu",
       (unsigned long) CLOCK_SEC(&warp_time),
       (unsigned long) CLOCK_USEC(&warp_time));

  if (1 != timewarp)
  {
    verb ("V: we'll do the time warp another time - we're not setting clock");
  }

  /* We are not going to set the clock, thus no need to stay root */
  if (0 == setclock && 0 == timewarp)
  {
    verb ("V: attemping to drop administrator privileges");
    drop_privs_to (UNPRIV_USER, UNPRIV_GROUP);
  }

  // We cast the mmap value to remove this error when compiling with g++:
  // src/tlsdate-helper.c: In function ‘int main(int, char**)’:
  // src/tlsdate-helper.c:822:41: error: invalid conversion from ‘void*’ to ‘uint32_t
  time_map = (uint32_t *) mmap (NULL, sizeof (uint32_t),
       PROT_READ | PROT_WRITE,
       MAP_SHARED | MAP_ANONYMOUS, -1, 0);
   if (MAP_FAILED == time_map)
  {
    fprintf (stderr, "mmap failed: %s",
             strerror (errno));
    return 1;
  }

  /* Get the current time from the system clock. */
  if (0 != clock_get_real_time(&start_time))
  {
    die ("Failed to read current time of day: %s", strerror (errno));
  }

  verb ("V: time is currently %lu.%06lu",
       (unsigned long) CLOCK_SEC(&start_time),
       (unsigned long) CLOCK_NSEC(&start_time));

  if (((unsigned long) CLOCK_SEC(&start_time)) < ((unsigned long) CLOCK_SEC(&warp_time)))
  {
    verb ("V: local clock time is less than RECENT_COMPILE_DATE");
    if (timewarp)
    {
      verb ("V: Attempting to warp local clock into the future");
      if (0 != clock_set_real_time(&warp_time))
      {
        die ("setting time failed: %s (Attempted to set clock to %lu.%06lu)",
        strerror (errno),
        (unsigned long) CLOCK_SEC(&warp_time),
        (unsigned long) CLOCK_SEC(&warp_time));
      }
      if (0 != clock_get_real_time(&start_time))
      {
        die ("Failed to read current time of day: %s", strerror (errno));
      }
      verb ("V: time is currently %lu.%06lu",
           (unsigned long) CLOCK_SEC(&start_time),
           (unsigned long) CLOCK_NSEC(&start_time));
      verb ("V: It's just a step to the left...");
    }
  } else {
    verb ("V: time is greater than RECENT_COMPILE_DATE");
  }

  /* initialize to bogus value, just to be on the safe side */
  *time_map = 0;

  /* Run SSL interaction in separate process (and not as 'root') */
  ssl_child = fork ();
  if (-1 == ssl_child)
    die ("fork failed: %s", strerror (errno));
  if (0 == ssl_child)
  {
    drop_privs_to (UNPRIV_USER, UNPRIV_GROUP);
    run_ssl (time_map, leap, http);
    (void) munmap (time_map, sizeof (uint32_t));
    _exit (0);
  }
  if (ssl_child != platform->process_wait (ssl_child, &status, 1))
    die ("waitpid failed: %s", strerror (errno));
  if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)) ))
    die ("child process failed in SSL handshake");

  if (0 != clock_get_real_time(&end_time))
    die ("Failed to read current time of day: %s", strerror (errno));

  /* calculate RTT */
  rt_time_ms = (CLOCK_SEC(&end_time) - CLOCK_SEC(&start_time)) * 1000 + (CLOCK_USEC(&end_time) - CLOCK_USEC(&start_time)) / 1000;
  if (rt_time_ms < 0)
    rt_time_ms = 0; /* non-linear time... */
#ifdef USE_POLARSSL
  server_time_s = *time_map;
#else
  server_time_s = ntohl (*time_map);
#endif
  // We should never have a time_map of zero here;
  // It either stayed zero or we have a false ticker.
  if ( 0 == server_time_s )
    die ("child process failed to update time map; weird platform issues?");
  munmap (time_map, sizeof (uint32_t));

  verb ("V: server time %u (difference is about %d s) was fetched in %lld ms",
  (unsigned int) server_time_s,
  CLOCK_SEC(&start_time) - server_time_s,
  rt_time_ms);

  /* warning if the handshake took too long */
  if (rt_time_ms > TLS_RTT_UNREASONABLE) {
    die ("the TLS handshake took more than %d msecs - consider using a different " \
      "server or run it again", TLS_RTT_UNREASONABLE);
  }
  if (rt_time_ms > TLS_RTT_THRESHOLD) {
    verb ("V: the TLS handshake took more than %d msecs - consider using a different " \
      "server or run it again", TLS_RTT_THRESHOLD);
  }

  if (showtime_raw)
  {
    fwrite(&server_time_s, sizeof(server_time_s), 1, stdout);
  }

  if (showtime)
  {
     struct tm  ltm;
     time_t tim = server_time_s;
     char       buf[256];

     localtime_r(&tim, &ltm);
     if (0 == strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %Z %Y", &ltm))
     {
       die ("strftime returned 0");
     }
     fprintf(stdout, "%s\n", buf);
  }

  /* finally, actually set the time */
  if (setclock)
  {
    struct tlsdate_time server_time;

    clock_init_time(&server_time,  server_time_s + (rt_time_ms / 2 / 1000),
                   (rt_time_ms / 2) % 1000);

    // We should never receive a time that is before the time we were last
    // compiled; we subscribe to the linear theory of time for this program
    // and this program alone!
    if (CLOCK_SEC(&server_time) >= MAX_REASONABLE_TIME)
      die("remote server is a false ticker from the future!");
    if (CLOCK_SEC(&server_time) <= RECENT_COMPILE_DATE)
      die ("remote server is a false ticker!");
    if (0 != clock_set_real_time(&server_time))
      die ("setting time failed: %s (Difference from server is about %d s)",
     strerror (errno),
     CLOCK_SEC(&start_time) - server_time_s);
    verb ("V: setting time succeeded");
  }
  return 0;
}
示例#2
0
int
main(int argc, char **argv)
{
  uint32_t *time_map;
  struct tlsdate_time start_time, end_time, warp_time;
  int status;
  pid_t ssl_child;
  long long rt_time_ms;
  uint32_t server_time_s;
  int setclock;
  int showtime;
  int timewarp;
  int leap;

  if (argc != 11)
    return 1;
  host = argv[1];
  port = argv[2];
  protocol = argv[3];
  certdir = argv[6];
  ca_racket = (0 != strcmp ("unchecked", argv[4]));
  verbose = (0 != strcmp ("quiet", argv[5]));
  setclock = (0 == strcmp ("setclock", argv[7]));
  showtime = (0 == strcmp ("showtime", argv[8]));
  timewarp = (0 == strcmp ("timewarp", argv[9]));
  leap = (0 == strcmp ("leapaway", argv[10]));

  clock_init_time(&warp_time, RECENT_COMPILE_DATE, 0);

  if (timewarp)
  {
    verb ("V: RECENT_COMPILE_DATE is %lu.%06lu\n",
         (unsigned long) CLOCK_SEC(&warp_time),
         (unsigned long) CLOCK_USEC(&warp_time));
  }

  /* We are not going to set the clock, thus no need to stay root */
  if (0 == setclock && 0 == timewarp)
  {
    become_nobody ();
  }

  time_map = mmap (NULL, sizeof (uint32_t),
       PROT_READ | PROT_WRITE,
       MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  if (MAP_FAILED == time_map)
  {
    fprintf (stderr, "mmap failed: %s\n",
             strerror (errno));
    return 1;
  }

  /* Get the current time from the system clock. */
  if (0 != clock_get_real_time(&start_time))
  {
    die ("Failed to read current time of day: %s\n", strerror (errno));
  }

  verb ("V: time is currently %lu.%06lu\n",
       (unsigned long) CLOCK_SEC(&start_time),
       (unsigned long) CLOCK_NSEC(&start_time));

  if (((unsigned long) CLOCK_SEC(&start_time)) < ((unsigned long) CLOCK_SEC(&warp_time)))
  {
    verb ("V: local clock time is less than RECENT_COMPILE_DATE\n");
    if (timewarp)
    {
      verb ("V: Attempting to warp local clock into the future\n");
      if (0 != clock_set_real_time(&warp_time))
      {
        die ("setting time failed: %s (Attempted to set clock to %lu.%06lu)\n",
        strerror (errno),
        (unsigned long) CLOCK_SEC(&warp_time),
        (unsigned long) CLOCK_SEC(&warp_time));
      }
      if (0 != clock_get_real_time(&start_time))
      {
        die ("Failed to read current time of day: %s\n", strerror (errno));
      }
      verb ("V: time is currently %lu.%06lu\n",
           (unsigned long) CLOCK_SEC(&start_time),
           (unsigned long) CLOCK_NSEC(&start_time));
      verb ("V: It's just a step to the left...\n");
    }
  } else {
    verb ("V: time is greater than RECENT_COMPILE_DATE\n");
  }

  /* initialize to bogus value, just to be on the safe side */
  *time_map = 0;

  /* Run SSL interaction in separate process (and not as 'root') */
  ssl_child = fork ();
  if (-1 == ssl_child)
    die ("fork failed: %s\n", strerror (errno));
  if (0 == ssl_child)
  {
    become_nobody ();
    run_ssl (time_map, leap);
    (void) munmap (time_map, sizeof (uint32_t));
    _exit (0);
  } 
  if (ssl_child != waitpid (ssl_child, &status, 0))
    die ("waitpid failed: %s\n", strerror (errno));
  if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)) ))
    die ("child process failed in SSL handshake\n");

  if (0 != clock_get_real_time(&end_time))
    die ("Failed to read current time of day: %s\n", strerror (errno));
  
  /* calculate RTT */
  rt_time_ms = (CLOCK_SEC(&end_time) - CLOCK_SEC(&start_time)) * 1000 + (CLOCK_USEC(&end_time) - CLOCK_USEC(&start_time)) / 1000;
  if (rt_time_ms < 0)
    rt_time_ms = 0; /* non-linear time... */
  server_time_s = ntohl (*time_map);
  munmap (time_map, sizeof (uint32_t));

  verb ("V: server time %u (difference is about %d s) was fetched in %lld ms\n",
  (unsigned int) server_time_s,
  CLOCK_SEC(&start_time) - server_time_s,
  rt_time_ms);

  /* warning if the handshake took too long */
  if (rt_time_ms > TLS_RTT_THRESHOLD) {
    verb ("V: the TLS handshake took more than %d msecs - consider using a different " \
      "server or run it again\n", TLS_RTT_THRESHOLD);
  }

  if (showtime)
  {
     struct tm  ltm;
     time_t tim = server_time_s;
     char       buf[256];

     localtime_r(&tim, &ltm);
     (void) strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %Z %Y", &ltm);
     fprintf(stdout, "%s\n", buf);
  }

  /* finally, actually set the time */
  if (setclock)
  {
    struct tlsdate_time server_time;

    clock_init_time(&server_time,  server_time_s + (rt_time_ms / 2 / 1000),
                   (rt_time_ms / 2) % 1000);

    // We should never receive a time that is before the time we were last
    // compiled; we subscribe to the linear theory of time for this program
    // and this program alone!
    if (CLOCK_SEC(&server_time) >= MAX_REASONABLE_TIME)
      die("remote server is a false ticker from the future!\n");
    if (CLOCK_SEC(&server_time) <= RECENT_COMPILE_DATE)
      die ("remote server is a false ticker!\n");
    if (0 != clock_set_real_time(&server_time))
      die ("setting time failed: %s (Difference from server is about %d)\n",
     strerror (errno),
     CLOCK_SEC(&start_time) - server_time_s);
    verb ("V: setting time succeeded\n");
  }
  return 0;
}