Beispiel #1
0
int
main(int argc, char **argv)
{
  uint32_t *time_map;
  struct timeval start_timeval;
  struct timeval end_timeval;
  int status;
  pid_t ssl_child;
  long long rt_time_ms;
  uint32_t server_time_s;

  if (argc != 6)
    return 1;
  host = argv[1];
  port = argv[2];
  protocol = argv[3];
  ca_racket = (0 != strcmp ("unchecked", argv[4]));
  verbose = (0 != strcmp ("quiet", argv[5]));

  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 != gettimeofday(&start_timeval, NULL))
    die ("Failed to read current time of day: %s\n", strerror (errno));
  verb ("V: time is currently %lu.%06lu\n",
	(unsigned long)start_timeval.tv_sec, 
	(unsigned long)start_timeval.tv_usec);  

  /* 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);
    (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 != gettimeofday(&end_timeval, NULL))
    die ("Failed to read current time of day: %s\n", strerror (errno));
  
  /* calculate RTT */
  rt_time_ms = (end_timeval.tv_sec - start_timeval.tv_sec) * 1000 + (end_timeval.tv_usec - start_timeval.tv_usec) / 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,
	start_timeval.tv_sec - server_time_s,
	rt_time_ms);

  /* finally, actually set the time */
  {
    struct timeval server_time;

    /* correct server time by half of RTT */
    server_time.tv_sec = server_time_s + (rt_time_ms / 2 / 1000);
    server_time.tv_usec = (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 (server_time.tv_sec >= MAX_REASONABLE_TIME)
      die("remote server is a false ticker from the future!");
    if (server_time.tv_sec <= RECENT_COMPILE_DATE)
      die ("remote server is a false ticker!");
    if (0 != settimeofday(&server_time, NULL))
      die ("setting time failed: %s\n", strerror (errno));
  }
  verb ("V: setting time succeeded\n");
  return 0;
}
Beispiel #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;
}