Home | History | Annotate | Download | only in src
      1 /* Copyright (c) 2012, Jacob Appelbaum.
      2  * Copyright (c) 2012, The Tor Project, Inc.
      3  * Copyright (c) 2012, Christian Grothoff. */
      4 /* See LICENSE for licensing information */
      5 /*
      6                     This file contains the license for tlsdate,
      7         a free software project to set your system clock securely.
      8 
      9         It also lists the licenses for other components used by tlsdate.
     10 
     11       For more information about tlsdate, see https://github.com/ioerror/tlsdate
     12 
     13              If you got this file as a part of a larger bundle,
     14         there may be other license terms that you should be aware of.
     15 
     16 ===============================================================================
     17 tlsdate is distributed under this license:
     18 
     19 Copyright (c) 2011-2012, Jacob Appelbaum <jacob (at) appelbaum.net>
     20 Copyright (c) 2011-2012, The Tor Project, Inc.
     21 
     22 Redistribution and use in source and binary forms, with or without
     23 modification, are permitted provided that the following conditions are
     24 met:
     25 
     26     * Redistributions of source code must retain the above copyright
     27 notice, this list of conditions and the following disclaimer.
     28 
     29     * Redistributions in binary form must reproduce the above
     30 copyright notice, this list of conditions and the following disclaimer
     31 in the documentation and/or other materials provided with the
     32 distribution.
     33 
     34     * Neither the names of the copyright owners nor the names of its
     35 contributors may be used to endorse or promote products derived from
     36 this software without specific prior written permission.
     37 
     38 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     39 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     40 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     41 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     42 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     43 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     44 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     45 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     46 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     47 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     48 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     49 ===============================================================================
     50 If you got tlsdate as a static binary with OpenSSL included, then you should
     51 know:
     52 
     53  "This product includes software developed by the OpenSSL Project for use in
     54   the OpenSSL Toolkit (http://www.openssl.org/)"
     55 
     56 ===============================================================================
     57 */
     58 
     59 /**
     60  * \file tlsdate-helper.c
     61  * \brief Helper program that does the actual work of setting the system clock.
     62  **/
     63 
     64 /*
     65  * tlsdate is a tool for setting the system clock by hand or by communication
     66  * with the network. It does not set the RTC. It is designed to be as secure as
     67  * TLS (RFC 2246) but of course the security of TLS is often reduced to
     68  * whichever CA racket you believe is trustworthy. By default, tlsdate trusts
     69  * your local CA root store - so any of these companies could assist in a MITM
     70  * attack against you and you'd be screwed.
     71 
     72  * This tool is designed to be run by hand or as a system daemon. It must be
     73  * run as root or otherwise have the proper caps; it will not be able to set
     74  * the system time without running as root or another privileged user.
     75  */
     76 
     77 #include "config.h"
     78 #include "src/tlsdate-helper.h"
     79 #include "src/util.h"
     80 
     81 #ifndef USE_POLARSSL
     82 #include "src/proxy-bio.h"
     83 #else
     84 #include "src/proxy-polarssl.h"
     85 #endif
     86 
     87 #include "src/compat/clock.h"
     88 
     89 #ifndef MAP_ANONYMOUS
     90 #define MAP_ANONYMOUS MAP_ANON
     91 #endif
     92 
     93 #ifdef USE_POLARSSL
     94 #include "polarssl/entropy.h"
     95 #include "polarssl/ctr_drbg.h"
     96 #include "polarssl/ssl.h"
     97 #endif
     98 
     99 static void
    100 validate_proxy_scheme(const char *scheme)
    101 {
    102   if (!strcmp(scheme, "http"))
    103     return;
    104   if (!strcmp(scheme, "socks4"))
    105     return;
    106   if (!strcmp(scheme, "socks5"))
    107     return;
    108   die("invalid proxy scheme");
    109 }
    110 
    111 static void
    112 validate_proxy_host(const char *host)
    113 {
    114   const char *kValid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    115                        "abcdefghijklmnopqrstuvwxyz"
    116                        "0123456789"
    117                        ".-";
    118   if (strspn(host, kValid) != strlen(host))
    119     die("invalid char in host");
    120 }
    121 
    122 static void
    123 validate_proxy_port(const char *port)
    124 {
    125   while (*port)
    126     if (!isdigit((int)(unsigned char)*port++))
    127       die("invalid char in port");
    128 }
    129 
    130 static void
    131 parse_proxy_uri(char *proxy, char **scheme, char **host, char **port)
    132 {
    133   /* Expecting a URI, so: <scheme> '://' <host> ':' <port> */
    134   *scheme = proxy;
    135   proxy = strstr(proxy, "://");
    136   if (!proxy)
    137     die("malformed proxy URI");
    138   *proxy = '\0'; /* terminate scheme string */
    139   proxy += strlen("://");
    140 
    141   *host = proxy;
    142   proxy = strchr(proxy, ':');
    143   if (!proxy)
    144     die("malformed proxy URI");
    145   *proxy++ = '\0';
    146 
    147   *port = proxy;
    148 
    149   validate_proxy_scheme(*scheme);
    150   validate_proxy_host(*host);
    151   validate_proxy_port(*port);
    152 }
    153 
    154 #ifndef USE_POLARSSL
    155 static void
    156 setup_proxy(BIO *ssl)
    157 {
    158   BIO *bio;
    159   char *scheme;
    160   char *proxy_host;
    161   char *proxy_port;
    162 
    163   if (!proxy)
    164     return;
    165   /*
    166    * grab the proxy's host and port out of the URI we have for it. We want the
    167    * underlying connect BIO to connect to this, not the target host and port, so
    168    * we squirrel away the target host and port in the proxy BIO (as the proxy
    169    * target) and swap out the connect BIO's target host and port so it'll
    170    * connect to the proxy instead.
    171    */
    172   parse_proxy_uri(proxy, &scheme, &proxy_host, &proxy_port);
    173   bio = BIO_new_proxy();
    174   BIO_proxy_set_type(bio, scheme);
    175   BIO_proxy_set_host(bio, host);
    176   BIO_proxy_set_port(bio, atoi(port));
    177   host = proxy_host;
    178   port = proxy_port;
    179   BIO_push(ssl, bio);
    180 }
    181 
    182 static int
    183 write_all_to_ssl(SSL *ssl, const char *string)
    184 {
    185   int n = (int) strlen(string);
    186   int r;
    187 
    188   while (n) {
    189     r = SSL_write(ssl, string, n);
    190     if (r > 0) {
    191       if (r > n)
    192         return -1;
    193       n -= r;
    194       string += r;
    195     } else {
    196       return 0;
    197     }
    198   }
    199 
    200   return 1;
    201 }
    202 
    203 /* If the string is all nice clean ascii that it's safe to log, return
    204  * it. Otherwise return a placeholder "This is junk" string. */
    205 static const char *
    206 sanitize_string(const char *s)
    207 {
    208   const unsigned char *cp;
    209   for (cp = (const unsigned char *)s; *cp; cp++) {
    210     if (*cp < 32 || *cp >= 127)
    211       return "string with invalid characters";
    212   }
    213   return s;
    214 }
    215 
    216 static int
    217 handle_date_line(const char *dateline, uint32_t *result)
    218 {
    219   int year,mon,day,hour,min,sec;
    220   char month[4];
    221   struct tm tm;
    222   int i;
    223   time_t t;
    224   /* We recognize the three formats in RFC2616, section 3.3.1.  Month
    225      names are always in English.  The formats are:
    226 
    227       Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
    228       Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
    229       Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format
    230 
    231      Note that the first is preferred.
    232    */
    233 
    234   static const char *MONTHS[] =
    235     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    236       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
    237 
    238   if (strncmp("\r\nDate: ", dateline, 8))
    239     return 0;
    240 
    241   dateline += 8;
    242   if (strlen(dateline) > MAX_DATE_LINE_LEN) {
    243     verb("V: The date line was impossibly long.");
    244     return -1;
    245   }
    246   verb("V: The alleged date is <%s>", sanitize_string(dateline));
    247 
    248   while (*dateline == ' ')
    249     ++dateline;
    250   while (*dateline && *dateline != ' ')
    251     ++dateline;
    252   while (*dateline == ' ')
    253     ++dateline;
    254   /* We just skipped over the day of the week. Now we have:*/
    255   if (sscanf(dateline, "%d %3s %d %d:%d:%d",
    256              &day, month, &year, &hour, &min, &sec) == 6 ||
    257       sscanf(dateline, "%d-%3s-%d %d:%d:%d",
    258              &day, month, &year, &hour, &min, &sec) == 6 ||
    259       sscanf(dateline, "%3s %d %d:%d:%d %d",
    260              month, &day, &hour, &min, &sec, &year) == 6) {
    261 
    262     /* Two digit dates are defined to be relative to 1900; all other dates
    263      * are supposed to be represented as four digits. */
    264     if (year < 100)
    265       year += 1900;
    266 
    267     verb("V: Parsed the date: %04d-%s-%02d %02d:%02d:%02d",
    268          year, month, day, hour, min, sec);
    269   } else {
    270     verb("V: Couldn't parse date.");
    271     return -1;
    272   }
    273 
    274   for (i = 0; ; ++i) {
    275     if (!MONTHS[i])
    276       return -2;
    277     if (!strcmp(month, MONTHS[i])) {
    278       mon = i;
    279       break;
    280     }
    281   }
    282 
    283   memset(&tm, 0, sizeof(tm));
    284   tm.tm_year = year - 1900;
    285   tm.tm_mon = mon;
    286   tm.tm_mday = day;
    287   tm.tm_hour = hour;
    288   tm.tm_min = min;
    289   tm.tm_sec = sec;
    290 
    291   t = timegm(&tm);
    292   if (t > ((time_t) 0xffffffff) || t < 0)
    293     return -1;
    294 
    295   *result = (uint32_t) t;
    296 
    297   return 1;
    298 }
    299 
    300 static int
    301 read_http_date_from_ssl(SSL *ssl, uint32_t *result)
    302 {
    303   int n;
    304   char buf[MAX_HTTP_HEADERS_SIZE];
    305   size_t buf_len=0;
    306   char *dateline, *endofline;
    307 
    308   while (buf_len < sizeof(buf)-1) {
    309     n = SSL_read(ssl, buf+buf_len, sizeof(buf)-buf_len-1);
    310     if (n <= 0)
    311       return 0;
    312     buf_len += n;
    313     buf[buf_len] = 0;
    314     verb_debug ("V: read %d bytes.", n, buf);
    315 
    316     dateline = memmem(buf, buf_len, "\r\nDate: ", 8);
    317     if (NULL == dateline)
    318       continue;
    319 
    320     endofline = memmem(dateline+2, buf_len - (dateline-buf+2), "\r\n", 2);
    321     if (NULL == endofline)
    322       continue;
    323 
    324     *endofline = 0;
    325     return handle_date_line(dateline, result);
    326   }
    327   return -2;
    328 }
    329 
    330 /** helper function for 'malloc' */
    331 static void *
    332 xmalloc (size_t size)
    333 {
    334   void *ptr;
    335 
    336   if (0 == size)
    337     die("xmalloc: zero size");
    338 
    339   ptr = malloc(size);
    340   if (NULL == ptr)
    341     die("xmalloc: out of memory (allocating %zu bytes)", size);
    342 
    343   return ptr;
    344 }
    345 
    346 
    347 /** helper function for 'free' */
    348 static void
    349 xfree (void *ptr)
    350 {
    351   if (NULL == ptr)
    352     die("xfree: NULL pointer given as argument");
    353 
    354   free(ptr);
    355 }
    356 
    357 void
    358 openssl_time_callback (const SSL* ssl, int where, int ret)
    359 {
    360   if (where == SSL_CB_CONNECT_LOOP &&
    361       (ssl->state == SSL3_ST_CR_SRVR_HELLO_A || ssl->state == SSL3_ST_CR_SRVR_HELLO_B))
    362   {
    363     // XXX TODO: If we want to trust the remote system for time,
    364     // can we just read that time out of the remote system and if the
    365     // cert verifies, decide that the time is reasonable?
    366     // Such a process seems to indicate that a once valid cert would be
    367     // forever valid - we stopgap that by ensuring it isn't less than
    368     // the latest compiled_time and isn't above max_reasonable_time...
    369     // XXX TODO: Solve eternal question about the Chicken and the Egg...
    370     uint32_t compiled_time = RECENT_COMPILE_DATE;
    371     uint32_t max_reasonable_time = MAX_REASONABLE_TIME;
    372     uint32_t server_time;
    373     verb("V: freezing time for x509 verification");
    374     memcpy(&server_time, ssl->s3->server_random, sizeof(uint32_t));
    375     if (compiled_time < ntohl(server_time)
    376         &&
    377         ntohl(server_time) < max_reasonable_time)
    378     {
    379       verb("V: remote peer provided: %d, preferred over compile time: %d",
    380             ntohl(server_time), compiled_time);
    381       verb("V: freezing time with X509_VERIFY_PARAM_set_time");
    382       X509_VERIFY_PARAM_set_time(ssl->ctx->cert_store->param,
    383                                  (time_t) ntohl(server_time) + 86400);
    384     } else {
    385       die("V: the remote server is a false ticker! server: %d compile: %d",
    386            ntohl(server_time), compiled_time);
    387     }
    388   }
    389 }
    390 
    391 static const char *
    392 key_type_to_str (int key_type)
    393 {
    394   switch (key_type)
    395   {
    396     case EVP_PKEY_RSA:
    397       return "EVP_PKEY_RSA";
    398     case EVP_PKEY_RSA2:
    399       return "EVP_PKEY_RSA2";
    400     case EVP_PKEY_DSA:
    401       return "EVP_PKEY_DSA";
    402 #if defined(EVP_PKEY_DSA1)
    403     case EVP_PKEY_DSA1:
    404       return "EVP_PKEY_DSA1";
    405 #endif  /* EVP_PKEY_DSA1 */
    406 #if defined(EVP_PKEY_DSA2)
    407     case EVP_PKEY_DSA2:
    408       return "EVP_PKEY_DSA2";
    409 #endif  /* EVP_PKEY_DSA2 */
    410 #if defined(EVP_PKEY_DSA3)
    411     case EVP_PKEY_DSA3:
    412       return "EVP_PKEY_DSA3";
    413 #endif  /* EVP_PKEY_DSA3 */
    414 #if defined(EVP_PKEY_DSA4)
    415     case EVP_PKEY_DSA4:
    416       return "EVP_PKEY_DSA4";
    417 #endif  /* EVP_PKEY_DSA4 */
    418     case EVP_PKEY_DH:
    419       return "EVP_PKEY_DH";
    420     case EVP_PKEY_EC:
    421       return "EVP_PKEY_EC";
    422     // Should we also care about EVP_PKEY_HMAC and EVP_PKEY_CMAC?
    423     default:
    424       return NULL;
    425   }
    426   return NULL;
    427 }
    428 
    429 uint32_t
    430 get_certificate_keybits (EVP_PKEY *public_key)
    431 {
    432   /*
    433     In theory, we could use check_bitlen_dsa() and check_bitlen_rsa()
    434    */
    435   uint32_t key_bits;
    436   const char *key_type_str;
    437 
    438   key_type_str = key_type_to_str(public_key->type);
    439   if (key_type_str)
    440     verb("V: key type: %s", key_type_str);
    441   else
    442     verb("V: key type: %d", public_key->type);
    443 
    444   key_bits = EVP_PKEY_bits(public_key);
    445   if (0 == key_bits)
    446     die ("unknown public key type");
    447   verb ("V: keybits: %d", key_bits);
    448   return key_bits;
    449 }
    450 
    451 uint32_t
    452 dns_label_count(char *label, char *delim)
    453 {
    454   char *label_tmp;
    455   char *saveptr;
    456   char *saveptr_tmp;
    457   uint32_t label_count;
    458 
    459   label_tmp = strdup(label);
    460   label_count = 0;
    461   saveptr = NULL;
    462   saveptr_tmp = NULL;
    463   saveptr = strtok_r(label_tmp, delim, &saveptr);
    464   if (NULL != saveptr)
    465   {
    466     // Did we find our first label?
    467     if (saveptr[0] != delim[0])
    468     {
    469       label_count++;
    470     }
    471     do
    472     {
    473       // Find all subsequent labels
    474       label_count++;
    475       saveptr_tmp = strtok_r(NULL, delim, &saveptr);
    476     } while (NULL != saveptr_tmp);
    477   }
    478   verb_debug ("V: label found; total label count: %d", label_count);
    479   free(label_tmp);
    480   return label_count;
    481 }
    482 
    483 // first we split strings on '.'
    484 // then we call each split string a 'label'
    485 // Do not allow '*' for the top level domain label; eg never allow *.*.com
    486 // Do not allow '*' for subsequent subdomains; eg never allow *.foo.example.com
    487 // Do allow *.example.com
    488 uint32_t
    489 check_wildcard_match_rfc2595 (const char *orig_hostname,
    490                       const char *orig_cert_wild_card)
    491 {
    492   char *hostname;
    493   char *hostname_to_free;
    494   char *cert_wild_card;
    495   char *cert_wild_card_to_free;
    496   char *expected_label;
    497   char *wildcard_label;
    498   char *delim;
    499   char *wildchar;
    500   uint32_t ok;
    501   uint32_t wildcard_encountered;
    502   uint32_t label_count;
    503 
    504   // First we copy the original strings
    505   hostname = strndup(orig_hostname, strlen(orig_hostname));
    506   cert_wild_card = strndup(orig_cert_wild_card, strlen(orig_cert_wild_card));
    507   hostname_to_free = hostname;
    508   cert_wild_card_to_free = cert_wild_card;
    509   delim = strdup(".");
    510   wildchar = strdup("*");
    511 
    512   verb_debug ("V: Inspecting '%s' for possible wildcard match against '%s'",
    513          hostname, cert_wild_card);
    514 
    515   // By default we have not processed any labels
    516   label_count = dns_label_count(cert_wild_card, delim);
    517 
    518   // By default we have no match
    519   ok = 0;
    520   wildcard_encountered = 0;
    521   // First - do we have labels? If not, we refuse to even try to match
    522   if ((NULL != strpbrk(cert_wild_card, delim)) &&
    523       (NULL != strpbrk(hostname, delim)) &&
    524       (label_count <= ((uint32_t)RFC2595_MIN_LABEL_COUNT)))
    525   {
    526     if (wildchar[0] == cert_wild_card[0])
    527     {
    528       verb_debug ("V: Found wildcard in at start of provided certificate name");
    529       do
    530       {
    531         // Skip over the bytes between the first char and until the next label
    532         wildcard_label = strsep(&cert_wild_card, delim);
    533         expected_label = strsep(&hostname, delim);
    534         if (NULL != wildcard_label &&
    535             NULL != expected_label &&
    536             NULL != hostname &&
    537             NULL != cert_wild_card)
    538         {
    539           // Now we only consider this wildcard valid if the rest of the
    540           // hostnames match verbatim
    541           verb_debug ("V: Attempting match of '%s' against '%s'",
    542                  expected_label, wildcard_label);
    543           // This is the case where we have a label that begins with wildcard
    544           // Furthermore, we only allow this for the first label
    545           if (wildcard_label[0] == wildchar[0] &&
    546               0 == wildcard_encountered && 0 == ok)
    547           {
    548             verb ("V: Forced match of '%s' against '%s'", expected_label, wildcard_label);
    549             wildcard_encountered = 1;
    550           } else {
    551             verb_debug ("V: Attempting match of '%s' against '%s'",
    552                    hostname, cert_wild_card);
    553             if (0 == strcasecmp (expected_label, wildcard_label) &&
    554                 label_count >= ((uint32_t)RFC2595_MIN_LABEL_COUNT))
    555             {
    556               ok = 1;
    557               verb_debug ("V: remaining labels match!");
    558               break;
    559             } else {
    560               ok = 0;
    561               verb_debug ("V: remaining labels do not match!");
    562               break;
    563             }
    564           }
    565         } else {
    566           // We hit this case when we have a mismatched number of labels
    567           verb_debug ("V: NULL label; no wildcard here");
    568           break;
    569         }
    570       } while (0 != wildcard_encountered && label_count <= RFC2595_MIN_LABEL_COUNT);
    571     } else {
    572       verb_debug ("V: Not a RFC 2595 wildcard");
    573     }
    574   } else {
    575     verb_debug ("V: Not a valid wildcard certificate");
    576     ok = 0;
    577   }
    578   // Free our copies
    579   free(wildchar);
    580   free(delim);
    581   free(hostname_to_free);
    582   free(cert_wild_card_to_free);
    583   if (wildcard_encountered & ok && label_count >= RFC2595_MIN_LABEL_COUNT)
    584   {
    585     verb_debug ("V: wildcard match of %s against %s",
    586           orig_hostname, orig_cert_wild_card);
    587     return (wildcard_encountered & ok);
    588   } else {
    589     verb_debug ("V: wildcard match failure of %s against %s",
    590           orig_hostname, orig_cert_wild_card);
    591     return 0;
    592   }
    593 }
    594 #endif
    595 
    596 #ifndef USE_POLARSSL
    597 /**
    598  This extracts the first commonName and checks it against hostname.
    599 */
    600 uint32_t
    601 check_cn (SSL *ssl, const char *hostname)
    602 {
    603   int ok = 0;
    604   int ret;
    605   char *cn_buf;
    606   X509 *certificate;
    607   X509_NAME *xname;
    608 
    609   // We cast this to cast away g++ complaining about the following:
    610   // error: invalid conversion from void* to char*
    611   cn_buf = (char *) xmalloc(TLSDATE_HOST_NAME_MAX + 1);
    612 
    613   certificate = SSL_get_peer_certificate(ssl);
    614   if (NULL == certificate)
    615   {
    616     die ("Unable to extract certificate");
    617   }
    618 
    619   memset(cn_buf, '\0', (TLSDATE_HOST_NAME_MAX + 1));
    620   xname = X509_get_subject_name(certificate);
    621   ret = X509_NAME_get_text_by_NID(xname, NID_commonName,
    622                                   cn_buf, TLSDATE_HOST_NAME_MAX);
    623 
    624   if (-1 == ret || ret != (int) strlen(cn_buf))
    625   {
    626     die ("Unable to extract commonName");
    627   }
    628   if (strcasecmp(cn_buf, hostname))
    629   {
    630     verb ("V: commonName mismatch! Expected: %s - received: %s",
    631           hostname, cn_buf);
    632   } else {
    633     verb ("V: commonName matched: %s", cn_buf);
    634     ok = 1;
    635   }
    636 
    637   X509_NAME_free(xname);
    638   X509_free(certificate);
    639   xfree(cn_buf);
    640 
    641   return ok;
    642 }
    643 
    644 /**
    645  Search for a hostname match in the SubjectAlternativeNames.
    646 */
    647 uint32_t
    648 check_san (SSL *ssl, const char *hostname)
    649 {
    650   X509 *cert;
    651   int extcount, ok = 0;
    652   /* What an OpenSSL mess ... */
    653   if (NULL == (cert = SSL_get_peer_certificate(ssl)))
    654   {
    655     die ("Getting certificate failed");
    656   }
    657 
    658   if ((extcount = X509_get_ext_count(cert)) > 0)
    659   {
    660     int i;
    661     for (i = 0; i < extcount; ++i)
    662     {
    663       const char *extstr;
    664       X509_EXTENSION *ext;
    665       ext = X509_get_ext(cert, i);
    666       extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
    667 
    668       if (!strcmp(extstr, "subjectAltName"))
    669       {
    670 
    671         int j;
    672         void *extvalstr;
    673         const unsigned char *tmp;
    674 
    675         STACK_OF(CONF_VALUE) *val;
    676         CONF_VALUE *nval;
    677 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
    678         const
    679 #endif
    680         X509V3_EXT_METHOD *method;
    681 
    682         if (!(method = X509V3_EXT_get(ext)))
    683         {
    684           break;
    685         }
    686 
    687         tmp = ext->value->data;
    688         if (method->it)
    689         {
    690           extvalstr = ASN1_item_d2i(NULL, &tmp, ext->value->length,
    691                                     ASN1_ITEM_ptr(method->it));
    692         } else {
    693           extvalstr = method->d2i(NULL, &tmp, ext->value->length);
    694         }
    695 
    696         if (!extvalstr)
    697         {
    698           break;
    699         }
    700 
    701         if (method->i2v)
    702         {
    703           val = method->i2v(method, extvalstr, NULL);
    704           for (j = 0; ((size_t) j) < sk_CONF_VALUE_num(val); ++j)
    705           {
    706             nval = sk_CONF_VALUE_value(val, j);
    707             if ((!strcasecmp(nval->name, "DNS") &&
    708                 !strcasecmp(nval->value, hostname) ) ||
    709                 (!strcasecmp(nval->name, "iPAddress") &&
    710                 !strcasecmp(nval->value, hostname)))
    711             {
    712               verb ("V: subjectAltName matched: %s, type: %s", nval->value, nval->name); // We matched this; so it's safe to print
    713               ok = 1;
    714               break;
    715             }
    716             // Attempt to match subjectAltName DNS names
    717             if (!strcasecmp(nval->name, "DNS"))
    718             {
    719               ok = check_wildcard_match_rfc2595(hostname, nval->value);
    720               if (ok)
    721               {
    722                 break;
    723               }
    724             }
    725             verb_debug ("V: subjectAltName found but not matched: %s, type: %s",
    726                 nval->value, sanitize_string(nval->name));
    727           }
    728         }
    729       } else {
    730         verb_debug ("V: found non subjectAltName extension");
    731       }
    732       if (ok)
    733       {
    734         break;
    735       }
    736     }
    737   } else {
    738     verb_debug ("V: no X509_EXTENSION field(s) found");
    739   }
    740   X509_free(cert);
    741   return ok;
    742 }
    743 
    744 uint32_t
    745 check_name (SSL *ssl, const char *hostname)
    746 {
    747   uint32_t ret;
    748   ret = check_cn(ssl, hostname);
    749   ret += check_san(ssl, hostname);
    750   if (0 != ret && 0 < ret)
    751   {
    752     verb ("V: hostname verification passed");
    753   } else {
    754     die ("hostname verification failed for host %s!", host);
    755   }
    756   return ret;
    757 }
    758 #endif
    759 
    760 #ifdef USE_POLARSSL
    761 uint32_t
    762 verify_signature (ssl_context *ssl, const char *hostname)
    763 {
    764   int ssl_verify_result;
    765 
    766   ssl_verify_result = ssl_get_verify_result (ssl);
    767   if (ssl_verify_result & BADCERT_EXPIRED)
    768   {
    769     die ("certificate has expired");
    770   }
    771   if (ssl_verify_result & BADCERT_REVOKED)
    772   {
    773     die ("certificate has been revoked");
    774   }
    775   if (ssl_verify_result & BADCERT_CN_MISMATCH)
    776   {
    777     die ("CN and subject AltName mismatch for certificate");
    778   }
    779   if (ssl_verify_result & BADCERT_NOT_TRUSTED)
    780   {
    781     die ("certificate is self-signed or not signed by a trusted CA");
    782   }
    783 
    784   if (0 == ssl_verify_result)
    785   {
    786     verb ("V: verify success");
    787   }
    788   else
    789   {
    790     die ("certificate verification error: -0x%04x", -ssl_verify_result);
    791   }
    792   return 0;
    793 }
    794 #else
    795 uint32_t
    796 verify_signature (SSL *ssl, const char *hostname)
    797 {
    798   long ssl_verify_result;
    799   X509 *certificate;
    800 
    801   certificate = SSL_get_peer_certificate(ssl);
    802   if (NULL == certificate)
    803   {
    804     die ("Getting certificate failed");
    805   }
    806   // In theory, we verify that the cert is valid
    807   ssl_verify_result = SSL_get_verify_result(ssl);
    808   switch (ssl_verify_result)
    809   {
    810   case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
    811   case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
    812     die ("certificate is self signed");
    813   case X509_V_OK:
    814     verb ("V: certificate verification passed");
    815     break;
    816   default:
    817     die ("certification verification error: %ld",
    818          ssl_verify_result);
    819   }
    820  return 0;
    821 }
    822 #endif
    823 
    824 #ifdef USE_POLARSSL
    825 void
    826 check_key_length (ssl_context *ssl)
    827 {
    828   uint32_t key_bits;
    829   const x509_cert *certificate;
    830   const rsa_context *public_key;
    831   char buf[1024];
    832 
    833   certificate = ssl_get_peer_cert (ssl);
    834   if (NULL == certificate)
    835   {
    836     die ("Getting certificate failed");
    837   }
    838 
    839   x509parse_dn_gets(buf, 1024, &certificate->subject);
    840   verb_debug ("V: Certificate for subject '%s'", buf);
    841 
    842   public_key = &certificate->rsa;
    843   if (NULL == public_key)
    844   {
    845     die ("public key extraction failure");
    846   } else {
    847     verb_debug ("V: public key is ready for inspection");
    848   }
    849   key_bits = mpi_msb (&public_key->N);
    850   if (MIN_PUB_KEY_LEN >= key_bits)
    851   {
    852     die ("Unsafe public key size: %d bits", key_bits);
    853   } else {
    854     verb_debug ("V: key length appears safe");
    855   }
    856 }
    857 #else
    858 void
    859 check_key_length (SSL *ssl)
    860 {
    861   uint32_t key_bits;
    862   X509 *certificate;
    863   EVP_PKEY *public_key;
    864   certificate = SSL_get_peer_certificate (ssl);
    865   if (NULL == certificate)
    866   {
    867     die ("Getting certificate failed");
    868   }
    869   public_key = X509_get_pubkey (certificate);
    870   if (NULL == public_key)
    871   {
    872     die ("public key extraction failure");
    873   } else {
    874     verb_debug ("V: public key is ready for inspection");
    875   }
    876 
    877   key_bits = get_certificate_keybits (public_key);
    878   if (MIN_PUB_KEY_LEN >= key_bits && public_key->type != EVP_PKEY_EC)
    879   {
    880     die ("Unsafe public key size: %d bits", key_bits);
    881   } else {
    882      if (public_key->type == EVP_PKEY_EC)
    883        if(key_bits >= MIN_ECC_PUB_KEY_LEN
    884           && key_bits <= MAX_ECC_PUB_KEY_LEN)
    885        {
    886          verb_debug ("V: ECC key length appears safe");
    887        } else {
    888          die ("Unsafe ECC key size: %d bits", key_bits);
    889      } else {
    890        verb_debug ("V: key length appears safe");
    891      }
    892   }
    893   EVP_PKEY_free (public_key);
    894 }
    895 #endif
    896 
    897 #ifdef USE_POLARSSL
    898 void
    899 inspect_key (ssl_context *ssl, const char *hostname)
    900 {
    901   verify_signature (ssl, hostname);
    902 
    903   // ssl_get_verify_result() already checks for CN / subjectAltName match
    904   // and reports the mismatch as error. So check_name() is not called
    905 }
    906 #else
    907 void
    908 inspect_key (SSL *ssl, const char *hostname)
    909 {
    910 
    911     verify_signature (ssl, hostname);
    912     check_name (ssl, hostname);
    913 }
    914 #endif
    915 
    916 #ifdef USE_POLARSSL
    917 void
    918 check_timestamp (uint32_t server_time)
    919 {
    920   uint32_t compiled_time = RECENT_COMPILE_DATE;
    921   uint32_t max_reasonable_time = MAX_REASONABLE_TIME;
    922   if (compiled_time < server_time
    923       &&
    924       server_time < max_reasonable_time)
    925   {
    926     verb("V: remote peer provided: %d, preferred over compile time: %d",
    927           server_time, compiled_time);
    928   } else {
    929     die("V: the remote server is a false ticker! server: %d compile: %d",
    930          server_time, compiled_time);
    931   }
    932 }
    933 
    934 static int ssl_do_handshake_part(ssl_context *ssl)
    935 {
    936   int ret = 0;
    937 
    938   /* Only do steps till ServerHello is received */
    939   while (ssl->state != SSL_SERVER_HELLO)
    940   {
    941     ret = ssl_handshake_step (ssl);
    942     if (0 != ret)
    943     {
    944       die("SSL handshake failed");
    945     }
    946   }
    947   /* Do ServerHello so we can skim the timestamp */
    948   ret = ssl_handshake_step (ssl);
    949   if (0 != ret)
    950   {
    951     die("SSL handshake failed");
    952   }
    953 
    954   return 0;
    955 }
    956 
    957 /**
    958  * Run SSL handshake and store the resulting time value in the
    959  * 'time_map'.
    960  *
    961  * @param time_map where to store the current time
    962  * @param time_is_an_illusion
    963  * @param http whether to do an http request and take the date from that
    964  *     instead.
    965  */
    966 static void
    967 run_ssl (uint32_t *time_map, int time_is_an_illusion, int http)
    968 {
    969   entropy_context entropy;
    970   ctr_drbg_context ctr_drbg;
    971   ssl_context ssl;
    972   proxy_polarssl_ctx proxy_ctx;
    973   x509_cert cacert;
    974   struct stat statbuf;
    975   int ret = 0, server_fd = 0;
    976   char *pers = "tlsdate-helper";
    977 
    978   memset (&ssl, 0, sizeof(ssl_context));
    979   memset (&cacert, 0, sizeof(x509_cert));
    980 
    981   verb("V: Using PolarSSL for SSL");
    982   if (ca_racket)
    983   {
    984     if (-1 == stat (ca_cert_container, &statbuf))
    985     {
    986       die("Unable to stat CA certficate container %s", ca_cert_container);
    987     }
    988     else
    989     {
    990       switch (statbuf.st_mode & S_IFMT)
    991       {
    992       case S_IFREG:
    993         if (0 > x509parse_crtfile(&cacert, ca_cert_container))
    994           fprintf(stderr, "x509parse_crtfile failed");
    995         break;
    996       case S_IFDIR:
    997         if (0 > x509parse_crtpath(&cacert, ca_cert_container))
    998           fprintf(stderr, "x509parse_crtpath failed");
    999         break;
   1000       default:
   1001         die("Unable to load CA certficate container %s", ca_cert_container);
   1002       }
   1003     }
   1004   }
   1005 
   1006   entropy_init (&entropy);
   1007   if (0 != ctr_drbg_init (&ctr_drbg, entropy_func, &entropy,
   1008                          (unsigned char *) pers, strlen(pers)))
   1009   {
   1010     die("Failed to initialize CTR_DRBG");
   1011   }
   1012 
   1013   if (0 != ssl_init (&ssl))
   1014   {
   1015     die("SSL initialization failed");
   1016   }
   1017   ssl_set_endpoint (&ssl, SSL_IS_CLIENT);
   1018   ssl_set_rng (&ssl, ctr_drbg_random, &ctr_drbg);
   1019   ssl_set_ca_chain (&ssl, &cacert, NULL, hostname_to_verify);
   1020   if (ca_racket)
   1021   {
   1022       // You can do SSL_VERIFY_REQUIRED here, but then the check in
   1023       // inspect_key() never happens as the ssl_handshake() will fail.
   1024       ssl_set_authmode (&ssl, SSL_VERIFY_OPTIONAL);
   1025   }
   1026 
   1027   if (proxy)
   1028   {
   1029     char *scheme;
   1030     char *proxy_host;
   1031     char *proxy_port;
   1032 
   1033     parse_proxy_uri (proxy, &scheme, &proxy_host, &proxy_port);
   1034 
   1035     verb("V: opening socket to proxy %s:%s", proxy_host, proxy_port);
   1036     if (0 != net_connect (&server_fd, proxy_host, atoi(proxy_port)))
   1037     {
   1038       die ("SSL connection failed");
   1039     }
   1040 
   1041     proxy_polarssl_init (&proxy_ctx);
   1042     proxy_polarssl_set_bio (&proxy_ctx, net_recv, &server_fd, net_send, &server_fd);
   1043     proxy_polarssl_set_host (&proxy_ctx, host);
   1044     proxy_polarssl_set_port (&proxy_ctx, atoi(port));
   1045     proxy_polarssl_set_scheme (&proxy_ctx, scheme);
   1046 
   1047     ssl_set_bio (&ssl, proxy_polarssl_recv, &proxy_ctx, proxy_polarssl_send, &proxy_ctx);
   1048 
   1049     verb("V: Handle proxy connection");
   1050     if (0 == proxy_ctx.f_connect (&proxy_ctx))
   1051       die("Proxy connection failed");
   1052   }
   1053   else
   1054   {
   1055     verb("V: opening socket to %s:%s", host, port);
   1056     if (0 != net_connect (&server_fd, host, atoi(port)))
   1057     {
   1058       die ("SSL connection failed");
   1059     }
   1060 
   1061     ssl_set_bio (&ssl, net_recv, &server_fd, net_send, &server_fd);
   1062   }
   1063 
   1064   verb("V: starting handshake");
   1065   if (0 != ssl_do_handshake_part (&ssl))
   1066     die("SSL handshake first part failed");
   1067 
   1068   uint32_t timestamp = ( (uint32_t) ssl.in_msg[6] << 24 )
   1069                      | ( (uint32_t) ssl.in_msg[7] << 16 )
   1070                      | ( (uint32_t) ssl.in_msg[8] <<  8 )
   1071                      | ( (uint32_t) ssl.in_msg[9]       );
   1072   check_timestamp (timestamp);
   1073 
   1074   verb("V: continuing handshake");
   1075   /* Continue with handshake */
   1076   while (0 != (ret = ssl_handshake (&ssl)))
   1077   {
   1078     if (POLARSSL_ERR_NET_WANT_READ  != ret &&
   1079         POLARSSL_ERR_NET_WANT_WRITE != ret)
   1080     {
   1081       die("SSL handshake failed");
   1082     }
   1083   }
   1084 
   1085   // Verify the peer certificate against the CA certs on the local system
   1086   if (ca_racket) {
   1087     inspect_key (&ssl, hostname_to_verify);
   1088   } else {
   1089     verb ("V: Certificate verification skipped!");
   1090   }
   1091   check_key_length (&ssl);
   1092 
   1093   memcpy (time_map, &timestamp, sizeof(uint32_t));
   1094   proxy_polarssl_free (&proxy_ctx);
   1095   ssl_free (&ssl);
   1096   x509_free (&cacert);
   1097 }
   1098 #else /* USE_POLARSSL */
   1099 /**
   1100  * Run SSL handshake and store the resulting time value in the
   1101  * 'time_map'.
   1102  *
   1103  * @param time_map where to store the current time
   1104  * @param time_is_an_illusion
   1105  * @param http whether to do an http request and take the date from that
   1106  *     instead.
   1107  */
   1108 static void
   1109 run_ssl (uint32_t *time_map, int time_is_an_illusion, int http)
   1110 {
   1111   BIO *s_bio;
   1112   SSL_CTX *ctx;
   1113   SSL *ssl;
   1114   struct stat statbuf;
   1115   uint32_t result_time;
   1116 
   1117   SSL_load_error_strings();
   1118   SSL_library_init();
   1119 
   1120   ctx = NULL;
   1121   if (0 == strcmp("sslv23", protocol))
   1122   {
   1123     verb ("V: using SSLv23_client_method()");
   1124     ctx = SSL_CTX_new(SSLv23_client_method());
   1125   } else if (0 == strcmp("sslv3", protocol))
   1126   {
   1127     verb ("V: using SSLv3_client_method()");
   1128     ctx = SSL_CTX_new(SSLv3_client_method());
   1129   } else if (0 == strcmp("tlsv1", protocol))
   1130   {
   1131     verb ("V: using TLSv1_client_method()");
   1132     ctx = SSL_CTX_new(TLSv1_client_method());
   1133   } else
   1134     die("Unsupported protocol `%s'", protocol);
   1135 
   1136   if (ctx == NULL)
   1137     die("OpenSSL failed to support protocol `%s'", protocol);
   1138 
   1139   verb("V: Using OpenSSL for SSL");
   1140   if (ca_racket)
   1141   {
   1142     if (-1 == stat(ca_cert_container, &statbuf))
   1143     {
   1144       die("Unable to stat CA certficate container %s", ca_cert_container);
   1145     } else
   1146     {
   1147       switch (statbuf.st_mode & S_IFMT)
   1148       {
   1149       case S_IFREG:
   1150         if (1 != SSL_CTX_load_verify_locations(ctx, ca_cert_container, NULL))
   1151           fprintf(stderr, "SSL_CTX_load_verify_locations failed");
   1152         break;
   1153       case S_IFDIR:
   1154         if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container))
   1155           fprintf(stderr, "SSL_CTX_load_verify_locations failed");
   1156         break;
   1157       default:
   1158         if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container))
   1159         {
   1160           fprintf(stderr, "SSL_CTX_load_verify_locations failed");
   1161           die("Unable to load CA certficate container %s", ca_cert_container);
   1162         }
   1163       }
   1164     }
   1165   }
   1166 
   1167   if (NULL == (s_bio = BIO_new(BIO_s_connect())))
   1168     die ("connect BIO setup failed");
   1169   setup_proxy(s_bio);
   1170   if (NULL == (ssl = SSL_new(ctx)))
   1171     die ("SSL setup failed");
   1172   SSL_set_bio(ssl, s_bio, s_bio);
   1173 
   1174   if (time_is_an_illusion)
   1175   {
   1176     SSL_set_info_callback(ssl, openssl_time_callback);
   1177   }
   1178 
   1179   SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
   1180   verb("V: opening socket to %s:%s", host, port);
   1181   if ( (1 != BIO_set_conn_hostname(s_bio, host)) ||
   1182        (1 != BIO_set_conn_port(s_bio, port)) )
   1183     die ("Failed to initialize connection to `%s:%s'", host, port);
   1184 
   1185   // This should run in seccomp
   1186   // eg:     prctl(PR_SET_SECCOMP, 1);
   1187   if (1 != SSL_connect(ssl))
   1188     die ("SSL connection failed");
   1189 
   1190   // from /usr/include/openssl/ssl3.h
   1191   //  ssl->s3->server_random is an unsigned char of 32 bits
   1192   memcpy(&result_time, ssl->s3->server_random, sizeof (uint32_t));
   1193   verb("V: In TLS response, T=%lu", (unsigned long)ntohl(result_time));
   1194 
   1195   if (http) {
   1196     char buf[1024];
   1197     verb_debug ("V: Starting HTTP");
   1198     if (snprintf(buf, sizeof(buf),
   1199                  HTTP_REQUEST, HTTPS_USER_AGENT, hostname_to_verify) >= 1024)
   1200       die("hostname too long");
   1201     buf[1023]='\0'; /* Unneeded. */
   1202     verb_debug ("V: Writing HTTP request");
   1203     if (1 != write_all_to_ssl(ssl, buf))
   1204       die ("write all to bio failed.");
   1205     verb_debug ("V: Reading HTTP response");
   1206     if (1 != read_http_date_from_ssl(ssl, &result_time))
   1207       die ("read all from bio failed.");
   1208     verb ("V: Received HTTP response. T=%lu", (unsigned long)result_time);
   1209 
   1210     result_time = htonl(result_time);
   1211   }
   1212 
   1213   // Verify the peer certificate against the CA certs on the local system
   1214   if (ca_racket) {
   1215     inspect_key (ssl, hostname_to_verify);
   1216   } else {
   1217     verb ("V: Certificate verification skipped!");
   1218   }
   1219   check_key_length(ssl);
   1220 
   1221   memcpy(time_map, &result_time, sizeof (uint32_t));
   1222 
   1223   SSL_free(ssl);
   1224   SSL_CTX_free(ctx);
   1225 }
   1226 #endif /* USE_POLARSSL */
   1227 /** drop root rights and become 'nobody' */
   1228 
   1229 int
   1230 main(int argc, char **argv)
   1231 {
   1232   uint32_t *time_map;
   1233   struct tlsdate_time start_time, end_time, warp_time;
   1234   int status;
   1235   pid_t ssl_child;
   1236   long long rt_time_ms;
   1237   uint32_t server_time_s;
   1238   int setclock;
   1239   int showtime;
   1240   int showtime_raw;
   1241   int timewarp;
   1242   int leap;
   1243   int http;
   1244 
   1245   if (argc != 13)
   1246     return 1;
   1247   host = argv[1];
   1248   hostname_to_verify = argv[1];
   1249   port = argv[2];
   1250   protocol = argv[3];
   1251   ca_cert_container = argv[6];
   1252   ca_racket = (0 != strcmp ("unchecked", argv[4]));
   1253   verbose = (0 != strcmp ("quiet", argv[5]));
   1254   verbose_debug = (0 != strcmp ("verbose", argv[5]));
   1255   setclock = (0 == strcmp ("setclock", argv[7]));
   1256   showtime = (0 == strcmp ("showtime", argv[8]));
   1257   showtime_raw = (0 == strcmp ("showtime=raw", argv[8]));
   1258   timewarp = (0 == strcmp ("timewarp", argv[9]));
   1259   leap = (0 == strcmp ("leapaway", argv[10]));
   1260   proxy = (0 == strcmp ("none", argv[11]) ? NULL : argv[11]);
   1261   http = (0 == (strcmp("http", argv[12])));
   1262 
   1263   /* Initalize warp_time with RECENT_COMPILE_DATE */
   1264   clock_init_time(&warp_time, RECENT_COMPILE_DATE, 0);
   1265 
   1266   verb ("V: RECENT_COMPILE_DATE is %lu.%06lu",
   1267        (unsigned long) CLOCK_SEC(&warp_time),
   1268        (unsigned long) CLOCK_USEC(&warp_time));
   1269 
   1270   if (1 != timewarp)
   1271   {
   1272     verb ("V: we'll do the time warp another time - we're not setting clock");
   1273   }
   1274 
   1275   /* We are not going to set the clock, thus no need to stay root */
   1276   if (0 == setclock && 0 == timewarp)
   1277   {
   1278     verb ("V: attemping to drop administrator privileges");
   1279     drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL);
   1280   }
   1281 
   1282   // We cast the mmap value to remove this error when compiling with g++:
   1283   // src/tlsdate-helper.c: In function int main(int, char**):
   1284   // src/tlsdate-helper.c:822:41: error: invalid conversion from void* to uint32_t
   1285   time_map = (uint32_t *) mmap (NULL, sizeof (uint32_t),
   1286        PROT_READ | PROT_WRITE,
   1287        MAP_SHARED | MAP_ANONYMOUS, -1, 0);
   1288    if (MAP_FAILED == time_map)
   1289   {
   1290     fprintf (stderr, "mmap failed: %s",
   1291              strerror (errno));
   1292     return 1;
   1293   }
   1294 
   1295   /* Get the current time from the system clock. */
   1296   if (0 != clock_get_real_time(&start_time))
   1297   {
   1298     die ("Failed to read current time of day: %s", strerror (errno));
   1299   }
   1300 
   1301   verb ("V: time is currently %lu.%06lu",
   1302        (unsigned long) CLOCK_SEC(&start_time),
   1303        (unsigned long) CLOCK_NSEC(&start_time));
   1304 
   1305   if (((unsigned long) CLOCK_SEC(&start_time)) < ((unsigned long) CLOCK_SEC(&warp_time)))
   1306   {
   1307     verb ("V: local clock time is less than RECENT_COMPILE_DATE");
   1308     if (timewarp)
   1309     {
   1310       verb ("V: Attempting to warp local clock into the future");
   1311       if (0 != clock_set_real_time(&warp_time))
   1312       {
   1313         die ("setting time failed: %s (Attempted to set clock to %lu.%06lu)",
   1314         strerror (errno),
   1315         (unsigned long) CLOCK_SEC(&warp_time),
   1316         (unsigned long) CLOCK_SEC(&warp_time));
   1317       }
   1318       if (0 != clock_get_real_time(&start_time))
   1319       {
   1320         die ("Failed to read current time of day: %s", strerror (errno));
   1321       }
   1322       verb ("V: time is currently %lu.%06lu",
   1323            (unsigned long) CLOCK_SEC(&start_time),
   1324            (unsigned long) CLOCK_NSEC(&start_time));
   1325       verb ("V: It's just a step to the left...");
   1326     }
   1327   } else {
   1328     verb ("V: time is greater than RECENT_COMPILE_DATE");
   1329   }
   1330 
   1331   /* initialize to bogus value, just to be on the safe side */
   1332   *time_map = 0;
   1333 
   1334   /* Run SSL interaction in separate process (and not as 'root') */
   1335   ssl_child = fork ();
   1336   if (-1 == ssl_child)
   1337     die ("fork failed: %s", strerror (errno));
   1338   if (0 == ssl_child)
   1339   {
   1340     drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL);
   1341     run_ssl (time_map, leap, http);
   1342     (void) munmap (time_map, sizeof (uint32_t));
   1343     _exit (0);
   1344   }
   1345   if (ssl_child != platform->process_wait (ssl_child, &status, 1))
   1346     die ("waitpid failed: %s", strerror (errno));
   1347   if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)) ))
   1348     die ("child process failed in SSL handshake");
   1349 
   1350   if (0 != clock_get_real_time(&end_time))
   1351     die ("Failed to read current time of day: %s", strerror (errno));
   1352 
   1353   /* calculate RTT */
   1354   rt_time_ms = (CLOCK_SEC(&end_time) - CLOCK_SEC(&start_time)) * 1000 + (CLOCK_USEC(&end_time) - CLOCK_USEC(&start_time)) / 1000;
   1355   if (rt_time_ms < 0)
   1356     rt_time_ms = 0; /* non-linear time... */
   1357 #ifdef USE_POLARSSL
   1358   server_time_s = *time_map;
   1359 #else
   1360   server_time_s = ntohl (*time_map);
   1361 #endif
   1362   // We should never have a time_map of zero here;
   1363   // It either stayed zero or we have a false ticker.
   1364   if ( 0 == server_time_s )
   1365     die ("child process failed to update time map; weird platform issues?");
   1366   munmap (time_map, sizeof (uint32_t));
   1367 
   1368   verb ("V: server time %u (difference is about %d s) was fetched in %lld ms",
   1369   (unsigned int) server_time_s,
   1370   CLOCK_SEC(&start_time) - server_time_s,
   1371   rt_time_ms);
   1372 
   1373   /* warning if the handshake took too long */
   1374   if (rt_time_ms > TLS_RTT_UNREASONABLE) {
   1375     die ("the TLS handshake took more than %d msecs - consider using a different " \
   1376       "server or run it again", TLS_RTT_UNREASONABLE);
   1377   }
   1378   if (rt_time_ms > TLS_RTT_THRESHOLD) {
   1379     verb ("V: the TLS handshake took more than %d msecs - consider using a different " \
   1380       "server or run it again", TLS_RTT_THRESHOLD);
   1381   }
   1382 
   1383   if (showtime_raw)
   1384   {
   1385     fwrite(&server_time_s, sizeof(server_time_s), 1, stdout);
   1386   }
   1387 
   1388   if (showtime)
   1389   {
   1390      struct tm  ltm;
   1391      time_t tim = server_time_s;
   1392      char       buf[256];
   1393 
   1394      localtime_r(&tim, &ltm);
   1395      if (0 == strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %Z %Y", &ltm))
   1396      {
   1397        die ("strftime returned 0");
   1398      }
   1399      fprintf(stdout, "%s\n", buf);
   1400   }
   1401 
   1402   /* finally, actually set the time */
   1403   if (setclock)
   1404   {
   1405     struct tlsdate_time server_time;
   1406 
   1407     clock_init_time(&server_time,  server_time_s + (rt_time_ms / 2 / 1000),
   1408                    (rt_time_ms / 2) % 1000);
   1409 
   1410     // We should never receive a time that is before the time we were last
   1411     // compiled; we subscribe to the linear theory of time for this program
   1412     // and this program alone!
   1413     if (CLOCK_SEC(&server_time) >= MAX_REASONABLE_TIME)
   1414       die("remote server is a false ticker from the future!");
   1415     if (CLOCK_SEC(&server_time) <= RECENT_COMPILE_DATE)
   1416       die ("remote server is a false ticker!");
   1417     if (0 != clock_set_real_time(&server_time))
   1418       die ("setting time failed: %s (Difference from server is about %d s)",
   1419      strerror (errno),
   1420      CLOCK_SEC(&start_time) - server_time_s);
   1421     verb ("V: setting time succeeded");
   1422   }
   1423   return 0;
   1424 }
   1425