Example #1
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 * @param time_is_an_illusion
 * @param http whether to do an http request and take the date from that
 *     instead.
 */
static void
run_ssl (uint32_t *time_map, int time_is_an_illusion, int http)
{
  BIO *s_bio;
  SSL_CTX *ctx;
  SSL *ssl;
  struct stat statbuf;
  uint32_t result_time;

  SSL_load_error_strings();
  SSL_library_init();

  ctx = NULL;
  if (0 == strcmp("sslv23", protocol))
  {
    verb ("V: using SSLv23_client_method()");
    ctx = SSL_CTX_new(SSLv23_client_method());
  } else if (0 == strcmp("sslv3", protocol))
  {
    verb ("V: using SSLv3_client_method()");
    ctx = SSL_CTX_new(SSLv3_client_method());
  } else if (0 == strcmp("tlsv1", protocol))
  {
    verb ("V: using TLSv1_client_method()");
    ctx = SSL_CTX_new(TLSv1_client_method());
  } else
    die("Unsupported protocol `%s'", protocol);

  if (ctx == NULL)
    die("OpenSSL failed to support protocol `%s'", protocol);

  verb("V: Using OpenSSL for SSL");
  if (ca_racket)
  {
    if (-1 == stat(ca_cert_container, &statbuf))
    {
      die("Unable to stat CA certficate container %s", ca_cert_container);
    } else
    {
      switch (statbuf.st_mode & S_IFMT)
      {
      case S_IFREG:
        if (1 != SSL_CTX_load_verify_locations(ctx, ca_cert_container, NULL))
          fprintf(stderr, "SSL_CTX_load_verify_locations failed");
        break;
      case S_IFDIR:
        if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container))
          fprintf(stderr, "SSL_CTX_load_verify_locations failed");
        break;
      default:
        if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container))
        {
          fprintf(stderr, "SSL_CTX_load_verify_locations failed");
          die("Unable to load CA certficate container %s", ca_cert_container);
        }
      }
    }
  }

  if (NULL == (s_bio = make_ssl_bio(ctx)))
    die ("SSL BIO setup failed");
  BIO_get_ssl(s_bio, &ssl);
  if (NULL == ssl)
    die ("SSL setup failed");

  if (time_is_an_illusion)
  {
    SSL_set_info_callback(ssl, openssl_time_callback);
  }

  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
  verb("V: opening socket to %s:%s", host, port);
  if ( (1 != BIO_set_conn_hostname(s_bio, host)) ||
       (1 != BIO_set_conn_port(s_bio, port)) )
    die ("Failed to initialize connection to `%s:%s'", host, port);

  if (NULL == BIO_new_fp(stdout, BIO_NOCLOSE))
    die ("BIO_new_fp returned error, possibly: %s", strerror(errno));

  // This should run in seccomp
  // eg:     prctl(PR_SET_SECCOMP, 1);
  if (1 != BIO_do_connect(s_bio)) // XXX TODO: BIO_should_retry() later?
    die ("SSL connection failed");
  if (1 != BIO_do_handshake(s_bio))
    die ("SSL handshake failed");

  // from /usr/include/openssl/ssl3.h
  //  ssl->s3->server_random is an unsigned char of 32 bits
  memcpy(&result_time, ssl->s3->server_random, sizeof (uint32_t));
  verb("V: In TLS response, T=%lu", (unsigned long)ntohl(result_time));

  if (http) {
    char buf[1024];
    verb_debug ("V: Starting HTTP");
    if (snprintf(buf, sizeof(buf),
                 HTTP_REQUEST, HTTPS_USER_AGENT, hostname_to_verify) >= 1024)
      die("hostname too long");
    buf[1023]='\0'; /* Unneeded. */
    verb_debug ("V: Writing HTTP request");
    if (1 != write_all_to_bio(s_bio, buf))
      die ("write all to bio failed.");
    verb_debug ("V: Reading HTTP response");
    if (1 != read_http_date_from_bio(s_bio, &result_time))
      die ("read all from bio failed.");
    verb ("V: Received HTTP response. T=%lu", (unsigned long)result_time);

    result_time = htonl(result_time);
  }

  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    inspect_key (ssl, hostname_to_verify);
  } else {
    verb ("V: Certificate verification skipped!");
  }
  check_key_length(ssl);

  memcpy(time_map, &result_time, sizeof (uint32_t));

  SSL_free(ssl);
  SSL_CTX_free(ctx);
}
Example #2
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 * @param time_is_an_illusion
 * @param http whether to do an http request and take the date from that
 *     instead.
 */
static void
run_ssl (uint32_t *time_map, int time_is_an_illusion, int http)
{
  entropy_context entropy;
  ctr_drbg_context ctr_drbg;
  ssl_context ssl;
  proxy_polarssl_ctx proxy_ctx;
  x509_cert cacert;
  struct stat statbuf;
  int ret = 0, server_fd = 0;
  char *pers = "tlsdate-helper";

  memset (&ssl, 0, sizeof(ssl_context));
  memset (&cacert, 0, sizeof(x509_cert));

  verb("V: Using PolarSSL for SSL");
  if (ca_racket)
  {
    if (-1 == stat (ca_cert_container, &statbuf))
    {
      die("Unable to stat CA certficate container %s", ca_cert_container);
    }
    else
    {
      switch (statbuf.st_mode & S_IFMT)
      {
      case S_IFREG:
        if (0 > x509parse_crtfile(&cacert, ca_cert_container))
          fprintf(stderr, "x509parse_crtfile failed");
        break;
      case S_IFDIR:
        if (0 > x509parse_crtpath(&cacert, ca_cert_container))
          fprintf(stderr, "x509parse_crtpath failed");
        break;
      default:
        die("Unable to load CA certficate container %s", ca_cert_container);
      }
    }
  }

  entropy_init (&entropy);
  if (0 != ctr_drbg_init (&ctr_drbg, entropy_func, &entropy,
                         (unsigned char *) pers, strlen(pers)))
  {
    die("Failed to initialize CTR_DRBG");
  }

  if (0 != ssl_init (&ssl))
  {
    die("SSL initialization failed");
  }
  ssl_set_endpoint (&ssl, SSL_IS_CLIENT);
  ssl_set_rng (&ssl, ctr_drbg_random, &ctr_drbg);
  ssl_set_ca_chain (&ssl, &cacert, NULL, hostname_to_verify);
  if (ca_racket)
  {
      // You can do SSL_VERIFY_REQUIRED here, but then the check in
      // inspect_key() never happens as the ssl_handshake() will fail.
      ssl_set_authmode (&ssl, SSL_VERIFY_OPTIONAL);
  }

  if (proxy)
  {
    char *scheme;
    char *proxy_host;
    char *proxy_port;

    parse_proxy_uri (proxy, &scheme, &proxy_host, &proxy_port);

    verb("V: opening socket to proxy %s:%s", proxy_host, proxy_port);
    if (0 != net_connect (&server_fd, proxy_host, atoi(proxy_port)))
    {
      die ("SSL connection failed");
    }

    proxy_polarssl_init (&proxy_ctx);
    proxy_polarssl_set_bio (&proxy_ctx, net_recv, &server_fd, net_send, &server_fd);
    proxy_polarssl_set_host (&proxy_ctx, host);
    proxy_polarssl_set_port (&proxy_ctx, atoi(port));
    proxy_polarssl_set_scheme (&proxy_ctx, scheme);

    ssl_set_bio (&ssl, proxy_polarssl_recv, &proxy_ctx, proxy_polarssl_send, &proxy_ctx);

    verb("V: Handle proxy connection");
    if (0 == proxy_ctx.f_connect (&proxy_ctx))
      die("Proxy connection failed");
  }
  else
  {
    verb("V: opening socket to %s:%s", host, port);
    if (0 != net_connect (&server_fd, host, atoi(port)))
    {
      die ("SSL connection failed");
    }

    ssl_set_bio (&ssl, net_recv, &server_fd, net_send, &server_fd);
  }

  verb("V: starting handshake");
  if (0 != ssl_do_handshake_part (&ssl))
    die("SSL handshake first part failed");

  uint32_t timestamp = ( (uint32_t) ssl.in_msg[6] << 24 )
                     | ( (uint32_t) ssl.in_msg[7] << 16 )
                     | ( (uint32_t) ssl.in_msg[8] <<  8 )
                     | ( (uint32_t) ssl.in_msg[9]       );
  check_timestamp (timestamp);

  verb("V: continuing handshake");
  /* Continue with handshake */
  while (0 != (ret = ssl_handshake (&ssl)))
  {
    if (POLARSSL_ERR_NET_WANT_READ  != ret &&
        POLARSSL_ERR_NET_WANT_WRITE != ret)
    {
      die("SSL handshake failed");
    }
  }

  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    inspect_key (&ssl, hostname_to_verify);
  } else {
    verb ("V: Certificate verification skipped!");
  }
  check_key_length (&ssl);

  memcpy (time_map, &timestamp, sizeof(uint32_t));
  proxy_polarssl_free (&proxy_ctx);
  ssl_free (&ssl);
  x509_free (&cacert);
}
Example #3
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 */
static void
run_ssl (uint32_t *time_map, int time_is_an_illusion)
{
  BIO *s_bio;
  SSL_CTX *ctx;
  SSL *ssl;

  SSL_load_error_strings();
  SSL_library_init();

  ctx = NULL;
  if (0 == strcmp("sslv23", protocol))
  {
    verb ("V: using SSLv23_client_method()\n");
    ctx = SSL_CTX_new(SSLv23_client_method());
  } else if (0 == strcmp("sslv3", protocol))
  {
    verb ("V: using SSLv3_client_method()\n");
    ctx = SSL_CTX_new(SSLv3_client_method());
  } else if (0 == strcmp("tlsv1", protocol))
  {
    verb ("V: using TLSv1_client_method()\n");
    ctx = SSL_CTX_new(TLSv1_client_method());
  } else
    die("Unsupported protocol `%s'\n", protocol);

  if (ctx == NULL)
    die("OpenSSL failed to support protocol `%s'\n", protocol);

  if (ca_racket)
  {
    if (1 != SSL_CTX_load_verify_locations(ctx, NULL, certdir))
      fprintf(stderr, "SSL_CTX_load_verify_locations failed\n");
  }

  if (NULL == (s_bio = BIO_new_ssl_connect(ctx)))
    die ("SSL BIO setup failed\n");
  BIO_get_ssl(s_bio, &ssl);
  if (NULL == ssl)
    die ("SSL setup failed\n");

  if (time_is_an_illusion)
  {
    SSL_set_info_callback(ssl, openssl_time_callback);
  }

  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
  if ( (1 != BIO_set_conn_hostname(s_bio, host)) ||
       (1 != BIO_set_conn_port(s_bio, port)) )
    die ("Failed to initialize connection to `%s:%s'\n", host, port);

  if (NULL == BIO_new_fp(stdout, BIO_NOCLOSE))
    die ("BIO_new_fp returned error, possibly: %s", strerror(errno));

  // This should run in seccomp
  // eg:     prctl(PR_SET_SECCOMP, 1);
  if (1 != BIO_do_connect(s_bio)) // XXX TODO: BIO_should_retry() later?
    die ("SSL connection failed\n");
  if (1 != BIO_do_handshake(s_bio))
    die ("SSL handshake failed\n");

  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    inspect_key (ssl, host);
  } else {
    verb ("V: Certificate verification skipped!\n");
  }
  check_key_length(ssl);
  // from /usr/include/openssl/ssl3.h
  //  ssl->s3->server_random is an unsigned char of 32 bits
  memcpy(time_map, ssl->s3->server_random, sizeof (uint32_t));
  SSL_free(ssl);
  SSL_CTX_free(ctx);
}