mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
support wildcard certs
This commit is contained in:
parent
f4107d22ac
commit
7f4aa0e1d7
@ -21,6 +21,7 @@
|
||||
#include "config_downloader.h"
|
||||
#include "virtualFileMountHTTP.h"
|
||||
#include "ramfile.h"
|
||||
#include "globPattern.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -1669,36 +1670,7 @@ run_ssl_handshake() {
|
||||
if (_client->get_verify_ssl() != HTTPClient::VS_no_verify) {
|
||||
// Check that the server is someone we expected to be talking
|
||||
// to.
|
||||
string common_name = get_x509_name_component(subject, NID_commonName);
|
||||
string hostname = _request.get_url().get_server();
|
||||
|
||||
/*
|
||||
X509_STORE *store = OpenSSLWrapper::get_global_ptr()->get_x509_store();
|
||||
|
||||
// Create the X509_STORE_CTX for verifying the cert.
|
||||
X509_STORE_CTX *ctx = X509_STORE_CTX_new();
|
||||
X509_STORE_CTX_init(ctx, store, cert, NULL);
|
||||
X509_STORE_CTX_set_cert(ctx, cert);
|
||||
|
||||
if (!X509_verify_cert(ctx)) {
|
||||
int verify_result = X509_STORE_CTX_get_error(ctx);
|
||||
downloader_cat.info()
|
||||
<< "Server certificate from " << hostname
|
||||
<< " is invalid: " << verify_result << "\n";
|
||||
_status_entry._status_code = SC_ssl_invalid_server_certificate;
|
||||
}
|
||||
_state = S_failure;
|
||||
return false;
|
||||
}
|
||||
|
||||
X509_STORE_CTX_cleanup(ctx);
|
||||
X509_STORE_CTX_free(ctx);
|
||||
*/
|
||||
|
||||
if (common_name != hostname) {
|
||||
downloader_cat.info()
|
||||
<< "Server certificate from " << hostname
|
||||
<< " provides wrong name: " << common_name << "\n";
|
||||
if (!validate_server_name(cert)) {
|
||||
_status_entry._status_code = SC_ssl_unexpected_server;
|
||||
_state = S_failure;
|
||||
return false;
|
||||
@ -3341,6 +3313,115 @@ certificate signing
|
||||
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPChannel::validate_server_name
|
||||
// Access: Private
|
||||
// Description: Returns true if the name in the cert matches the
|
||||
// hostname of the server, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool HTTPChannel::
|
||||
validate_server_name(X509 *cert) {
|
||||
string hostname = _request.get_url().get_server();
|
||||
|
||||
vector_string cert_names;
|
||||
|
||||
// According to RFC 2818, we should check the DNS name(s) in the
|
||||
// subjectAltName extension first, if that extension exists.
|
||||
GENERAL_NAMES *subject_alt_names =
|
||||
(GENERAL_NAMES *)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
|
||||
if (subject_alt_names != NULL) {
|
||||
int num_alts = sk_GENERAL_NAME_num(subject_alt_names);
|
||||
for (int i = 0; i < num_alts; ++i) {
|
||||
// Get the ith alt name.
|
||||
const GENERAL_NAME *alt_name =
|
||||
sk_GENERAL_NAME_value(subject_alt_names, i);
|
||||
|
||||
if (alt_name->type == GEN_DNS) {
|
||||
char *buffer = NULL;
|
||||
ASN1_STRING_to_UTF8((unsigned char**)&buffer,
|
||||
alt_name->d.ia5);
|
||||
cert_names.push_back(buffer);
|
||||
OPENSSL_free(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cert_names.empty()) {
|
||||
// If there were no DNS names, use the common name instead.
|
||||
|
||||
X509_NAME *xname = X509_get_subject_name(cert);
|
||||
if (xname != NULL) {
|
||||
string common_name = get_x509_name_component(xname, NID_commonName);
|
||||
cert_names.push_back(common_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (cert_names.empty()) {
|
||||
downloader_cat.info()
|
||||
<< "Server certificate from " << hostname
|
||||
<< " provides no name.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (downloader_cat.is_debug()) {
|
||||
downloader_cat.debug()
|
||||
<< "Server certificate from " << hostname
|
||||
<< " provides name(s):";
|
||||
vector_string::const_iterator si;
|
||||
for (si = cert_names.begin(); si != cert_names.end(); ++si) {
|
||||
const string &cert_name = (*si);
|
||||
downloader_cat.debug(false)
|
||||
<< " " << cert_name;
|
||||
}
|
||||
downloader_cat.debug(false)
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Now validate the names we found. If any of them matches, the
|
||||
// cert matches.
|
||||
vector_string::const_iterator si;
|
||||
for (si = cert_names.begin(); si != cert_names.end(); ++si) {
|
||||
const string &cert_name = (*si);
|
||||
|
||||
if (match_cert_name(cert_name, hostname)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
downloader_cat.info()
|
||||
<< "Server certificate from " << hostname
|
||||
<< " provides wrong name(s):";
|
||||
for (si = cert_names.begin(); si != cert_names.end(); ++si) {
|
||||
const string &cert_name = (*si);
|
||||
downloader_cat.info(false)
|
||||
<< " " << cert_name;
|
||||
}
|
||||
downloader_cat.info(false)
|
||||
<< "\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPChannel::match_cert_name
|
||||
// Access: Private, Static
|
||||
// Description: Returns true if this particular name from the
|
||||
// certificate matches the indicated hostname, false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool HTTPChannel::
|
||||
match_cert_name(const string &cert_name, const string &hostname) {
|
||||
// We use GlobPattern to match the name. This isn't quite
|
||||
// consistent with RFC2818, since it also accepts additional
|
||||
// wildcard characters like "?" and "[]", but I think it's close
|
||||
// enough.
|
||||
|
||||
GlobPattern pattern(cert_name);
|
||||
pattern.set_case_sensitive(false);
|
||||
pattern.set_nomatch_chars(".");
|
||||
return pattern.matches(hostname);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HTTPChannel::get_x509_name_component
|
||||
// Access: Private, Static
|
||||
|
@ -249,6 +249,8 @@ private:
|
||||
|
||||
void check_socket();
|
||||
|
||||
bool validate_server_name(X509 *cert);
|
||||
static bool match_cert_name(const string &cert_name, const string &hostname);
|
||||
static string get_x509_name_component(X509_NAME *name, int nid);
|
||||
static bool x509_name_subset(X509_NAME *name_a, X509_NAME *name_b);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "openssl/rand.h"
|
||||
#include "openssl/err.h"
|
||||
#include "openssl/x509.h"
|
||||
#include "openssl/x509v3.h"
|
||||
|
||||
// Windows may define this macro inappropriately.
|
||||
#ifdef X509_NAME
|
||||
|
Loading…
x
Reference in New Issue
Block a user