add certlist package for pre-approved certificates

This commit is contained in:
David Rose 2009-11-04 00:09:01 +00:00
parent d19cf49e44
commit a784d86581
5 changed files with 144 additions and 37 deletions

View File

@ -64,6 +64,20 @@ class images(package):
config(**configDict)
class certlist(package):
# This package holds any certificates that should be considered
# pre-approved by the plugin vendor. If you build and host your
# own version of the Panda3D plugin, you can add your own
# certificates to this list. The certificates in this package
# will be assumed to have been approved by the user when he/she
# installed the plugin.
# They should be PEM-encoded and their filenames must end in the
# ".pem" or ".crt" extension, and they should be added with the
# extract = True flag so they will be extracted to disk.
file('/home/drose/mycertpub.pem', extract = True)
class p3dcert(package):
# This special application, used to pop up a dialog to prompt the
# user to accept or deny unknown applications, is its own package.

View File

@ -88,6 +88,7 @@ P3DInstance(P3D_request_ready_func *func,
_got_wparams = false;
_p3d_trusted = false;
_xpackage = NULL;
_certlist_package = NULL;
_p3dcert_package = NULL;
_fparams.set_tokens(tokens, num_tokens);
@ -102,7 +103,7 @@ P3DInstance(P3D_request_ready_func *func,
_allow_python_dev = false;
_keep_user_env = (_fparams.lookup_token_int("keep_user_env") != 0);
_auto_start = (_fparams.lookup_token_int("auto_start") != 0);
_auth_button_approved = false;
_auth_button_clicked = false;
_failed = false;
_session = NULL;
_auth_session = NULL;
@ -234,6 +235,11 @@ P3DInstance::
_image_package = NULL;
}
if (_certlist_package != NULL) {
_certlist_package->remove_instance(this);
_certlist_package = NULL;
}
if (_p3dcert_package != NULL) {
_p3dcert_package->remove_instance(this);
_p3dcert_package = NULL;
@ -539,6 +545,10 @@ set_browser_script_object(P3D_object *browser_script_object) {
P3D_OBJECT_DECREF(port);
}
if (_origin_hostname.empty() && _origin_protocol == "file:") {
_origin_hostname = "localhost";
}
if (_origin_port.empty()) {
// Maybe the actual URL doesn't include the port, in which
// case it is implicit.
@ -553,8 +563,11 @@ set_browser_script_object(P3D_object *browser_script_object) {
}
}
nout << "origin is " << _origin_protocol << "//" << _origin_hostname
<< ":" << _origin_port << "\n";
nout << "origin is " << _origin_protocol << "//" << _origin_hostname;
if (!_origin_port.empty()) {
nout << ":" << _origin_port;
}
nout << "\n";
}
@ -1244,20 +1257,14 @@ auth_finished_sub_thread() {
////////////////////////////////////////////////////////////////////
void P3DInstance::
auth_finished_main_thread() {
// Set this flag to indicate that the user has clicked on the red
// "auth" button. This eliminates the need to click on the green
// "start" button.
_auth_button_clicked = true;
// After the authorization program has returned, check the signature
// again.
if (check_p3d_signature()) {
// Set this flag to indicate that the user has clicked on the red
// "auth" button and successfully approved the application's
// certificate. This eliminates the need to click on the green
// "start" button.
_auth_button_approved = true;
mark_p3d_trusted();
} else {
// Still untrusted.
mark_p3d_untrusted();
}
check_p3d_signature();
}
////////////////////////////////////////////////////////////////////
@ -1292,11 +1299,7 @@ priv_set_p3d_filename(const string &p3d_filename) {
return;
}
if (check_p3d_signature()) {
mark_p3d_trusted();
} else {
mark_p3d_untrusted();
}
check_p3d_signature();
}
////////////////////////////////////////////////////////////////////
@ -1505,18 +1508,21 @@ check_matches_component(const string &orig, const string &match) {
// Function: P3DInstance::check_p3d_signature
// Access: Private
// Description: Checks the signature(s) encoded in the p3d file, and
// looks to see if any of them are recognized. Returns
// true if the signature is recognized and the file
// should be trusted, false otherwise.
// looks to see if any of them are recognized.
//
// If the signature is recognized, calls
// mark_p3d_trusted(); otherwise, calls
// mark_p3d_untrusted().
////////////////////////////////////////////////////////////////////
bool P3DInstance::
void P3DInstance::
check_p3d_signature() {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
if (inst_mgr->get_trusted_environment()) {
// If we're in a trusted environment (e.g. the panda3d command
// line, where we've already downloaded the p3d file separately),
// then everything is approved.
return true;
mark_p3d_trusted();
return;
}
// See if we've previously approved the certificate--any
@ -1531,12 +1537,33 @@ check_p3d_signature() {
// Look up the certificate to see if we've stored a copy in our
// certs dir.
if (inst_mgr->find_cert(cert)) {
return true;
mark_p3d_trusted();
return;
}
}
// Check the list of pre-approved certificates.
if (_certlist_package == NULL) {
// We have to go download this package.
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
P3DHost *host = inst_mgr->get_host(inst_mgr->get_host_url());
_certlist_package = host->get_package("certlist", "");
if (_certlist_package != NULL) {
_certlist_package->add_instance(this);
}
// When the package finishes downloading, we will come back here.
return;
}
if (!_certlist_package->get_ready() && !_certlist_package->get_failed()) {
// Wait for it to finish downloading.
return;
}
// Couldn't find any approved certificates.
return false;
mark_p3d_untrusted();
return;
}
////////////////////////////////////////////////////////////////////
@ -1714,7 +1741,7 @@ scan_app_desc_file(TiXmlDocument *doc) {
_matches_script_origin = true;
}
if (_auth_button_approved) {
if (_auth_button_clicked) {
// But finally, if the user has already clicked through the red
// "auth" button, no need to present him/her with another green
// "play" button as well.
@ -2279,15 +2306,21 @@ set_button_image(ImageType image_type) {
////////////////////////////////////////////////////////////////////
void P3DInstance::
report_package_info_ready(P3DPackage *package) {
if (package == _image_package || package == _p3dcert_package) {
// A special case: the image package and the p3dcert package get
// immediately downloaded, without waiting for anything else.
if (package == _p3dcert_package) {
// If we're downloading p3dcert, though, put up a progress bar.
if (package == _image_package || package == _certlist_package ||
package == _p3dcert_package) {
// A special case: these packages get immediately downloaded,
// without waiting for anything else.
if (package == _certlist_package || package == _p3dcert_package) {
// If we're downloading one of the two cert packages, though,
// put up a progress bar.
make_splash_window();
if (_splash_window != NULL) {
_splash_window->set_install_progress(0.0);
_splash_window->set_install_label("Getting Authorization Dialog");
if (package == _certlist_package) {
_splash_window->set_install_label("Getting Certificates");
} else {
_splash_window->set_install_label("Getting Authorization Dialog");
}
}
}
@ -2503,7 +2536,7 @@ report_package_progress(P3DPackage *package, double progress) {
// Ignore this.
return;
}
if (package == _p3dcert_package) {
if (package == _certlist_package || package == _p3dcert_package) {
// This gets its own progress bar.
if (_splash_window != NULL) {
_splash_window->set_install_progress(progress);
@ -2591,6 +2624,23 @@ report_package_done(P3DPackage *package, bool success) {
return;
}
if (package == _certlist_package) {
// Another special case: successfully downloading certlist (or
// failing to download it) means we can finish checking the
// authenticity of the p3d file.
// Take down the download progress.
if (_splash_window != NULL) {
_splash_window->set_install_progress(0.0);
_splash_window->set_install_label("");
}
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
inst_mgr->read_certlist(package);
check_p3d_signature();
return;
}
if (package == _p3dcert_package) {
// Another special case: successfully downloading p3dcert means we
// can enable the auth button.

View File

@ -165,7 +165,7 @@ private:
void separate_components(vector<string> &components, const string &str);
bool check_matches_component(const string &orig, const string &match);
bool check_p3d_signature();
void check_p3d_signature();
void mark_p3d_untrusted();
void mark_p3d_trusted();
void scan_app_desc_file(TiXmlDocument *doc);
@ -238,6 +238,10 @@ private:
bool _p3d_trusted;
TiXmlElement *_xpackage;
// Holds the list of certificates that are pre-approved by the
// plugin vendor.
P3DPackage *_certlist_package;
// For downloading the p3dcert authorization program.
P3DPackage *_p3dcert_package;
@ -252,7 +256,7 @@ private:
bool _allow_python_dev;
bool _keep_user_env;
bool _auto_start;
bool _auth_button_approved;
bool _auth_button_clicked;
bool _failed;
P3DSession *_session;

View File

@ -22,6 +22,7 @@
#include "p3dUndefinedObject.h"
#include "p3dNoneObject.h"
#include "p3dBoolObject.h"
#include "p3dPackage.h"
#include "find_root_dir.h"
#include "fileSpec.h"
#include "get_tinyxml.h"
@ -873,6 +874,42 @@ find_cert(X509 *cert) {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::read_certlist
// Access: Public
// Description: Reads the pre-approved certificates in the certlist
// package and adds them to the in-memory cache.
////////////////////////////////////////////////////////////////////
void P3DInstanceManager::
read_certlist(P3DPackage *package) {
nout << "reading certlist in " << package->get_package_dir() << "\n";
vector<string> contents;
scan_directory(package->get_package_dir(), contents);
vector<string>::iterator si;
for (si = contents.begin(); si != contents.end(); ++si) {
const string &basename = (*si);
if (basename.length() > 4) {
string suffix = basename.substr(basename.length() - 4);
if (suffix == ".pem" || suffix == ".crt") {
string filename = package->get_package_dir() + "/" + basename;
X509 *x509 = NULL;
FILE *fp = fopen(filename.c_str(), "r");
if (fp != NULL) {
x509 = PEM_read_X509(fp, NULL, NULL, (void *)"");
fclose(fp);
}
if (x509 != NULL) {
string der2 = cert_to_der(x509);
_approved_certs.insert(der2);
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_cert_dir
// Access: Public

View File

@ -35,6 +35,7 @@ class P3DInstance;
class P3DSession;
class P3DAuthSession;
class P3DHost;
class P3DPackage;
class FileSpec;
class TiXmlElement;
@ -120,6 +121,7 @@ public:
void release_temp_filename(const string &filename);
bool find_cert(X509 *cert);
void read_certlist(P3DPackage *package);
string get_cert_dir(X509 *cert);
static string cert_to_der(X509 *cert);