From 54c3e34f6ee1ef7183320273684f52c1c72939e0 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 17 Sep 2009 22:52:52 +0000 Subject: [PATCH] getting somewhere --- direct/src/plugin/Sources.pp | 2 + direct/src/plugin/p3dCert.cxx | 195 ++++++++++++++++++-- direct/src/plugin/p3dCert.h | 37 +++- direct/src/plugin/p3dInstance.cxx | 153 +++++++++++++-- direct/src/plugin/p3dInstance.h | 8 + direct/src/plugin/p3dInstanceManager.cxx | 81 ++++++-- direct/src/plugin/p3dInstanceManager.h | 4 + direct/src/plugin/p3dSession.cxx | 8 - direct/src/plugin/p3d_plugin_composite1.cxx | 1 + 9 files changed, 422 insertions(+), 67 deletions(-) diff --git a/direct/src/plugin/Sources.pp b/direct/src/plugin/Sources.pp index 386ac6f871..484086b0b5 100644 --- a/direct/src/plugin/Sources.pp +++ b/direct/src/plugin/Sources.pp @@ -25,6 +25,7 @@ p3d_lock.h p3d_plugin.h \ p3d_plugin_config.h \ p3d_plugin_common.h \ + p3dAuthSession.h p3dAuthSession.I \ p3dBoolObject.h \ p3dConcreteSequence.h \ p3dConcreteStruct.h \ @@ -57,6 +58,7 @@ #define INCLUDED_SOURCES \ p3d_plugin.cxx \ + p3dAuthSession.cxx \ p3dBoolObject.cxx \ p3dConcreteSequence.cxx \ p3dConcreteStruct.cxx \ diff --git a/direct/src/plugin/p3dCert.cxx b/direct/src/plugin/p3dCert.cxx index 77130b0cf1..3e73ee2e49 100644 --- a/direct/src/plugin/p3dCert.cxx +++ b/direct/src/plugin/p3dCert.cxx @@ -14,6 +14,7 @@ #include "p3dCert.h" #include "wx/cmdline.h" +#include "wx/filename.h" #ifdef __WXMAC__ #include @@ -85,6 +86,7 @@ IMPLEMENT_APP(P3DCertApp) //////////////////////////////////////////////////////////////////// bool P3DCertApp:: OnInit() { + cerr << "OnInit\n"; // call the base class initialization method, currently it only parses a // few common command-line options but it could be do more in the future if (!wxApp::OnInit()) { @@ -103,8 +105,9 @@ OnInit() { SetFrontProcess(&psn); #endif - AuthDialog *dialog = new AuthDialog(_cert_filename, _ca_filename); + AuthDialog *dialog = new AuthDialog(_cert_filename, _cert_dir); SetTopWindow(dialog); + cerr << "got dialog " << dialog << "\n"; dialog->Show(true); // Return true to enter the main loop and wait for user input. @@ -132,7 +135,7 @@ OnInitCmdLine(wxCmdLineParser &parser) { bool P3DCertApp:: OnCmdLineParsed(wxCmdLineParser &parser) { _cert_filename = parser.GetParam(0); - _ca_filename = parser.GetParam(1); + _cert_dir = parser.GetParam(1); return true; } @@ -151,16 +154,19 @@ END_EVENT_TABLE() // Description: //////////////////////////////////////////////////////////////////// AuthDialog:: -AuthDialog(const wxString &cert_filename, const wxString &ca_filename) : - wxDialog(NULL, wxID_ANY, _T("New Panda3D Application"), wxDefaultPosition) +AuthDialog(const wxString &cert_filename, const wxString &cert_dir) : + wxDialog(NULL, wxID_ANY, _T("New Panda3D Application"), wxDefaultPosition), + _cert_dir(cert_dir) { + _view_cert_dialog = NULL; + _cert = NULL; _stack = NULL; _verify_result = -1; read_cert_file(cert_filename); get_common_name(); - verify_cert(ca_filename); + verify_cert(); layout(); } @@ -171,6 +177,10 @@ AuthDialog(const wxString &cert_filename, const wxString &ca_filename) : //////////////////////////////////////////////////////////////////// AuthDialog:: ~AuthDialog() { + if (_view_cert_dialog != NULL) { + _view_cert_dialog->Destroy(); + } + if (_cert != NULL) { X509_free(_cert); _cert = NULL; @@ -189,7 +199,7 @@ AuthDialog:: void AuthDialog:: run_clicked(wxCommandEvent &event) { cerr << "run\n"; - Destroy(); + approve_cert(); } //////////////////////////////////////////////////////////////////// @@ -200,6 +210,11 @@ run_clicked(wxCommandEvent &event) { void AuthDialog:: view_cert_clicked(wxCommandEvent &event) { cerr << "view cert\n"; + if (_view_cert_dialog != NULL) { + _view_cert_dialog->Destroy(); + } + _view_cert_dialog = new ViewCertDialog(this, _cert); + _view_cert_dialog->Show(); } //////////////////////////////////////////////////////////////////// @@ -213,6 +228,41 @@ cancel_clicked(wxCommandEvent &event) { Destroy(); } +//////////////////////////////////////////////////////////////////// +// Function: AuthDialog::approve_cert +// Access: Public +// Description: Writes the certificate into the _cert_dir, so +// that it will be found by the P3DInstanceManager and +// known to be approved. +//////////////////////////////////////////////////////////////////// +void AuthDialog:: +approve_cert() { + assert(_cert != NULL); + + // Make sure the directory exists. + wxFileName::Mkdir(_cert_dir, 0777, wxPATH_MKDIR_FULL); + + // Look for an unused filename. + wxString pathname; + int i = 1; + while (true) { + pathname.Printf(wxT("%s/p%d.crt"), _cert_dir.c_str(), i); + if (!wxFileName::FileExists(pathname)) { + break; + } + ++i; + } + + // Sure, there's a slight race condition right now: another process + // might attempt to create the same filename. So what. + FILE *fp = fopen(pathname.mb_str(), "w"); + if (fp != NULL) { + PEM_write_X509(fp, _cert); + fclose(fp); + } + Destroy(); +} + //////////////////////////////////////////////////////////////////// // Function: AuthDialog::read_cert_file // Access: Private @@ -246,7 +296,7 @@ read_cert_file(const wxString &cert_filename) { //////////////////////////////////////////////////////////////////// // Function: AuthDialog::get_common_name -// Access: Public +// Access: Private // Description: Extracts the common_name from the certificate. //////////////////////////////////////////////////////////////////// void AuthDialog:: @@ -286,12 +336,12 @@ get_common_name() { //////////////////////////////////////////////////////////////////// // Function: AuthDialog::verify_cert -// Access: Public +// Access: Private // Description: Checks whether the certificate is valid by the chain // and initializes _verify_status accordingly. //////////////////////////////////////////////////////////////////// void AuthDialog:: -verify_cert(const wxString &ca_filename) { +verify_cert() { if (_cert == NULL) { _verify_result = -1; return; @@ -301,17 +351,25 @@ verify_cert(const wxString &ca_filename) { X509_STORE *store = X509_STORE_new(); X509_STORE_set_default_paths(store); - // Read the trusted certificates. - FILE *fp = fopen(ca_filename.mb_str(), "r"); - if (fp == NULL) { - cerr << "Couldn't read " << ca_filename << "\n"; - } else { - X509 *c = PEM_read_X509(fp, NULL, NULL, (void *)""); - while (c != NULL) { - X509_STORE_add_cert(store, c); - c = PEM_read_X509(fp, NULL, NULL, (void *)""); + // Find the ca-bundle.crt. + char *p3dcert_root = getenv("P3DCERT_ROOT"); + if (p3dcert_root != NULL) { + wxString ca_filename = p3dcert_root; + ca_filename += "/ca-bundle.crt"; + + // Read the trusted certificates. + cerr << "Reading " << ca_filename.mb_str() << "\n";; + FILE *fp = fopen(ca_filename.mb_str(), "r"); + if (fp == NULL) { + cerr << "Couldn't read " << ca_filename.mb_str() << "\n"; + } else { + X509 *c = PEM_read_X509(fp, NULL, NULL, (void *)""); + while (c != NULL) { + X509_STORE_add_cert(store, c); + c = PEM_read_X509(fp, NULL, NULL, (void *)""); + } + fclose(fp); } - fclose(fp); } // Create the X509_STORE_CTX for verifying the cert and chain. @@ -430,3 +488,102 @@ get_text(wxString &header, wxString &text) { text.Printf(generic_error_cert_text, _verify_result); } } + + +// The event table for ViewCertDialog. +BEGIN_EVENT_TABLE(ViewCertDialog, wxDialog) + EVT_BUTTON(wxID_OK, ViewCertDialog::run_clicked) + EVT_BUTTON(wxID_CANCEL, ViewCertDialog::cancel_clicked) +END_EVENT_TABLE() + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +ViewCertDialog:: +ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) : + wxDialog(NULL, wxID_ANY, _T("View Certificate"), wxDefaultPosition), + _auth_dialog(auth_dialog), + _cert(cert) +{ + layout(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +ViewCertDialog:: +~ViewCertDialog() { + if (_auth_dialog != NULL) { + _auth_dialog->_view_cert_dialog = NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::run_clicked +// Access: Public +// Description: The user clicks the "Run" button. +//////////////////////////////////////////////////////////////////// +void ViewCertDialog:: +run_clicked(wxCommandEvent &event) { + cerr << "run\n"; + if (_auth_dialog != NULL){ + _auth_dialog->approve_cert(); + } + Destroy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::run_clicked +// Access: Public +// Description: The user clicks the "Cancel" button. +//////////////////////////////////////////////////////////////////// +void ViewCertDialog:: +cancel_clicked(wxCommandEvent &event) { + cerr << "cancel\n"; + Destroy(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ViewCertDialog::layout +// Access: Private +// Description: Arranges the text and controls within the dialog. +//////////////////////////////////////////////////////////////////// +void ViewCertDialog:: +layout() { + // Format the certificate text for display in the dialog. + assert(_cert != NULL); + + BIO *mbio = BIO_new(BIO_s_mem()); + X509_print(mbio, _cert); + + char *pp; + long pp_size = BIO_get_mem_data(mbio, &pp); + wxString cert_body(pp, wxConvUTF8, pp_size); + BIO_free(mbio); + + wxPanel *panel = new wxPanel(this); + wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); + + wxStaticText *text1 = new wxStaticText + (panel, wxID_ANY, cert_body, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); + vsizer->Add(text1, 0, wxCENTER | wxALL, 10); + + // Create the run / cancel buttons. + wxBoxSizer *bsizer = new wxBoxSizer(wxHORIZONTAL); + + wxButton *run_button = new wxButton(panel, wxID_OK, _T("Run")); + bsizer->Add(run_button, 0, wxALIGN_CENTER | wxALL, 5); + + wxButton *cancel_button = new wxButton(panel, wxID_CANCEL, _T("Cancel")); + bsizer->Add(cancel_button, 0, wxALIGN_CENTER | wxALL, 5); + + vsizer->Add(bsizer, 0, wxALIGN_CENTER | wxALL, 5); + + panel->SetSizer(vsizer); + panel->SetAutoLayout(true); + vsizer->Fit(this); +} diff --git a/direct/src/plugin/p3dCert.h b/direct/src/plugin/p3dCert.h index e2fbb161ef..bd32db72ac 100644 --- a/direct/src/plugin/p3dCert.h +++ b/direct/src/plugin/p3dCert.h @@ -27,6 +27,8 @@ #include using namespace std; +class ViewCertDialog; + //////////////////////////////////////////////////////////////////// // Class : P3DCertApp // Description : This is the wxApp that drives this application. @@ -39,7 +41,7 @@ public: private: wxString _cert_filename; - wxString _ca_filename; + wxString _cert_dir; }; //////////////////////////////////////////////////////////////////// @@ -54,25 +56,31 @@ private: //////////////////////////////////////////////////////////////////// class AuthDialog : public wxDialog { public: - AuthDialog(const wxString &cert_filename, const wxString &ca_filename); + AuthDialog(const wxString &cert_filename, const wxString &cert_dir); virtual ~AuthDialog(); void run_clicked(wxCommandEvent &event); void view_cert_clicked(wxCommandEvent &event); void cancel_clicked(wxCommandEvent &event); + void approve_cert(); + private: void read_cert_file(const wxString &cert_filename); void get_common_name(); - void verify_cert(const wxString &ca_filename); + void verify_cert(); void layout(); void get_text(wxString &header, wxString &text); +public: + ViewCertDialog *_view_cert_dialog; + private: // any class wishing to process wxWidgets events must use this macro DECLARE_EVENT_TABLE() + wxString _cert_dir; X509 *_cert; STACK *_stack; @@ -80,4 +88,27 @@ private: int _verify_result; }; +//////////////////////////////////////////////////////////////////// +// Class : ViewCertDialog +// Description : This is the detailed view of the particular +// certificate. +//////////////////////////////////////////////////////////////////// +class ViewCertDialog : public wxDialog { +public: + ViewCertDialog(AuthDialog *auth_dialog, X509 *cert); + virtual ~ViewCertDialog(); + + void run_clicked(wxCommandEvent &event); + void cancel_clicked(wxCommandEvent &event); + +private: + void layout(); + +private: + DECLARE_EVENT_TABLE() + + AuthDialog *_auth_dialog; + X509 *_cert; +}; + #endif diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 1b06ec9562..62751e3400 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -85,6 +85,7 @@ P3DInstance(P3D_request_ready_func *func, _got_fparams = false; _got_wparams = false; _p3d_trusted = false; + _p3dcert_package = NULL; _fparams.set_tokens(tokens, num_tokens); _fparams.set_args(argc, argv); @@ -96,6 +97,7 @@ P3DInstance(P3D_request_ready_func *func, _auto_start = false; _auth_button_approved = false; _session = NULL; + _auth_session = NULL; _panda3d = NULL; _splash_window = NULL; _instance_window_opened = false; @@ -140,6 +142,12 @@ P3DInstance:: ~P3DInstance() { assert(_session == NULL); + if (_auth_session != NULL) { + _auth_session->shutdown(false); + unref_delete(_auth_session); + _auth_session = NULL; + } + P3D_OBJECT_XDECREF(_browser_script_object); nout << "panda_script_object ref = " @@ -159,6 +167,11 @@ P3DInstance:: _image_package = NULL; } + if (_p3dcert_package != NULL) { + _p3dcert_package->remove_instance(this); + _p3dcert_package = NULL; + } + if (_splash_window != NULL) { delete _splash_window; _splash_window = NULL; @@ -929,20 +942,18 @@ splash_button_clicked_main_thread() { //////////////////////////////////////////////////////////////////// void P3DInstance:: auth_button_clicked() { - // Here's where we need to invoke the authorization program. cerr << "auth clicked\n"; - // 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 an successfully approved the application. This - // eliminates the need to click on the green "start" button. - _auth_button_approved = true; - mark_p3d_trusted(); - } else { - mark_p3d_untrusted(); + // Delete the previous session and create a new one. + if (_auth_session != NULL) { + _auth_session->shutdown(false); + unref_delete(_auth_session); + _auth_session = NULL; } + + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + _auth_session = inst_mgr->authorize_instance(this); + _auth_session->ref(); } //////////////////////////////////////////////////////////////////// @@ -962,6 +973,49 @@ play_button_clicked() { } } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstance::auth_finished_sub_thread +// Access: Public +// Description: Called by the P3DAuthSession code in a sub-thread +// when the auth dialog exits (for instance, because the +// user approved the certificate, or cancelled). +//////////////////////////////////////////////////////////////////// +void P3DInstance:: +auth_finished_sub_thread() { + TiXmlDocument *doc = new TiXmlDocument; + TiXmlElement *xrequest = new TiXmlElement("request"); + xrequest->SetAttribute("rtype", "notify"); + xrequest->SetAttribute("message", "authfinished"); + doc->LinkEndChild(xrequest); + + add_raw_request(doc); +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DInstance::auth_finished_main_thread +// Access: Public +// Description: Called only in the main thread, indirectly from +// auth_finished_sub_thread(), as the result of +// the user closing the auth dialog. +//////////////////////////////////////////////////////////////////// +void P3DInstance:: +auth_finished_main_thread() { + // 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(); + } +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstance::check_p3d_signature // Access: Private @@ -984,10 +1038,7 @@ check_p3d_signature() { // is complete. return true; - nout << "check_p3d_signature\n"; int num_signatures = _mf_reader.get_num_signatures(); - nout << "file has " << num_signatures << " signatures\n"; - for (int i = 0; i < num_signatures; ++i) { const P3DMultifileReader::CertChain &chain = _mf_reader.get_signature(i); @@ -1019,6 +1070,27 @@ void P3DInstance:: mark_p3d_untrusted() { // Failed test. nout << "p3d untrusted\n"; + + if (_p3dcert_package == NULL) { + // We have to go download this package. + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); + P3DHost *host = inst_mgr->get_host(PANDA_PACKAGE_HOST_URL); + _p3dcert_package = host->get_package("p3dcert", ""); + if (_p3dcert_package != NULL) { + _p3dcert_package->add_instance(this); + } + + // When the package finishes downloading, we will come back here. + return; + } + + if (!_p3dcert_package->get_ready()) { + // Wait for it to finish downloading. + return; + } + + // OK, we've got the authorization program; we can put up the red + // button now. set_background_image(IT_unauth); set_button_image(IT_auth_ready); make_splash_window(); @@ -1332,6 +1404,10 @@ handle_notify_request(const string &message) { // started Python yet). We use this as a sneaky way to forward // the event from the sub-thread to the main thread. splash_button_clicked_main_thread(); + + } else if (message == "authfinished") { + // Similarly for the "auth finished" message. + auth_finished_main_thread(); } } @@ -1506,7 +1582,9 @@ make_splash_window() { if (_image_package == NULL) { P3DHost *host = inst_mgr->get_host(PANDA_PACKAGE_HOST_URL); _image_package = host->get_package("images", ""); - _image_package->add_instance(this); + if (_image_package != NULL) { + _image_package->add_instance(this); + } } } @@ -1607,9 +1685,18 @@ set_button_image(ImageType image_type) { //////////////////////////////////////////////////////////////////// void P3DInstance:: report_package_info_ready(P3DPackage *package) { - if (package == _image_package) { - // A special case: the image package gets immediately downloaded, - // without waiting for anything else. + 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. + make_splash_window(); + if (_splash_window != NULL) { + _splash_window->set_install_progress(0.0); + _splash_window->set_install_label("Getting Authorization Dialog"); + } + } + package->activate_download(); return; } @@ -1785,6 +1872,18 @@ report_instance_progress(double progress) { //////////////////////////////////////////////////////////////////// void P3DInstance:: report_package_progress(P3DPackage *package, double progress) { + if (package == _image_package) { + // Ignore this. + return; + } + if (package == _p3dcert_package) { + // This gets its own progress bar. + if (_splash_window != NULL) { + _splash_window->set_install_progress(progress); + } + return; + } + if (_download_package_index >= (int)_downloading_packages.size() || package != _downloading_packages[_download_package_index]) { // Quietly ignore a download progress report from an unexpected @@ -1822,6 +1921,7 @@ report_package_done(P3DPackage *package, bool success) { nout << "No entry in image package\n"; return; } + cerr << "downloaded image_package\n"; for (int i = 0; i < (int)IT_none; ++i) { if (_image_files[i]._use_standard_image) { // This image indexes into the package. Go get the standard @@ -1838,6 +1938,7 @@ report_package_done(P3DPackage *package, bool success) { // still exists, put it up. if (_splash_window != NULL && _image_files[i]._image_placement != P3DSplashWindow::IP_none) { + cerr << "putting up image " << i << "\n"; P3DSplashWindow::ImagePlacement image_placement = _image_files[i]._image_placement; _splash_window->set_image_filename(image_filename, image_placement); } @@ -1847,6 +1948,22 @@ report_package_done(P3DPackage *package, bool success) { return; } + if (package == _p3dcert_package) { + // Another special case: successfully downloading p3dcert means we + // can enable the auth button. + + // Take down the download progress. + if (_splash_window != NULL) { + _splash_window->set_install_progress(0.0); + _splash_window->set_install_label(""); + } + + if (success) { + mark_p3d_untrusted(); + } + return; + } + if (success) { report_package_progress(package, 1.0); start_next_download(); diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index f6ffc14650..2844ff3f51 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -106,6 +106,9 @@ public: void auth_button_clicked(); void play_button_clicked(); + void auth_finished_sub_thread(); + void auth_finished_main_thread(); + private: class ImageDownload : public P3DFileDownload { public: @@ -209,6 +212,9 @@ private: P3DWindowParams _wparams; bool _p3d_trusted; + + // For downloading the p3dcert authorization program. + P3DPackage *_p3dcert_package; int _instance_id; string _session_key; @@ -219,6 +225,7 @@ private: bool _auth_button_approved; P3DSession *_session; + P3DAuthSession *_auth_session; #ifdef __APPLE__ // On OSX, we have to get a copy of the framebuffer data back from @@ -275,6 +282,7 @@ private: BakedRequests _baked_requests; friend class P3DSession; + friend class P3DAuthSession; friend class ImageDownload; friend class P3DWindowParams; friend class P3DPackage; diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index c4296a1b75..d21f510d7a 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -15,6 +15,7 @@ #include "p3dInstanceManager.h" #include "p3dInstance.h" #include "p3dSession.h" +#include "p3dAuthSession.h" #include "p3dHost.h" #include "p3d_plugin_config.h" #include "p3dWinSplashWindow.h" @@ -67,6 +68,8 @@ P3DInstanceManager() { _true_object = new P3DBoolObject(true); _false_object = new P3DBoolObject(false); + _auth_session = NULL; + #ifdef _WIN32 // Ensure the appropriate Windows common controls are available to // this application. @@ -110,6 +113,11 @@ P3DInstanceManager:: assert(_instances.empty()); assert(_sessions.empty()); + if (_auth_session != NULL) { + unref_delete(_auth_session); + _auth_session = NULL; + } + Hosts::iterator hi; for (hi = _hosts.begin(); hi != _hosts.end(); ++hi) { delete (*hi).second; @@ -381,6 +389,29 @@ finish_instance(P3DInstance *inst) { unref_delete(inst); } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::authorize_instance +// Access: Public +// Description: Creates a new P3DAuthSession object, to pop up a +// window for the user to authorize the certificate on +// this instance. Automatically terminates any +// previously-created P3DAuthSession. +//////////////////////////////////////////////////////////////////// +P3DAuthSession *P3DInstanceManager:: +authorize_instance(P3DInstance *inst) { + if (_auth_session != NULL) { + // We only want one auth_session window open at a time, to + // minimize user confusion, so close any previous window. + _auth_session->shutdown(true); + unref_delete(_auth_session); + _auth_session = NULL; + } + + _auth_session = new P3DAuthSession(inst); + _auth_session->ref(); + return _auth_session; +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::validate_instance // Access: Public @@ -678,25 +709,7 @@ find_cert(X509 *cert) { // OpenSSL's get_by_subject() approach, except we hash the whole // cert, not just the subject. (Since we also store self-signed // certs in this list, we can't trust the subject name alone.) - - static const size_t hash_size = 16; - unsigned char md[hash_size]; - - MD5_CTX ctx; - MD5_Init(&ctx); - MD5_Update(&ctx, der.data(), der.size()); - MD5_Final(md, &ctx); - - string basename; - static const size_t keep_hash = 6; - for (size_t i = 0; i < keep_hash; ++i) { - int high = (md[i] >> 4) & 0xf; - int low = md[i] & 0xf; - basename += P3DInstanceManager::encode_hexdigit(high); - basename += P3DInstanceManager::encode_hexdigit(low); - } - - string this_cert_dir = _certs_dir + "/" + basename; + string this_cert_dir = get_cert_dir(cert); nout << "looking in " << this_cert_dir << "\n"; vector contents; @@ -730,6 +743,36 @@ find_cert(X509 *cert) { return false; } +//////////////////////////////////////////////////////////////////// +// Function: P3DInstanceManager::get_cert_dir +// Access: Public +// Description: Returns the directory searched for this particular +// certificate. +//////////////////////////////////////////////////////////////////// +string P3DInstanceManager:: +get_cert_dir(X509 *cert) { + string der = cert_to_der(cert); + + static const size_t hash_size = 16; + unsigned char md[hash_size]; + + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, der.data(), der.size()); + MD5_Final(md, &ctx); + + string basename; + static const size_t keep_hash = 6; + for (size_t i = 0; i < keep_hash; ++i) { + int high = (md[i] >> 4) & 0xf; + int low = md[i] & 0xf; + basename += P3DInstanceManager::encode_hexdigit(high); + basename += P3DInstanceManager::encode_hexdigit(low); + } + + return _certs_dir + "/" + basename; +} + //////////////////////////////////////////////////////////////////// // Function: P3DInstanceManager::cert_to_der // Access: Public, Static diff --git a/direct/src/plugin/p3dInstanceManager.h b/direct/src/plugin/p3dInstanceManager.h index e8c08b4567..2a3d7afdba 100644 --- a/direct/src/plugin/p3dInstanceManager.h +++ b/direct/src/plugin/p3dInstanceManager.h @@ -33,6 +33,7 @@ class P3DInstance; class P3DSession; +class P3DAuthSession; class P3DHost; class FileSpec; class TiXmlElement; @@ -75,6 +76,7 @@ public: const string &p3d_filename); bool start_instance(P3DInstance *inst); void finish_instance(P3DInstance *inst); + P3DAuthSession *authorize_instance(P3DInstance *inst); P3DInstance *validate_instance(P3D_instance *instance); @@ -98,6 +100,7 @@ public: void release_temp_filename(const string &filename); bool find_cert(X509 *cert); + string get_cert_dir(X509 *cert); static string cert_to_der(X509 *cert); static P3DInstanceManager *get_global_ptr(); @@ -134,6 +137,7 @@ private: typedef set Instances; Instances _instances; + P3DAuthSession *_auth_session; typedef map Sessions; Sessions _sessions; diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index cb587b65f1..c5cc121ba9 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -816,7 +816,6 @@ start_p3dpython(P3DInstance *inst) { } } } - } // Define some new environment variables. @@ -964,13 +963,6 @@ start_p3dpython(P3DInstance *inst) { _pipe_write.open_write(to_fd[1]); #endif // _WIN32 - // Create the error stream for log output. This means opening the - // logfile, if we have one, or keeping the standard error if we - // don't. -#ifdef _WIN32 -#else // _WIN32 -#endif // _WIN32 - // Get the filename of the Panda3D multifile. We need to pass this // to p3dpython. _mf_filename = inst->_panda3d->get_archive_file_pathname(); diff --git a/direct/src/plugin/p3d_plugin_composite1.cxx b/direct/src/plugin/p3d_plugin_composite1.cxx index 063489081f..e03e738dbd 100644 --- a/direct/src/plugin/p3d_plugin_composite1.cxx +++ b/direct/src/plugin/p3d_plugin_composite1.cxx @@ -1,4 +1,5 @@ #include "p3d_plugin.cxx" +#include "p3dAuthSession.cxx" #include "p3dBoolObject.cxx" #include "p3dConcreteSequence.cxx" #include "p3dConcreteStruct.cxx"