Ejemplo n.º 1
0
static int run_cert(X509 *crt, const char *nameincert,
                     const struct set_name_fn *fn)
{
    const char *const *pname = names;
    int failed = 0;

    for (; *pname != NULL; ++pname) {
        int samename = strcasecmp(nameincert, *pname) == 0;
        size_t namelen = strlen(*pname);
        char *name = OPENSSL_malloc(namelen);
        int match, ret;

        memcpy(name, *pname, namelen);

        match = -1;
        if (!TEST_int_ge(ret = X509_check_host(crt, name, namelen, 0, NULL),
                         0)) {
            failed = 1;
        } else if (fn->host) {
            if (ret == 1 && !samename)
                match = 1;
            if (ret == 0 && samename)
                match = 0;
        } else if (ret == 1)
            match = 1;
        if (!TEST_true(check_message(fn, "host", nameincert, match, *pname)))
            failed = 1;

        match = -1;
        if (!TEST_int_ge(ret = X509_check_host(crt, name, namelen,
                                               X509_CHECK_FLAG_NO_WILDCARDS,
                                               NULL), 0)) {
            failed = 1;
        } else if (fn->host) {
            if (ret == 1 && !samename)
                match = 1;
            if (ret == 0 && samename)
                match = 0;
        } else if (ret == 1)
            match = 1;
        if (!TEST_true(check_message(fn, "host-no-wildcards",
                                     nameincert, match, *pname)))
            failed = 1;

        match = -1;
        ret = X509_check_email(crt, name, namelen, 0);
        if (fn->email) {
            if (ret && !samename)
                match = 1;
            if (!ret && samename && strchr(nameincert, '@') != NULL)
                match = 0;
        } else if (ret)
            match = 1;
        if (!TEST_true(check_message(fn, "email", nameincert, match, *pname)))
            failed = 1;
        OPENSSL_free(name);
    }

    return failed == 0;
}
Ejemplo n.º 2
0
static void run_cert(X509 *crt, const char *nameincert,
                     const struct set_name_fn *fn)
{
    const char *const *pname = names;
    while (*pname) {
        int samename = sgx_strcasecmp(nameincert, *pname) == 0;
        size_t namelen = sgx_strlen(*pname);
        char *name = sgx_malloc(namelen);
        int match, ret;
        sgx_memcpy(name, *pname, namelen);

        ret = X509_check_host(crt, name, namelen, 0, NULL);
        match = -1;
        if (ret < 0) {
            fprintf(stderr, "internal error in X509_check_host");
            ++errors;
        } else if (fn->host) {
            if (ret == 1 && !samename)
                match = 1;
            if (ret == 0 && samename)
                match = 0;
        } else if (ret == 1)
            match = 1;
        check_message(fn, "host", nameincert, match, *pname);

        ret = X509_check_host(crt, name, namelen,
                              X509_CHECK_FLAG_NO_WILDCARDS, NULL);
        match = -1;
        if (ret < 0) {
            fprintf(stderr, "internal error in X509_check_host");
            ++errors;
        } else if (fn->host) {
            if (ret == 1 && !samename)
                match = 1;
            if (ret == 0 && samename)
                match = 0;
        } else if (ret == 1)
            match = 1;
        check_message(fn, "host-no-wildcards", nameincert, match, *pname);

        ret = X509_check_email(crt, name, namelen, 0);
        match = -1;
        if (fn->email) {
            if (ret && !samename)
                match = 1;
            if (!ret && samename && sgx_strchr(nameincert, '@') != NULL)
                match = 0;
        } else if (ret)
            match = 1;
        check_message(fn, "email", nameincert, match, *pname);
        ++pname;
        sgx_free(name);
    }
}
Ejemplo n.º 3
0
static inline int tls_check_cert(shout_tls_t *tls)
{
	X509 *cert = SSL_get_peer_certificate(tls->ssl);
	int cert_ok = 0;
	if (!cert)
		return SHOUTERR_TLSBADCERT;

	do {
		if (SSL_get_verify_result(tls->ssl) != X509_V_OK)
			break;

#ifdef XXX_HAVE_X509_check_host
		if (X509_check_host(cert, tls->host, 0, 0, NULL) != 1)
			break;
#else
		if (tls_check_host(cert, tls->host) != SHOUTERR_SUCCESS)
			break;
#endif

		/* ok, all test passed... */
		cert_ok = 1;
	} while (0);

	X509_free(cert);
	return cert_ok ? SHOUTERR_SUCCESS : SHOUTERR_TLSBADCERT;
}
int
main(int argc, char **argv)
{
  if (argc != 3) {
    usage(argv[0]);
  }

  BIO *bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
  if (bio_err == NULL) {
    perror("BIO_ne_fp(stderr)");
    exit(1);
  }

  //+ Features TLS-Client-OpenSSL-Init
  // The following call prints an error message and calls exit() if
  // the OpenSSL configuration file is unreadable.
  OPENSSL_config(NULL);
  // Provide human-readable error messages.
  SSL_load_error_strings();
  // Register ciphers.
  SSL_library_init();
  //-

  //+ Features TLS-Client-OpenSSL-CTX
  // Configure a client connection context.  Send a hendshake for the
  // highest supported TLS version, and disable compression.
  const SSL_METHOD *const req_method = SSLv23_client_method();
  SSL_CTX *const ctx = SSL_CTX_new(req_method);
  if (ctx == NULL) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION);

  // Adjust the ciphers list based on a whitelist.  First enable all
  // ciphers of at least medium strength, to get the list which is
  // compiled into OpenSSL.
  if (SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM") != 1) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  {
    // Create a dummy SSL session to obtain the cipher list.
    SSL *ssl = SSL_new(ctx);
    if (ssl == NULL) {
      ERR_print_errors(bio_err);
      exit(1);
    }
    STACK_OF(SSL_CIPHER) *active_ciphers = SSL_get_ciphers(ssl);
    if (active_ciphers == NULL) {
      ERR_print_errors(bio_err);
      exit(1);
    }
    // Whitelist of candidate ciphers.
    static const char *const candidates[] =  {
      "AES128-GCM-SHA256", "AES128-SHA256", "AES256-SHA256", // strong ciphers
      "AES128-SHA", "AES256-SHA", // strong ciphers, also in older versions
      "RC4-SHA", "RC4-MD5", // backwards compatibility, supposed to be weak
      "DES-CBC3-SHA", "DES-CBC3-MD5", // more backwards compatibility
      NULL
    };
    // Actually selected ciphers.
    char ciphers[300];
    ciphers[0] = '\0';
    for (const char *const *c = candidates; *c; ++c) {
      for (int i = 0; i < sk_SSL_CIPHER_num(active_ciphers); ++i) {
	if (strcmp(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(active_ciphers, i)),
		   *c) == 0) {
	  if (*ciphers) {
	    strcat(ciphers, ":");
	  }
	  strcat(ciphers, *c);
	  break;
	}
      }
    }
    SSL_free(ssl);
    // Apply final cipher list.
    if (SSL_CTX_set_cipher_list(ctx, ciphers) != 1) {
      ERR_print_errors(bio_err);
      exit(1);
    }
  }

  // Load the set of trusted root certificates.
  if (!SSL_CTX_set_default_verify_paths(ctx)) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  //-

  const char *host = argv[1];
  const char *service = argv[2];
  // Perform name lookup, create the TCP client socket, and connect to
  // the server.
  int sockfd = tcp_connect(host, service);
  if (sockfd < 0) {
    perror("connect");
    exit(1);
  }
  // Deactivate the Nagle algorithm.
  //+ Features TLS-Nagle
  const int val = 1;
  int ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
  if (ret < 0) {
    perror("setsockopt(TCP_NODELAY)");
    exit(1);
  }
  //-
  //+ Features TLS-Client-OpenSSL-Connect
  // Create the connection object.
  SSL *ssl = SSL_new(ctx);
  if (ssl == NULL) {
    ERR_print_errors(bio_err);
    exit(1);
  }
  SSL_set_fd(ssl, sockfd);

  // Enable the ServerNameIndication extension
  if (!SSL_set_tlsext_host_name(ssl, host)) {
    ERR_print_errors(bio_err);
    exit(1);
  }

  // Perform the TLS handshake with the server.
  ret = SSL_connect(ssl);
  if (ret != 1) {
    // Error status can be 0 or negative.
    ssl_print_error_and_exit(ssl, "SSL_connect", ret);
  }

  // Obtain the server certificate.
  X509 *peercert = SSL_get_peer_certificate(ssl);
  if (peercert == NULL) {
    fprintf(stderr, "peer certificate missing");
    exit(1);
  }

  // Check the certificate verification result.  Allow an explicit
  // certificate validation override in case verification fails.
  int verifystatus = SSL_get_verify_result(ssl);
  if (verifystatus != X509_V_OK && !certificate_validity_override(peercert)) {
    fprintf(stderr, "SSL_connect: verify result: %s\n",
	    X509_verify_cert_error_string(verifystatus));
    exit(1);
  }

  // Check if the server certificate matches the host name used to
  // establish the connection.
  // FIXME: Currently needs OpenSSL 1.1.
  if (X509_check_host(peercert, (const unsigned char *)host, strlen(host),
		      0) != 1
      && !certificate_host_name_override(peercert, host)) {
    fprintf(stderr, "SSL certificate does not match host name\n");
    exit(1);
  }

  X509_free(peercert);

  //-
  //+ Features TLS-Client-OpenSSL-Connection-Use
  const char *const req = "GET / HTTP/1.0\r\n\r\n";
  if (SSL_write(ssl, req, strlen(req)) < 0) {
    ssl_print_error_and_exit(ssl, "SSL_write", ret);
  }
  char buf[4096];
  ret = SSL_read(ssl, buf, sizeof(buf));
  if (ret < 0) {
    ssl_print_error_and_exit(ssl, "SSL_read", ret);
  }
  //-
  write(STDOUT_FILENO, buf, ret);
  //+ Features TLS-OpenSSL-Connection-Close
  // Send the close_notify alert.
  ret = SSL_shutdown(ssl);
  switch (ret) {
  case 1:
    // A close_notify alert has already been received.
    break;
  case 0:
    // Wait for the close_notify alert from the peer.
    ret = SSL_shutdown(ssl);
    switch (ret) {
    case 0:
      fprintf(stderr, "info: second SSL_shutdown returned zero\n");
      break;
    case 1:
      break;
    default:
      ssl_print_error_and_exit(ssl, "SSL_shutdown 2", ret);
    }
    break;
  default:
    ssl_print_error_and_exit(ssl, "SSL_shutdown 1", ret);
  }
  SSL_free(ssl);
  close(sockfd);
  //-
  //+ Features TLS-OpenSSL-Context-Close
  SSL_CTX_free(ctx);
  //-
  BIO_free(bio_err);
  return 0;
}
Ejemplo n.º 5
0
  bool OpenSSLBase::handshake()
  {

    doTLSOperation( TLSHandshake );

    if( !m_secure )
      return true;

    long res = SSL_get_verify_result( m_ssl );
    if( res != X509_V_OK )
      m_certInfo.status = CertInvalid;
    else
      m_certInfo.status = CertOk;

    X509* peer = SSL_get_peer_certificate( m_ssl );
    if( peer )
    {
      char peer_CN[256];
      X509_NAME_get_text_by_NID( X509_get_issuer_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) );
      m_certInfo.issuer = peer_CN;
      X509_NAME_get_text_by_NID( X509_get_subject_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) );
      m_certInfo.server = peer_CN;
      m_certInfo.date_from = ASN1Time2UnixTime( X509_get_notBefore( peer ) );
      m_certInfo.date_to = ASN1Time2UnixTime( X509_get_notAfter( peer ) );
      std::string p( peer_CN );
      std::transform( p.begin(), p.end(), p.begin(), tolower );

#if defined OPENSSL_VERSION_NUMBER && ( OPENSSL_VERSION_NUMBER >= 0x10002000 )
      res = X509_check_host( peer, p.c_str(), p.length(), X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS, 0 );
      if( res <= 0 ) // 0: verification failed; -1: internal error; -2 input is malformed
        m_certInfo.status |= CertWrongPeer;
#else
      if( p != m_server )
        m_certInfo.status |= CertWrongPeer;
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000

      if( ASN1_UTCTIME_cmp_time_t( X509_get_notBefore( peer ), time( 0 ) ) != -1 )
        m_certInfo.status |= CertNotActive;

      if( ASN1_UTCTIME_cmp_time_t( X509_get_notAfter( peer ), time( 0 ) ) != 1 )
        m_certInfo.status |= CertExpired;

      X509_free( peer );
    }
    else
    {
      m_certInfo.status = CertInvalid;
    }

    const char* tmp;
    tmp = SSL_get_cipher_name( m_ssl );
    if( tmp )
      m_certInfo.cipher = tmp;

    SSL_SESSION* sess = SSL_get_session( m_ssl );
    if( sess )
    {
      switch( SSL_SESSION_get_protocol_version( sess ) )
      {
        case TLS1_VERSION:
          m_certInfo.protocol = "TLSv1";
          break;
        case TLS1_1_VERSION:
          m_certInfo.protocol = "TLSv1.1";
          break;
        case TLS1_2_VERSION:
          m_certInfo.protocol = "TLSv1.2";
          break;
#ifdef TLS1_3_VERSION
        case TLS1_3_VERSION:
          m_certInfo.protocol = "TLSv1.3";
          break;
#endif // TLS1_3_VERSION
        default:
          m_certInfo.protocol = "Unknown TLS version";
          break;
      }
    }

    tmp = SSL_COMP_get_name( SSL_get_current_compression( m_ssl ) );
    if( tmp )
      m_certInfo.compression = tmp;

    m_valid = true;

    m_handler->handleHandshakeResult( this, true, m_certInfo );
    return true;
  }