Refactor Openssl certificate Subject Alternative Name logic. Review: https://reviews.apache.org/r/35853
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/69e0f5a2 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/69e0f5a2 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/69e0f5a2 Branch: refs/heads/master Commit: 69e0f5a29449835e8001614a4a0d54a6c456d4be Parents: ed84f36 Author: Joris Van Remoortere <[email protected]> Authored: Thu Jun 25 21:05:20 2015 -0700 Committer: Benjamin Hindman <[email protected]> Committed: Thu Jun 25 21:05:20 2015 -0700 ---------------------------------------------------------------------- 3rdparty/libprocess/src/openssl.cpp | 73 +++++++++++++++++--------------- 1 file changed, 38 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/69e0f5a2/3rdparty/libprocess/src/openssl.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/src/openssl.cpp b/3rdparty/libprocess/src/openssl.cpp index 090e985..40b60bf 100644 --- a/3rdparty/libprocess/src/openssl.cpp +++ b/3rdparty/libprocess/src/openssl.cpp @@ -389,7 +389,8 @@ void initialize() EXIT(EXIT_FAILURE) << "Could not load default CA file and/or directory"; } - VLOG(2) << "Using default CA file and/or directory"; + VLOG(2) << "Using default CA file '" << X509_get_default_cert_file() + << "' and/or directory '" << X509_get_default_cert_dir() << "'"; } // Set SSL peer verification callback. @@ -488,44 +489,46 @@ Try<Nothing> verify(const SSL* const ssl, const Option<string>& hostname) : Try<Nothing>(Nothing()); } - int extcount = X509_get_ext_count(cert); - if (extcount <= 0) { - X509_free(cert); - return Error("X509_get_ext_count failed: " + stringify(extcount)); - } - - for (int i = 0; i < extcount; i++) { - X509_EXTENSION* ext = X509_get_ext(cert, i); - - const string extstr = - OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); - - if (extstr == "subjectAltName") { -#if OPENSSL_VERSION_NUMBER <= 0x00909000L - X509V3_EXT_METHOD* method = X509V3_EXT_get(ext); -#else - const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext); -#endif - if (method == NULL) { - break; - } - - const unsigned char* data = ext->value->data; - - STACK_OF(CONF_VALUE)* values = method->i2v( - method, - method->d2i(NULL, &data, ext->value->length), - NULL); - - for (int j = 0; j < sk_CONF_VALUE_num(values); j++) { - CONF_VALUE* value = sk_CONF_VALUE_value(values, j); - if ((strcmp(value->name, "DNS") == 0) && - (value->value == hostname.get())) { + // From https://wiki.openssl.org/index.php/Hostname_validation. + // Check the Subject Alternate Name extension (SAN). This is useful + // for certificates that serve multiple physical hosts. + STACK_OF(GENERAL_NAME)* san_names = + reinterpret_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i( + reinterpret_cast<X509*>(cert), + NID_subject_alt_name, + NULL, + NULL)); + + if (san_names != NULL) { + int san_names_num = sk_GENERAL_NAME_num(san_names); + + // Check each name within the extension. + for (int i = 0; i < san_names_num; i++) { + const GENERAL_NAME* current_name = sk_GENERAL_NAME_value(san_names, i); + + if (current_name->type == GEN_DNS) { + // Current name is a DNS name, let's check it. + const string dns_name = + reinterpret_cast<char*>(ASN1_STRING_data(current_name->d.dNSName)); + + // Make sure there isn't an embedded NUL character in the DNS name. + const size_t length = ASN1_STRING_length(current_name->d.dNSName); + if (length != dns_name.length()) { + sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); X509_free(cert); - return Nothing(); + return Error( + "X509 certificate malformed: embedded NUL character in DNS name"); + } else { // Compare expected hostname with the DNS name. + if (hostname.get() == dns_name) { + sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); + X509_free(cert); + return Nothing(); + } } } } + + sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); } // If we still haven't verified the hostname, try doing it via
