mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
support loading SSL certificates
This commit is contained in:
parent
907e6b55cb
commit
27107f5244
@ -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());
|
|
||||||
}
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user