From be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 04:57:58 +0200 Subject: Adding upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../openssl/DigiCertHighAssuranceEVRootCA.pem | 23 +++ .../libh2o/deps/ssl-conservatory/openssl/Makefile | 12 ++ .../deps/ssl-conservatory/openssl/Makefile_mingw | 18 ++ .../libh2o/deps/ssl-conservatory/openssl/README.md | 61 +++++++ ...everything-you-wanted-to-know-about-openssl.pdf | Bin 0 -> 180899 bytes .../openssl/openssl_hostname_validation.c | 181 +++++++++++++++++++++ .../openssl/openssl_hostname_validation.h | 40 +++++ .../deps/ssl-conservatory/openssl/test_client | Bin 0 -> 15680 bytes .../deps/ssl-conservatory/openssl/test_client.c | 142 ++++++++++++++++ 9 files changed, 477 insertions(+) create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/DigiCertHighAssuranceEVRootCA.pem create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile_mingw create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/README.md create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/everything-you-wanted-to-know-about-openssl.pdf create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.c create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.h create mode 100755 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client create mode 100644 web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client.c (limited to 'web/server/h2o/libh2o/deps/ssl-conservatory/openssl') diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/DigiCertHighAssuranceEVRootCA.pem b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/DigiCertHighAssuranceEVRootCA.pem new file mode 100644 index 00000000..4b1bc66b --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/DigiCertHighAssuranceEVRootCA.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile new file mode 100644 index 00000000..0edaa7cb --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile @@ -0,0 +1,12 @@ +# Tested on FreeBSD, Ubuntu 10.04 and Cygwin +CC=gcc +CFLAGS=-c -Wall -std=c99 -pedantic +LDFLAGS=-lcrypto -lssl + +all: test_client + +test_client: test_client.o openssl_hostname_validation.o + $(CC) test_client.o openssl_hostname_validation.o -o test_client $(LDFLAGS) + +clean: + rm -rf *.o test_client diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile_mingw b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile_mingw new file mode 100644 index 00000000..00f63144 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile_mingw @@ -0,0 +1,18 @@ +# Tested on Windows 7 with MinGW-w64 +CC=gcc +CFLAGS=-c -Wall +LDFLAGS= -leay32 -lssl32 + +all: test_client + +test_client: test_client.o openssl_hostname_validation.o + $(CC) test_client.o openssl_hostname_validation.o -o test_client $(LDFLAGS) + +test_client.o: test_client.c + $(CC) $(CFLAGS) test_client.c + +openssl_hostname_validation.o: openssl_hostname_validation.c + $(CC) $(CFLAGS) openssl_hostname_validation.c + +clean: + rm -rf *.o test_client.exe diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/README.md b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/README.md new file mode 100644 index 00000000..14ca84ae --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/README.md @@ -0,0 +1,61 @@ +The SSL Conservatory: OpenSSL Certificate Validation +==================================================== + +This sample code demonstrates how to perform certificate validation when using +the OpenSSL library to connect to an SSL/TLS server. It was tested on Windows +7, OS X and Linux. + + +Read The Whitepaper +------------------- + +Before using this code, please read the white paper "Everything you've always +wanted to know about certificate validation with OpenSSL (but were afraid to +ask)" available at ./everything-you-wanted-to-know-about-openssl.pdf. + + +OS-Specific Instructions +------------------------ + +### Linux + +The code was compiled and tested on Ubuntu 11.04. + +You will have to install the libssl and libcrypto development libraries and +header files. In most Linux distros they are part of the "libssl-dev" package. + + +### OS X + +The code was compiled and tested on OS X Mountain Lion. + +OS X comes the OpenSSL development libraries pre-installed. However, libssl has +been modified by Apple to automatically use the system's trust store when +validating certificate chains; this behavior cannot be changed. Therefore, +specifying a trust store using SSL_CTX_load_verify_locations() will always be +ignored on OS X. + +Additionally, compiling the code on OS X will generate a lot of "is +deprecated" warnings because Apple is migrating from OpenSSL to the Common +Crypto framework. + + +### Windows + +The code was compiled using minGW and tested on Windows 7. + +You will have to install minGW as well as the OpenSSL development libraries. +The OpenSSL project provides a link to pre-compiled libraries for Windows at +the following URL: http://www.openssl.org/related/binaries.html + +If you used those binaries, here are additional instructions to compile the +sample code. First add the OpenSSL headers and libraries to MinGW: + + Copy /include/ to /include/ + Copy /libeay32.dll to /lib/libeay32.dll + Copy /libssl32.dll to /lib/libssl32.dll + +Then compile the test_client: + + make -f Makefile_mingw + diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/everything-you-wanted-to-know-about-openssl.pdf b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/everything-you-wanted-to-know-about-openssl.pdf new file mode 100644 index 00000000..9e6524f6 Binary files /dev/null and b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/everything-you-wanted-to-know-about-openssl.pdf differ diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.c b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.c new file mode 100644 index 00000000..066fd6dd --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.c @@ -0,0 +1,181 @@ +/* + * Helper functions to perform basic hostname validation using OpenSSL. + * + * Please read "everything-you-wanted-to-know-about-openssl.pdf" before + * attempting to use this code. This whitepaper describes how the code works, + * how it should be used, and what its limitations are. + * + * Author: Alban Diquet + * License: See LICENSE + * + */ + + +#include +#include +#include + +#include "openssl_hostname_validation.h" + + +#define HOSTNAME_MAX_SIZE 255 + +static int lowercase(int ch) { + if ('A' <= ch && ch <= 'Z') + return ch - 'A' + 'a'; + return ch; +} + +static int memeq_ncase(const char *x, const char *y, size_t l) { + if (l == 0) + return 1; + do { + if (lowercase(*x++) != lowercase(*y++)) + return 0; + } while (--l != 0); + return 1; +} + +static int has_nul(const char *s, size_t l) { + if (l == 0) + return 0; + do { + if (*s++ == '\0') + return 1; + } while (--l != 0); + return 0; +} + +static HostnameValidationResult validate_name(const char *hostname, ASN1_STRING *certname_asn1) { +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) + char *certname_s = (char *) ASN1_STRING_get0_data(certname_asn1); +#else + char *certname_s = (char *) ASN1_STRING_data(certname_asn1); +#endif + int certname_len = ASN1_STRING_length(certname_asn1), hostname_len = strlen(hostname); + + // Make sure there isn't an embedded NUL character in the DNS name + if (has_nul(certname_s, certname_len)) { + return MalformedCertificate; + } + // remove last '.' from hostname + if (hostname_len != 0 && hostname[hostname_len - 1] == '.') + --hostname_len; + // skip the first segment if wildcard + if (certname_len > 2 && certname_s[0] == '*' && certname_s[1] == '.') { + if (hostname_len != 0) { + do { + --hostname_len; + if (*hostname++ == '.') + break; + } while (hostname_len != 0); + } + certname_s += 2; + certname_len -= 2; + } + // Compare expected hostname with the DNS name + if (certname_len != hostname_len) { + return MatchNotFound; + } + return memeq_ncase(hostname, certname_s, hostname_len) ? MatchFound : MatchNotFound; +} + +/** +* Tries to find a match for hostname in the certificate's Common Name field. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if the Common Name had a NUL character embedded in it. +* Returns Error if the Common Name could not be extracted. +*/ +static HostnameValidationResult matches_common_name(const char *hostname, const X509 *server_cert) { + int common_name_loc = -1; + X509_NAME_ENTRY *common_name_entry = NULL; + ASN1_STRING *common_name_asn1 = NULL; + + // Find the position of the CN field in the Subject field of the certificate + common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) server_cert), NID_commonName, -1); + if (common_name_loc < 0) { + return Error; + } + + // Extract the CN field + common_name_entry = X509_NAME_get_entry(X509_get_subject_name((X509 *) server_cert), common_name_loc); + if (common_name_entry == NULL) { + return Error; + } + common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); + if (common_name_asn1 == NULL) { + return Error; + } + + // validate the names + return validate_name(hostname, common_name_asn1); +} + + +/** +* Tries to find a match for hostname in the certificate's Subject Alternative Name extension. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it. +* Returns NoSANPresent if the SAN extension was not present in the certificate. +*/ +static HostnameValidationResult matches_subject_alternative_name(const char *hostname, const X509 *server_cert) { + HostnameValidationResult result = MatchNotFound; + int i; + int san_names_nb = -1; + STACK_OF(GENERAL_NAME) *san_names = NULL; + + // Try to extract the names within the SAN extension from the certificate + san_names = X509_get_ext_d2i((X509 *) server_cert, NID_subject_alt_name, NULL, NULL); + if (san_names == NULL) { + return NoSANPresent; + } + san_names_nb = sk_GENERAL_NAME_num(san_names); + + // Check each name within the extension + for (i=0; itype == GEN_DNS) { + // Current name is a DNS name, let's check it + result = validate_name(hostname, current_name->d.dNSName); + if (result != MatchNotFound) { + break; + } + } + } + sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); + + return result; +} + + +/** +* Validates the server's identity by looking for the expected hostname in the +* server's certificate. As described in RFC 6125, it first tries to find a match +* in the Subject Alternative Name extension. If the extension is not present in +* the certificate, it checks the Common Name instead. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it. +* Returns Error if there was an error. +*/ +HostnameValidationResult validate_hostname(const char *hostname, const X509 *server_cert) { + HostnameValidationResult result; + + if((hostname == NULL) || (server_cert == NULL)) + return Error; + + // First try the Subject Alternative Names extension + result = matches_subject_alternative_name(hostname, server_cert); + if (result == NoSANPresent) { + // Extension was not found: try the Common Name + result = matches_common_name(hostname, server_cert); + } + + return result; +} diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.h b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.h new file mode 100644 index 00000000..ca4b9be9 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.h @@ -0,0 +1,40 @@ +/* + * Helper functions to perform basic hostname validation using OpenSSL. + * + * Please read "everything-you-wanted-to-know-about-openssl.pdf" before + * attempting to use this code. This whitepaper describes how the code works, + * how it should be used, and what its limitations are. + * + * Author: Alban Diquet + * License: See LICENSE + * + */ +#ifndef openssl_hostname_validation_h +#define openssl_hostname_validation_h + +#ifndef OPENSSL_HOSTNAME_VALIDATION_LINKAGE +#define OPENSSL_HOSTNAME_VALIDATION_LINKAGE extern +#endif + +typedef enum { + MatchFound, + MatchNotFound, + NoSANPresent, + MalformedCertificate, + Error +} HostnameValidationResult; + +/** +* Validates the server's identity by looking for the expected hostname in the +* server's certificate. As described in RFC 6125, it first tries to find a match +* in the Subject Alternative Name extension. If the extension is not present in +* the certificate, it checks the Common Name instead. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it. +* Returns Error if there was an error. +*/ +OPENSSL_HOSTNAME_VALIDATION_LINKAGE HostnameValidationResult validate_hostname(const char *hostname, const X509 *server_cert); + +#endif diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client new file mode 100755 index 00000000..054fd8cd Binary files /dev/null and b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client differ diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client.c b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client.c new file mode 100644 index 00000000..916a22ed --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client.c @@ -0,0 +1,142 @@ +/* + * Sample HTTPS client to demonstrate how to do certificate validation using + * OpenSSL. + * This client will securely connect to www.isecpartners.com:443 and print the + * server's response to an HTTP GET request. + * + * Please read "everything-you-wanted-to-know-about-openssl.pdf" before + * attempting to use this code. This whitepaper describes how the code works, + * how it should be used, and what its limitations are. + * + * Author: Alban Diquet + * License: See LICENSE + * + */ + +#include +#include +#include +#include + +#include "openssl_hostname_validation.h" + + +// Sample SSL client for https://www.isecpartners.com +#define TARGET_HOST "www.isecpartners.com" +#define TARGET_PORT "443" + +// CA certificate that signed www.isecpartners.com's certificate +#define TRUSTED_CA_PATHNAME "DigiCertHighAssuranceEVRootCA.pem" + + + +#define TARGET_SERVER TARGET_HOST":"TARGET_PORT +// 'High' cipher suites minus Anonymous DH and Camellia +#define SECURE_CIPHER_LIST "RC4-SHA:HIGH:!ADH:!AECDH:!CAMELLIA" + +/* Sends an HTTP GET and prints the server's response */ +static void send_http_get_and_print(BIO * sbio) { + int len; + char tmpbuf[1024]; + BIO * out = BIO_new_fp(stdout, BIO_NOCLOSE); + + BIO_puts(sbio, "GET / HTTP/1.0\n\n"); + for(;;) { + len = BIO_read(sbio, tmpbuf, 1024); + if(len <= 0) break; + BIO_write(out, tmpbuf, len); + } + BIO_free(out); +} + + +int main(int argc, char *argv[]) { + BIO *sbio; + SSL_CTX *ssl_ctx; + SSL *ssl; + X509 *server_cert; + + // Initialize OpenSSL + SSL_library_init(); + SSL_load_error_strings(); + + // Check OpenSSL PRNG + if(RAND_status() != 1) { + fprintf(stderr, "OpenSSL PRNG not seeded with enough data."); + goto error_1; + } + + ssl_ctx = SSL_CTX_new(TLSv1_client_method()); + + // Enable certificate validation + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); + // Configure the CA trust store to be used + if (SSL_CTX_load_verify_locations(ssl_ctx, TRUSTED_CA_PATHNAME, NULL) != 1) { + fprintf(stderr, "Couldn't load certificate trust store.\n"); + goto error_2; + } + + // Only support secure cipher suites + if (SSL_CTX_set_cipher_list(ssl_ctx, SECURE_CIPHER_LIST) != 1) + goto error_2; + + // Create the SSL connection + sbio = BIO_new_ssl_connect(ssl_ctx); + BIO_get_ssl(sbio, &ssl); + if(!ssl) { + fprintf(stderr, "Can't locate SSL pointer\n"); + goto error_3; + } + + // Do the SSL handshake + BIO_set_conn_hostname(sbio, TARGET_SERVER); + if(SSL_do_handshake(ssl) <= 0) { + // SSL Handshake failed + long verify_err = SSL_get_verify_result(ssl); + if (verify_err != X509_V_OK) { + // It failed because the certificate chain validation failed + fprintf(stderr, "Certificate chain validation failed: %s\n", X509_verify_cert_error_string(verify_err)); + } + else { + // It failed for another reason + ERR_print_errors_fp(stderr); + } + goto error_3; + } + + // Recover the server's certificate + server_cert = SSL_get_peer_certificate(ssl); + if (server_cert == NULL) { + // The handshake was successful although the server did not provide a certificate + // Most likely using an insecure anonymous cipher suite... get out! + goto error_4; + } + + // Validate the hostname + if (validate_hostname(TARGET_HOST, server_cert) != MatchFound) { + fprintf(stderr, "Hostname validation failed.\n"); + goto error_5; + } + + // Hostname validation succeeded; we can start sending data + send_http_get_and_print(sbio); + + +error_5: + X509_free(server_cert); + +error_4: + BIO_ssl_shutdown(sbio); + +error_3: + BIO_free_all(sbio); + +error_2: + SSL_CTX_free(ssl_ctx); + +error_1: // OpenSSL cleanup + EVP_cleanup(); + ERR_free_strings(); + + return 0; +} -- cgit v1.2.3