support loading SSL certificates

This commit is contained in:
David Rose 2002-09-27 15:27:28 +00:00
parent 907e6b55cb
commit 27107f5244
3 changed files with 141 additions and 19 deletions

View File

@ -79,16 +79,3 @@ get_proxy() const {
return _proxy; return _proxy;
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::make_ctx
// Access: Private
// Description: Creates the OpenSSL context object.
////////////////////////////////////////////////////////////////////
INLINE void HTTPClient::
make_ctx() {
if (!_ssl_initialized) {
initialize_ssl();
}
_ssl_ctx = SSL_CTX_new(SSLv23_client_method());
}

View File

@ -18,6 +18,9 @@
#include "httpClient.h" #include "httpClient.h"
#include "config_downloader.h" #include "config_downloader.h"
#include "filename.h"
#include "config_express.h"
#include "virtualFileSystem.h"
#ifdef HAVE_SSL #ifdef HAVE_SSL
@ -27,9 +30,43 @@
bool HTTPClient::_ssl_initialized = false; bool HTTPClient::_ssl_initialized = false;
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::load_certificates
// Access: Published
// Description: Reads the certificate(s) (delimited by -----BEGIN
// CERTIFICATE----- and -----END CERTIFICATE-----) from
// the indicated file and makes them known as trusted
// public keys for validating future connections.
// Returns true on success, false otherwise.
////////////////////////////////////////////////////////////////////
bool HTTPClient::
load_certificates(const Filename &filename) {
int result;
if (use_vfs) {
result = load_verify_locations(_ssl_ctx, filename);
} else {
string os_specific = filename.to_os_specific();
result =
SSL_CTX_load_verify_locations(_ssl_ctx, os_specific.c_str(), NULL);
}
if (result <= 0) {
downloader_cat.info()
<< "Could not load certificates from " << filename << ".\n";
#ifndef NDEBUG
ERR_print_errors_fp(stderr);
#endif
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_document // Function: HTTPClient::get_document
// Access: Published, Virtual // Access: Published
// Description: Opens the named document for reading, or if body is // Description: Opens the named document for reading, or if body is
// nonempty, posts data for a particular URL and // nonempty, posts data for a particular URL and
// retrieves the response. Returns a new HTTPDocument // retrieves the response. Returns a new HTTPDocument
@ -58,6 +95,39 @@ get_document(const URLSpec &url, const string &body) {
return new HTTPDocument(bio, true); return new HTTPDocument(bio, true);
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::make_ctx
// Access: Private
// Description: Creates the OpenSSL context object.
////////////////////////////////////////////////////////////////////
void HTTPClient::
make_ctx() {
if (!_ssl_initialized) {
initialize_ssl();
}
_ssl_ctx = SSL_CTX_new(SSLv23_client_method());
// Load in any default certificates listed in the Configrc file.
Config::ConfigTable::Symbol cert_files;
config_express.GetAll("ssl-certificates", cert_files);
// When we use GetAll(), we might inadvertently read duplicate
// lines. Filter them out with a set.
pset<string> already_read;
Config::ConfigTable::Symbol::iterator si;
for (si = cert_files.begin(); si != cert_files.end(); ++si) {
string cert_file = (*si).Val();
if (already_read.insert(cert_file).second) {
Filename filename = Filename::from_os_specific(cert_file);
if (load_certificates(filename)) {
downloader_cat.info()
<< "Appending SSL certificates from " << cert_file << "\n";
}
}
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::initialize_ssl // Function: HTTPClient::initialize_ssl
// Access: Private, Static // Access: Private, Static
@ -75,6 +145,66 @@ initialize_ssl() {
_ssl_initialized = true; _ssl_initialized = true;
} }
////////////////////////////////////////////////////////////////////
// Function: HTTPClient::load_verify_locations
// Access: Private, Static
// Description: An implementation of the OpenSSL-provided
// SSL_CTX_load_verify_locations() that takes a Filename
// (and supports Panda vfs).
//
// This reads the certificates from the named ca_file
// and makes them available to the given SSL context.
// It returns a positive number on success, or <= 0 on
// failure.
////////////////////////////////////////////////////////////////////
int HTTPClient::
load_verify_locations(SSL_CTX *ctx, const Filename &ca_file) {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
// First, read the complete file into memory.
string data;
if (!vfs->read_file(ca_file, data)) {
// Could not find or read file.
downloader_cat.info()
<< "Could not read " << ca_file << ".\n";
return 0;
}
STACK_OF(X509_INFO) *inf;
// Now create an in-memory BIO to read the "file" from the buffer we
// just read, and call the low-level routines to read the
// certificates from the BIO.
BIO *mbio = BIO_new_mem_buf((void *)data.data(), data.length());
inf = PEM_X509_INFO_read_bio(mbio, NULL, NULL, NULL);
BIO_free(mbio);
if (!inf) {
// Could not scan certificates.
return 0;
}
// Now add the certificates to the context.
X509_STORE *store = ctx->cert_store;
int count = 0;
for (int i = 0; i < sk_X509_INFO_num(inf); i++) {
X509_INFO *itmp = sk_X509_INFO_value(inf, i);
if (itmp->x509) {
X509_STORE_add_cert(store, itmp->x509);
count++;
} else if (itmp->crl) {
X509_STORE_add_crl(store, itmp->crl);
count++;
}
}
sk_X509_INFO_pop_free(inf, X509_INFO_free);
return count;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: HTTPClient::get_https // Function: HTTPClient::get_https
// Access: Private // Access: Private
@ -83,7 +213,7 @@ initialize_ssl() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BIO *HTTPClient:: BIO *HTTPClient::
get_http(const URLSpec &url, const string &body) { get_http(const URLSpec &url, const string &body) {
stringstream server; ostringstream server;
server << url.get_server() << ":" << url.get_port(); server << url.get_server() << ":" << url.get_port();
string server_str = server.str(); string server_str = server.str();
@ -116,7 +246,7 @@ get_https(const URLSpec &url, const string &body) {
nassertr(ssl != (SSL *)NULL, NULL); nassertr(ssl != (SSL *)NULL, NULL);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
stringstream server; ostringstream server;
server << url.get_server() << ":" << url.get_port(); server << url.get_server() << ":" << url.get_port();
string server_str = server.str(); string server_str = server.str();
@ -152,7 +282,7 @@ get_https(const URLSpec &url, const string &body) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
BIO *HTTPClient:: BIO *HTTPClient::
get_http_proxy(const URLSpec &url, const string &body) { get_http_proxy(const URLSpec &url, const string &body) {
stringstream proxy_server; ostringstream proxy_server;
proxy_server << _proxy.get_server() << ":" << _proxy.get_port(); proxy_server << _proxy.get_server() << ":" << _proxy.get_port();
string proxy_server_str = proxy_server.str(); string proxy_server_str = proxy_server.str();
@ -180,7 +310,7 @@ get_http_proxy(const URLSpec &url, const string &body) {
BIO *HTTPClient:: BIO *HTTPClient::
get_https_proxy(const URLSpec &url, const string &body) { get_https_proxy(const URLSpec &url, const string &body) {
// First, ask the proxy to open a connection for us. // First, ask the proxy to open a connection for us.
stringstream proxy_server; ostringstream proxy_server;
proxy_server << _proxy.get_server() << ":" << _proxy.get_port(); proxy_server << _proxy.get_server() << ":" << _proxy.get_port();
string proxy_server_str = proxy_server.str(); string proxy_server_str = proxy_server.str();

View File

@ -34,6 +34,8 @@
#include <openssl/ssl.h> #include <openssl/ssl.h>
class Filename;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : HTTPClient // Class : HTTPClient
// Description : Handles contacting an HTTP server and retrieving a // Description : Handles contacting an HTTP server and retrieving a
@ -49,11 +51,14 @@ PUBLISHED:
INLINE void set_proxy(const URLSpec &proxy); INLINE void set_proxy(const URLSpec &proxy);
INLINE const URLSpec &get_proxy() const; INLINE const URLSpec &get_proxy() const;
bool load_certificates(const Filename &filename);
PT(HTTPDocument) get_document(const URLSpec &url, const string &body = string()); PT(HTTPDocument) get_document(const URLSpec &url, const string &body = string());
private: private:
INLINE void make_ctx(); void make_ctx();
static void initialize_ssl(); static void initialize_ssl();
static int load_verify_locations(SSL_CTX *ctx, const Filename &ca_file);
BIO *get_http(const URLSpec &url, const string &body); BIO *get_http(const URLSpec &url, const string &body);
BIO *get_https(const URLSpec &url, const string &body); BIO *get_https(const URLSpec &url, const string &body);