Răsfoiți Sursa

signed multifiles

David Rose 16 ani în urmă
părinte
comite
3c0e701659

+ 0 - 3
panda/src/downloader/Sources.pp

@@ -35,7 +35,6 @@
     multiplexStreamBuf.I multiplexStreamBuf.h \
     patcher.h patcher.I \
     socketStream.h socketStream.I \
-    ssl_utils.h \
     stringStreamBuf.I stringStreamBuf.h \
     stringStream.I stringStream.h \
     urlSpec.I urlSpec.h \
@@ -66,7 +65,6 @@
     multiplexStream.cxx multiplexStreamBuf.cxx \
     patcher.cxx \
     socketStream.cxx \
-    ssl_utils.cxx \
     stringStreamBuf.cxx \
     stringStream.cxx \
     urlSpec.cxx \
@@ -99,7 +97,6 @@
     multiplexStreamBuf.I multiplexStreamBuf.h \
     patcher.h patcher.I \
     socketStream.h socketStream.I \
-    ssl_utils.h \
     stringStreamBuf.I stringStreamBuf.h \
     stringStream.I stringStream.h \
     urlSpec.h urlSpec.I \

+ 2 - 2
panda/src/downloader/bioStreamBuf.cxx

@@ -14,7 +14,7 @@
 
 #include "bioStreamBuf.h"
 #include "config_downloader.h"
-#include "ssl_utils.h"
+#include "openSSLWrapper.h"
 #include <errno.h>
 
 #ifdef HAVE_OPENSSL
@@ -199,7 +199,7 @@ underflow() {
             << "Lost connection to "
             << _source->get_server_name() << ":" 
             << _source->get_port() << " (" << read_count << ").\n";
-          notify_ssl_errors();
+          OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
 
           SSL *ssl = NULL;
           BIO_get_ssl(*_source, &ssl);

+ 1 - 4
panda/src/downloader/config_downloader.cxx

@@ -64,9 +64,6 @@ ConfigVariableInt patcher_buffer_size
 ConfigVariableList expected_ssl_server
 ("expected-ssl-server");
 
-ConfigVariableList ssl_certificates
-("ssl-certificates");
-
 ConfigVariableBool http_proxy_tunnel
 ("http-proxy-tunnel", false,
  PRC_DESC("This specifies the default value for HTTPChannel::set_proxy_tunnel().  "
@@ -145,7 +142,7 @@ init_libdownloader() {
               "library is loaded), or false to defer this until it is actually "
               "needed (which will be the first time you open an https connection "
               "or otherwise use encryption services).  You can also call "
-              "HTTPClient::initialize_ssl() to "
+              "HTTPClient::init_random_seed() to "
               "do this when you are ready.  The issue is that on Windows, "
               "OpenSSL will attempt to "
               "randomize its seed by crawling through the entire heap of "

+ 0 - 1
panda/src/downloader/config_downloader.h

@@ -39,7 +39,6 @@ extern ConfigVariableDouble extractor_step_time;
 extern ConfigVariableInt patcher_buffer_size;
 
 extern ConfigVariableList expected_ssl_server;
-extern ConfigVariableList ssl_certificates;
 
 extern ConfigVariableBool http_proxy_tunnel;
 extern ConfigVariableDouble http_connect_timeout;

+ 0 - 1
panda/src/downloader/downloader_composite2.cxx

@@ -13,7 +13,6 @@
 #include "multiplexStreamBuf.cxx"
 #include "patcher.cxx"
 #include "socketStream.cxx"
-#include "ssl_utils.cxx"
 #include "stringStreamBuf.cxx"
 #include "stringStream.cxx"
 #include "urlSpec.cxx"

+ 4 - 6
panda/src/downloader/httpChannel.cxx

@@ -16,7 +16,6 @@
 #include "httpClient.h"
 #include "httpCookie.h"
 #include "bioStream.h"
-#include "ssl_utils.h"
 #include "chunkedStream.h"
 #include "identityStream.h"
 #include "config_downloader.h"
@@ -26,7 +25,6 @@
 #include <stdio.h>
 
 #ifdef HAVE_OPENSSL
-#include "openssl/x509.h"
 
 #ifdef WIN32_VC
   #include <WinSock2.h>
@@ -989,7 +987,7 @@ run_connecting() {
     downloader_cat.info()
       << "Could not connect to " << _bio->get_server_name() << ":" 
       << _bio->get_port() << "\n";
-    notify_ssl_errors();
+    OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
     _status_entry._status_code = SC_no_connection;
     _state = S_try_next_proxy;
     return false;
@@ -1487,7 +1485,7 @@ run_setup_ssl() {
   if (result == 0) {
     downloader_cat.error()
       << "Invalid cipher list: '" << cipher_list << "'\n";
-    notify_ssl_errors();
+    OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
     _status_entry._status_code = SC_ssl_internal_failure;
     _state = S_failure;
     return false;
@@ -1563,7 +1561,7 @@ run_ssl_handshake() {
     downloader_cat.info()
       << "Could not establish SSL handshake with " 
       << _request.get_url().get_server_and_port() << "\n";
-    notify_ssl_errors();
+    OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
 
     // It seems to be an error to free sbio at this point; perhaps
     // it's already been freed?
@@ -2485,7 +2483,7 @@ begin_request(HTTPEnum::Method method, const DocumentSpec &url,
 
     } else {
       // Couldn't read the file.
-      notify_ssl_errors();
+      OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
       _status_entry._status_code = SC_no_connection;
       _state = S_failure;
     }

+ 10 - 181
panda/src/downloader/httpClient.cxx

@@ -15,7 +15,6 @@
 #include "httpClient.h"
 #include "httpChannel.h"
 #include "config_downloader.h"
-#include "ssl_utils.h"
 #include "filename.h"
 #include "config_express.h"
 #include "virtualFileSystem.h"
@@ -26,19 +25,6 @@
 
 #ifdef HAVE_OPENSSL
 
-#include "openssl/rand.h"
-#include "openssl/err.h"
-
-// Windows may define this macro inappropriately.
-#ifdef X509_NAME
-#undef X509_NAME
-#endif
-
-bool HTTPClient::_ssl_initialized = false;
-
-// This is created once and never freed.
-X509_STORE *HTTPClient::_x509_store = NULL;
-
 PT(HTTPClient) HTTPClient::_global_ptr;
 
 ////////////////////////////////////////////////////////////////////
@@ -183,10 +169,8 @@ HTTPClient() {
   _client_certificate_priv = NULL;
 
   // The first time we create an HTTPClient, we must initialize the
-  // OpenSSL library.
-  if (!_ssl_initialized) {
-    initialize_ssl();
-  }
+  // OpenSSL library.  The OpenSSLWrapper object does that.
+  OpenSSLWrapper::get_global_ptr();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -238,7 +222,6 @@ HTTPClient::
   // pointer from it, so it won't be destroyed along with it (this
   // object is shared among all contexts).
   if (_ssl_ctx != (SSL_CTX *)NULL) {
-    nassertv(_ssl_ctx->cert_store == _x509_store);
     _ssl_ctx->cert_store = NULL;
     SSL_CTX_free(_ssl_ctx);
   }
@@ -267,16 +250,9 @@ HTTPClient::
 ////////////////////////////////////////////////////////////////////
 void HTTPClient::
 init_random_seed() {
-  static bool _initialized = false;
-  if (!_initialized) {
-    _initialized = true;
-
-    // It is necessary to call this before making any other OpenSSL
-    // call, per the docs.  Also, the docs say that making this call
-    // will seed the random number generator.  Apparently you can get
-    // away with not calling it in versions prior to 0.9.8, however.
-    SSL_library_init();
-  }
+  // Creating the global OpenSSLWrapper object is nowadays sufficient
+  // to ensure that OpenSSL and its random seed have been initialized.
+  OpenSSLWrapper::get_global_ptr();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -995,26 +971,8 @@ parse_http_version_string(const string &version) {
 ////////////////////////////////////////////////////////////////////
 bool HTTPClient::
 load_certificates(const Filename &filename) {
-  // The line below might be a recursive call, but it should be safe,
-  // since get_ssl_ctx() won't call load_certificates() until after it
-  // has assigned _ssl_ctx--guaranteeing that the second call to
-  // get_ssl_ctx() will be a no-op.
-  SSL_CTX *ctx = get_ssl_ctx();
-
-  int result = load_verify_locations(ctx, filename);
-
-  if (result <= 0) {
-    downloader_cat.info()
-      << "Could not load certificates from " << filename << ".\n";
-    notify_ssl_errors();
-    return false;
-  }
-
-  downloader_cat.info()
-    << "Appending " << result << " SSL certificates from "
-    << filename << "\n";
-
-  return true;
+  OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr();
+  return sslw->load_certificates(filename);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1178,7 +1136,8 @@ get_ssl_ctx() {
 #endif
 
   // Make sure the error strings are loaded.
-  notify_ssl_errors();
+  OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr();
+  sslw->notify_ssl_errors();
 
   // Get the configured set of expected servers.
   int num_servers = expected_ssl_server.get_num_unique_values();
@@ -1187,29 +1146,7 @@ get_ssl_ctx() {
     add_expected_server(expected_server);
   }
 
-  if (_x509_store != (X509_STORE *)NULL) {
-    // If we've already created an x509 store object, share it with
-    // this context.  It would be better to make a copy of the store
-    // object for each context, so we could locally add certificates,
-    // but (a) there doesn't seem to be an interface for this, and (b)
-    // something funny about loading certificates that seems to save
-    // some persistent global state anyway.
-    SSL_CTX_set_cert_store(_ssl_ctx, _x509_store);
-
-  } else {
-    // Create the first x509 store object, and fill it up with our
-    // certificates.
-    _x509_store = X509_STORE_new();
-    SSL_CTX_set_cert_store(_ssl_ctx, _x509_store);
-
-    // Load in any default certificates listed in the Configrc file.
-    int num_certs = ssl_certificates.get_num_unique_values();
-    for (int ci = 0; ci < num_certs; ci++) {
-      string cert_file = ssl_certificates.get_unique_value(ci);
-      Filename filename = Filename::expand_from(cert_file);
-      load_certificates(filename);
-    }
-  }
+  SSL_CTX_set_cert_store(_ssl_ctx, sslw->get_x509_store());
 
   return _ssl_ctx;
 }
@@ -1461,114 +1398,6 @@ unload_client_certificate() {
   _client_certificate_loaded = false;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: HTTPClient::initialize_ssl
-//       Access: Private, Static
-//  Description: Called once the first time this class is used to
-//               initialize the OpenSSL library.
-////////////////////////////////////////////////////////////////////
-void HTTPClient::
-initialize_ssl() {
-  OpenSSL_add_all_algorithms();
-  _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, true)) {
-    // 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());
-
-  // We have to be sure and clear the OpenSSL error state before we
-  // call this function, or it will get confused.
-  ERR_clear_error();
-  inf = PEM_X509_INFO_read_bio(mbio, NULL, NULL, NULL);
-  BIO_free(mbio);
-
-  if (!inf) {
-    // Could not scan certificates.
-    downloader_cat.info()
-      << "PEM_X509_INFO_read_bio() returned NULL.\n";
-    notify_ssl_errors();
-    return 0;
-  }
-  
-  if (downloader_cat.is_spam()) {
-    downloader_cat.spam()
-      << "PEM_X509_INFO_read_bio() found " << sk_X509_INFO_num(inf)
-      << " entries.\n";
-  }
-
-  // Now add the certificates to the context.
-  X509_STORE *store = ctx->cert_store;
-
-  int count = 0;
-  int num_entries = sk_X509_INFO_num(inf);
-  for (int i = 0; i < num_entries; i++) {
-    X509_INFO *itmp = sk_X509_INFO_value(inf, i);
-
-    if (itmp->x509) {
-      X509_STORE_add_cert(store, itmp->x509);
-      count++;
-      if (downloader_cat.is_spam()) {
-        downloader_cat.spam()
-          << "Entry " << i << " is x509\n";
-      }
-
-    } else if (itmp->crl) {
-      X509_STORE_add_crl(store, itmp->crl);
-      count++;
-      if (downloader_cat.is_spam()) {
-        downloader_cat.spam()
-          << "Entry " << i << " is crl\n";
-      }
-
-    } else if (itmp->x_pkey) {
-      //      X509_STORE_add_crl(store, itmp->x_pkey);
-      //      count++;
-      if (downloader_cat.is_spam()) {
-        downloader_cat.spam()
-          << "Entry " << i << " is pkey\n";
-      }
-
-    } else {
-      if (downloader_cat.is_spam()) {
-        downloader_cat.spam()
-          << "Entry " << i << " is unknown type\n";
-      }
-    }
-  }
-  sk_X509_INFO_pop_free(inf, X509_INFO_free);
-
-  return count;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: HTTPClient::parse_x509_name
 //       Access: Private, Static

+ 1 - 14
panda/src/downloader/httpClient.h

@@ -23,7 +23,6 @@
 // communications.
 
 #ifdef HAVE_OPENSSL
-#define OPENSSL_NO_KRB5
 
 #include "urlSpec.h"
 #include "httpAuthorization.h"
@@ -35,13 +34,7 @@
 #include "pmap.h"
 #include "pset.h"
 #include "referenceCount.h"
-
-#include "openssl/ssl.h"
-
-// Windows may define this macro inappropriately.
-#ifdef X509_NAME
-#undef X509_NAME
-#endif
+#include "openSSLWrapper.h"
 
 class Filename;
 class HTTPChannel;
@@ -155,9 +148,6 @@ private:
 
   void unload_client_certificate();
 
-  static void initialize_ssl();
-  static int load_verify_locations(SSL_CTX *ctx, const Filename &ca_file);
-
   static X509_NAME *parse_x509_name(const string &source);
 
 #if defined(SSL_097) && !defined(NDEBUG)
@@ -206,9 +196,6 @@ private:
   X509 *_client_certificate_pub;
   EVP_PKEY *_client_certificate_priv;
 
-  static bool _ssl_initialized;
-  static X509_STORE *_x509_store;
-
   static PT(HTTPClient) _global_ptr;
 
   friend class HTTPChannel;

+ 0 - 52
panda/src/downloader/ssl_utils.cxx

@@ -1,52 +0,0 @@
-// Filename: ssl_utils.cxx
-// Created by:  drose (15Dec03)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) Carnegie Mellon University.  All rights reserved.
-//
-// All use of this software is subject to the terms of the revised BSD
-// license.  You should have received a copy of this license along
-// with this source code in a file named "LICENSE."
-//
-////////////////////////////////////////////////////////////////////
-
-#include "ssl_utils.h"
-#include "config_downloader.h"
-
-#ifdef HAVE_OPENSSL
-
-#ifdef REPORT_OPENSSL_ERRORS
-#include "openssl/err.h"
-#endif
-
-////////////////////////////////////////////////////////////////////
-//     Function: notify_ssl_errors
-//  Description: A convenience function that is itself a wrapper
-//               around the OpenSSL convenience function to output the
-//               recent OpenSSL errors.  This function sends the error
-//               string to downloader_cat.warning().  If
-//               REPORT_OPENSSL_ERRORS is not defined, the function
-//               does nothing.
-////////////////////////////////////////////////////////////////////
-void notify_ssl_errors() {
-#ifdef REPORT_OPENSSL_ERRORS
-  static bool strings_loaded = false;
-  if (!strings_loaded) {
-    SSL_load_error_strings();
-    strings_loaded = true;
-  }
-
-  unsigned long e = ERR_get_error();
-  while (e != 0) {
-    static const size_t buffer_len = 256;
-    char buffer[buffer_len];
-    ERR_error_string_n(e, buffer, buffer_len);
-    downloader_cat.warning() << buffer << "\n";
-    e = ERR_get_error();
-  }
-#endif  //  REPORT_OPENSSL_ERRORS
-}
-
-#endif  // HAVE_OPENSSL

+ 178 - 61
panda/src/downloadertools/multify.cxx

@@ -22,6 +22,7 @@
 #include "pointerTo.h"
 #include "filename.h"
 #include "pset.h"
+#include "vector_string.h"
 #include <stdio.h>
 #include <time.h>
 
@@ -47,6 +48,8 @@ Filename chdir_to;             // -C
 bool got_chdir_to = false;
 size_t scale_factor = 0;       // -F
 pset<string> dont_compress;    // -Z
+vector_string sign_params;     // -S
+pvector<Filename> cert_chain;  // -N
 
 // Default extensions not to compress.  May be overridden with -Z.
 string dont_compress_str = "jpg,png,mp3,ogg";
@@ -220,7 +223,27 @@ help() {
     "  -1 .. -9\n"
     "      Specify the compression level when -z is in effect.  Larger numbers\n"
     "      generate slightly smaller files, but compression takes longer.  The\n"
-    "      default is -" << default_compression_level << ".\n\n";
+    "      default is -" << default_compression_level << ".\n\n"
+
+    "  -N ca-chain.crt\n"
+    "      Adds the indicated certificate chain file to the multifile.  This must\n"
+    "      used in conjunction with -c or -u mode.  The indicated file must be\n"
+    "      a PEM-formatted collection of certificates, representing the chain of\n"
+    "      authentication from the certificate used to sign the multifile (-S,\n"
+    "      below), and a certificate authority.  This may be necessary for\n"
+    "      certain certificates whose signing authority is one or more steps\n"
+    "      removed from a well-known certificate authority.  You must add this\n"
+    "      file to the multifile before signing it (or at least at the same time).\n\n"
+
+    "  -S file.crt,file.key[,\"password\"]\n"
+    "      Sign the multifile.  The signing certificate should be in PEM form in\n"
+    "      file.crt, with its private key in PEM form in file.key.  If the key\n"
+    "      is encrypted on-disk, specify the decryption password as the third\n"
+    "      option.  PEM form is the form accepted by the Apache web server.  The\n"
+    "      signature is written to the multifile to prove it is unchanged; any\n"
+    "      subsequent change to the multifile will invalidate the signature.\n"
+    "      This parameter may be repeated to sign the multifile with different\n"
+    "      certificates.\n\n";
 }
 
 const string &
@@ -236,16 +259,17 @@ get_password() {
 
 
 bool
-is_named(const string &subfile_name, int argc, char *argv[]) {
+is_named(const string &subfile_name, const vector_string &params) {
   // Returns true if the indicated subfile appears on the list of
   // files named on the command line.
-  if (argc < 2) {
+  if (params.empty()) {
     // No named files; everything is listed.
     return true;
   }
 
-  for (int i = 1; i < argc; i++) {
-    if (subfile_name == argv[i]) {
+  vector_string::const_iterator pi;
+  for (pi = params.begin(); pi != params.end(); ++pi) {
+    if (subfile_name == (*pi)) {
       return true;
     }
   }
@@ -273,20 +297,39 @@ get_compression_level(const Filename &subfile_name) {
 }
 
 bool
-add_directory(Multifile *multifile, const Filename &directory_name) {
+do_add_files(Multifile *multifile, const pvector<Filename> &filenames,
+             bool cert_chain_flag);
+
+bool
+do_add_directory(Multifile *multifile, const Filename &directory_name,
+                 bool cert_chain_flag) {
   vector_string files;
   if (!directory_name.scan_directory(files)) {
     cerr << "Unable to scan directory " << directory_name << "\n";
     return false;
   }
 
-  bool okflag = true;
-
+  pvector<Filename> filenames;
+  filenames.reserve(files.size());
   vector_string::const_iterator fi;
   for (fi = files.begin(); fi != files.end(); ++fi) {
     Filename subfile_name(directory_name, (*fi));
+    filenames.push_back(subfile_name);
+  }
+
+  return do_add_files(multifile, filenames, cert_chain_flag);
+}
+
+bool
+do_add_files(Multifile *multifile, const pvector<Filename> &filenames,
+             bool cert_chain_flag) {
+  bool okflag = true;
+  pvector<Filename>::const_iterator fi;
+  for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
+    const Filename &subfile_name = (*fi);
+
     if (subfile_name.is_directory()) {
-      if (!add_directory(multifile, subfile_name)) {
+      if (!do_add_directory(multifile, subfile_name, cert_chain_flag)) {
         okflag = false;
       }
 
@@ -310,15 +353,20 @@ add_directory(Multifile *multifile, const Filename &directory_name) {
         if (verbose) {
           cout << new_subfile_name << "\n";
         }
+        if (cert_chain_flag) {
+          // Set the cert_chain flag on the file.
+          int index = multifile->find_subfile(new_subfile_name);
+          nassertr(index >= 0, false);
+          multifile->set_subfile_is_cert_chain(index, true);
+        }
       }
     }
   }
-
   return okflag;
 }
 
 bool
-add_files(int argc, char *argv[]) {
+add_files(const vector_string &params) {
   PT(Multifile) multifile = new Multifile;
   if (append || update) {
     if (!multifile->open_read_write(multifile_name)) {
@@ -350,36 +398,17 @@ add_files(int argc, char *argv[]) {
     multifile->set_scale_factor(scale_factor);
   }
 
-  bool okflag = true;
-  for (int i = 1; i < argc; i++) {
-    Filename subfile_name = Filename::from_os_specific(argv[i]);
-    if (subfile_name.is_directory()) {
-      if (!add_directory(multifile, subfile_name)) {
-        okflag = false;
-      }
-
-    } else if (!subfile_name.exists()) {
-      cerr << "Not found: " << subfile_name << "\n";
-      okflag = false;
+  pvector<Filename> filenames;
+  filenames.reserve(params.size());
+  vector_string::const_iterator si;
+  for (si = params.begin(); si != params.end(); ++si) {
+    Filename subfile_name = Filename::from_os_specific(*si);
+    filenames.push_back(subfile_name);
+  }
 
-    } else {
-      string new_subfile_name;
-      if (update) {
-        new_subfile_name = multifile->update_subfile
-          (subfile_name, subfile_name, get_compression_level(subfile_name));
-      } else {
-        new_subfile_name = multifile->add_subfile
-          (subfile_name, subfile_name, get_compression_level(subfile_name));
-      }
-      if (new_subfile_name.empty()) {
-        cerr << "Unable to add " << subfile_name << ".\n";
-        okflag = false;
-      } else {
-        if (verbose) {
-          cout << new_subfile_name << "\n";
-        }
-      }
-    }
+  bool okflag = do_add_files(multifile, filenames, false);
+  if (okflag && !cert_chain.empty()) {
+    okflag = do_add_files(multifile, cert_chain, true);
   }
 
   if (multifile->needs_repack()) {
@@ -398,7 +427,7 @@ add_files(int argc, char *argv[]) {
 }
 
 bool
-extract_files(int argc, char *argv[]) {
+extract_files(const vector_string &params) {
   if (!multifile_name.exists()) {
     cerr << multifile_name << " not found.\n";
     return false;
@@ -418,7 +447,7 @@ extract_files(int argc, char *argv[]) {
   bool any_encrypted = false;
   for (i = 0; i < num_subfiles && !any_encrypted; i++) {
     string subfile_name = multifile->get_subfile_name(i);
-    if (is_named(subfile_name, argc, argv)) {
+    if (is_named(subfile_name, params)) {
       if (multifile->is_subfile_encrypted(i)) {
         any_encrypted = true;
       }
@@ -432,7 +461,7 @@ extract_files(int argc, char *argv[]) {
   // Now walk back through the list and this time do the extraction.
   for (i = 0; i < num_subfiles; i++) {
     string subfile_name = multifile->get_subfile_name(i);
-    if (is_named(subfile_name, argc, argv)) {
+    if (is_named(subfile_name, params)) {
       Filename filename = subfile_name;
       if (got_chdir_to) {
         filename = Filename(chdir_to, subfile_name);
@@ -455,7 +484,7 @@ extract_files(int argc, char *argv[]) {
 }
 
 bool
-kill_files(int argc, char *argv[]) {
+kill_files(const vector_string &params) {
   if (!multifile_name.exists()) {
     cerr << multifile_name << " not found.\n";
     return false;
@@ -473,7 +502,7 @@ kill_files(int argc, char *argv[]) {
   int i = 0;
   while (i < multifile->get_num_subfiles()) {
     string subfile_name = multifile->get_subfile_name(i);
-    if (is_named(subfile_name, argc, argv)) {
+    if (is_named(subfile_name, params)) {
       Filename filename = subfile_name;
 
       if (verbose) {
@@ -502,6 +531,50 @@ kill_files(int argc, char *argv[]) {
   return okflag;
 }
 
+bool
+sign_multifile() {
+#ifndef HAVE_OPENSSL
+  cerr << "Cannot sign multifiles without OpenSSL compiled in.\n";
+  return false;
+
+#else  // HAVE_OPENSSL
+  // Re-open the Multifile, and sign it with the indicated certificate
+  // and key files.
+  PT(Multifile) multifile = new Multifile;
+  if (!multifile->open_read_write(multifile_name)) {
+    cerr << "Unable to re-open " << multifile_name << " for signing.\n";
+    return false;
+  }
+
+  vector_string::iterator si;
+  for (si = sign_params.begin(); si != sign_params.end(); ++si) {
+    const string &param = (*si);
+    size_t comma1 = param.find(',');
+    if (comma1 == string::npos) {
+      cerr << "Signing parameter requires a comma: " << param << "\n";
+      return false;
+    }
+    size_t comma2 = param.find(',', comma1 + 1);
+
+    Filename certificate = Filename::from_os_specific(param.substr(0, comma1));
+    Filename pkey;
+    string password;
+    if (comma2 != string::npos) {
+      pkey = Filename::from_os_specific(param.substr(comma1 + 1, comma2 - comma1 - 1));
+      password = param.substr(comma2 + 1);
+    } else {
+      pkey = Filename::from_os_specific(param.substr(comma1 + 1));
+    }
+
+    if (!multifile->add_signature(certificate, pkey, password)) {
+      return false;
+    }
+  }    
+
+  return true;
+#endif  // HAVE_OPENSSL
+}
+
 const char *
 format_timestamp(bool record_timestamp, time_t timestamp) {
   static const size_t buffer_size = 512;
@@ -533,7 +606,7 @@ format_timestamp(bool record_timestamp, time_t timestamp) {
 }
 
 bool
-list_files(int argc, char *argv[]) {
+list_files(const vector_string &params) {
   if (!multifile_name.exists()) {
     cerr << multifile_name << " not found.\n";
     return false;
@@ -546,15 +619,20 @@ list_files(int argc, char *argv[]) {
 
   int num_subfiles = multifile->get_num_subfiles();
   
+  int i;
   if (verbose) {
     cout << num_subfiles << " subfiles:\n" << flush;
-    for (int i = 0; i < num_subfiles; i++) {
+    for (i = 0; i < num_subfiles; i++) {
       string subfile_name = multifile->get_subfile_name(i);
-      if (is_named(subfile_name, argc, argv)) {
+      if (is_named(subfile_name, params)) {
         char encrypted_symbol = ' ';
         if (multifile->is_subfile_encrypted(i)) {
           encrypted_symbol = 'e';
         }
+        char cert_chain_symbol = ' ';
+        if (multifile->get_subfile_is_cert_chain(i)) {
+          cert_chain_symbol = 'N';
+        }
         if (multifile->is_subfile_compressed(i)) {
           size_t orig_length = multifile->get_subfile_length(i);
           size_t internal_length = multifile->get_subfile_internal_length(i);
@@ -563,24 +641,25 @@ list_files(int argc, char *argv[]) {
             ratio = (double)internal_length / (double)orig_length;
           }
           if (ratio > 1.0) {
-            printf("%12d worse %c %s %s\n",
+            printf("%12d worse %c%c %s %s\n",
                    (int)multifile->get_subfile_length(i),
-                   encrypted_symbol,
+                   encrypted_symbol, cert_chain_symbol,
                    format_timestamp(multifile->get_record_timestamp(),
                                     multifile->get_subfile_timestamp(i)),
                    subfile_name.c_str());
           } else {
-            printf("%12d  %3.0f%% %c %s %s\n",
+            printf("%12d  %3.0f%% %c%c %s %s\n",
                    (int)multifile->get_subfile_length(i),
-                   100.0 - ratio * 100.0, encrypted_symbol,
+                   100.0 - ratio * 100.0, 
+                   encrypted_symbol, cert_chain_symbol,
                    format_timestamp(multifile->get_record_timestamp(),
                                     multifile->get_subfile_timestamp(i)),
                    subfile_name.c_str());
           }
         } else {
-          printf("%12d       %c %s %s\n", 
+          printf("%12d       %c%c %s %s\n", 
                  (int)multifile->get_subfile_length(i),
-                 encrypted_symbol,
+                 encrypted_symbol, cert_chain_symbol,
                  format_timestamp(multifile->get_record_timestamp(),
                                   multifile->get_subfile_timestamp(i)),
                  subfile_name.c_str());
@@ -601,14 +680,35 @@ list_files(int argc, char *argv[]) {
       cout << "Multifile needs to be repacked.\n";
     }
   } else {
-    for (int i = 0; i < num_subfiles; i++) {
+    for (i = 0; i < num_subfiles; i++) {
       string subfile_name = multifile->get_subfile_name(i);
-      if (is_named(subfile_name, argc, argv)) {
+      if (is_named(subfile_name, params)) {
         cout << subfile_name << "\n";
       }
     }
   }
 
+#ifdef HAVE_OPENSSL
+  int num_signatures = multifile->get_num_signatures();
+  if (num_signatures != 0) {
+    multifile->load_certificate_chains();
+    cout << "\n";
+    for (i = 0; i < num_signatures; ++i) {
+      cout << "Signed by " << multifile->get_signature_common_name(i);
+      int verify_result = multifile->validate_signature_certificate(i);
+      if (verify_result == 0) {
+        cout << " (certificate validated)\n";
+      } else {
+        cout << " (certificate unknown, reason " << verify_result << ")\n";
+      }
+      if (verbose) {
+        multifile->write_signature_certificate(i, cout);
+        cout << "\n";
+      }
+    }
+  }
+#endif  // HAVE_OPENSSL
+
   return true;
 }
 
@@ -647,7 +747,7 @@ main(int argc, char *argv[]) {
 
   extern char *optarg;
   extern int optind;
-  static const char *optflags = "crutxkvz123456789Z:T:f:OC:ep:P:F:h";
+  static const char *optflags = "crutxkvz123456789Z:T:S:T:f:OC:ep:P:F:h";
   int flag = getopt(argc, argv, optflags);
   Filename rel_path;
   while (flag != EOF) {
@@ -715,6 +815,12 @@ main(int argc, char *argv[]) {
     case 'Z':
       dont_compress_str = optarg;
       break;
+    case 'N':
+      cert_chain.push_back(Filename::from_os_specific(optarg));
+      break;
+    case 'S':
+      sign_params.push_back(optarg);
+      break;
     case 'T':
       {
         int flag;
@@ -798,24 +904,35 @@ main(int argc, char *argv[]) {
   // Split out the extensions named by -Z into different words.
   tokenize_extensions(dont_compress_str, dont_compress);
 
+  // Build a list of remaining parameters.
+  vector_string params;
+  params.reserve(argc - 1);
+  for (int i = 1; i < argc; i++) {
+    params.push_back(argv[i]);
+  }
+
   bool okflag = true;
   if (create || append || update) {
-    okflag = add_files(argc, argv);
+    okflag = add_files(params);
   } else if (extract) {
     if (got_record_timestamp_flag) {
       cerr << "Warning: -T ignored on extract.\n";
     }
-    okflag = extract_files(argc, argv);
+    okflag = extract_files(params);
   } else if (kill_cmd) {
     if (got_record_timestamp_flag) {
       cerr << "Warning: -T ignored on kill.\n";
     }
-    okflag = kill_files(argc, argv);
+    okflag = kill_files(params);
   } else { // list
     if (got_record_timestamp_flag) {
       cerr << "Warning: -T ignored on list.\n";
     }
-    okflag = list_files(argc, argv);
+    okflag = list_files(params);
+  }
+
+  if (okflag && !sign_params.empty()) {
+    sign_multifile();
   }
 
   if (okflag) {

+ 3 - 0
panda/src/express/Sources.pp

@@ -35,6 +35,7 @@
     nodePointerToBase.h nodePointerToBase.I \
     nodePointerTo.h nodePointerTo.I \
     nodeReferenceCount.h nodeReferenceCount.I \
+    openSSLWrapper.h openSSLWrapper.I \
     ordered_vector.h ordered_vector.I ordered_vector.T \
     password_hash.h \
     patchfile.I patchfile.h \
@@ -88,6 +89,7 @@
     nodePointerToBase.cxx \
     nodePointerTo.cxx \
     nodeReferenceCount.cxx \
+    openSSLWrapper.cxx \
     ordered_vector.cxx \
     password_hash.cxx \
     patchfile.cxx \
@@ -147,6 +149,7 @@
     nodePointerToBase.h nodePointerToBase.I \
     nodePointerTo.h nodePointerTo.I \
     nodeReferenceCount.h nodeReferenceCount.I \
+    openSSLWrapper.h openSSLWrapper.I \
     ordered_vector.h ordered_vector.I ordered_vector.T \
     password_hash.h \
     patchfile.I patchfile.h \

+ 3 - 0
panda/src/express/config_express.cxx

@@ -69,6 +69,9 @@ ConfigVariableBool collect_tcp
 ConfigVariableDouble collect_tcp_interval
 ("collect-tcp-interval", 0.2);
 
+ConfigVariableList ssl_certificates
+("ssl-certificates");
+
 ////////////////////////////////////////////////////////////////////
 //     Function: init_libexpress
 //  Description: Initializes the library.  This must be called at

+ 3 - 0
panda/src/express/config_express.h

@@ -21,6 +21,8 @@
 
 #include "configVariableBool.h"
 #include "configVariableInt.h"
+#include "configVariableDouble.h"
+#include "configVariableList.h"
 
 // Include this so interrogate can find it.
 #include "executionEnvironment.h"
@@ -50,6 +52,7 @@ extern ConfigVariableBool keep_temporary_files;
 
 extern EXPCL_PANDAEXPRESS ConfigVariableBool collect_tcp;
 extern EXPCL_PANDAEXPRESS ConfigVariableDouble collect_tcp_interval;
+extern ConfigVariableList ssl_certificates;
 
 // Expose the Config variable for Python access.
 BEGIN_PUBLISH

+ 1 - 0
panda/src/express/express_composite1.cxx

@@ -21,6 +21,7 @@
 #include "nodePointerToBase.cxx"
 #include "nodePointerTo.cxx"
 #include "nodeReferenceCount.cxx"
+#include "openSSLWrapper.cxx"
 #include "ordered_vector.cxx"
 #include "patchfile.cxx"
 #include "password_hash.cxx"

+ 37 - 1
panda/src/express/multifile.I

@@ -436,15 +436,26 @@ Subfile() {
   _source = (istream *)NULL;
   _flags = 0;
   _compression_level = 0;
+#ifdef HAVE_OPENSSL
+  _pkey = NULL;
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: Multifile::Subfile::operator <
 //       Access: Public
-//  Description: 
+//  Description: Compares two Subfiles for proper sorting within the
+//               index.
 ////////////////////////////////////////////////////////////////////
 INLINE bool Multifile::Subfile::
 operator < (const Multifile::Subfile &other) const {
+  // This should only be called on normal subfiles, not on certificate
+  // files or signature files.  (We don't attempt to sort these
+  // special signature files.)
+  nassertr(!is_cert_special() && !other.is_cert_special(), false);
+
+  // Normal subfiles are simply sorted in alphabetical order by
+  // filename.
   return _name < other._name;
 }
 
@@ -484,3 +495,28 @@ INLINE bool Multifile::Subfile::
 is_data_invalid() const {
   return (_flags & SF_data_invalid) != 0;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: Multifile::Subfile::is_cert_special
+//       Access: Public
+//  Description: Returns true if this Subfile represents a signature
+//               record, which is treated specially; or false if it is
+//               an ordinary Subfile.
+////////////////////////////////////////////////////////////////////
+INLINE bool Multifile::Subfile::
+is_cert_special() const {
+  return (_flags & SF_signature) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Multifile::Subfile::get_last_byte_pos
+//       Access: Public
+//  Description: Returns the byte position within the Multifile of the
+//               last byte that contributes to this Subfile, either in
+//               the index record or in the subfile data.
+////////////////////////////////////////////////////////////////////
+INLINE streampos Multifile::Subfile::
+get_last_byte_pos() const {
+  return max(_index_start + (streampos)_index_length, 
+             _data_start + (streampos)_data_length) - (streampos)1;
+}

Fișier diff suprimat deoarece este prea mare
+ 743 - 78
panda/src/express/multifile.cxx


+ 37 - 0
panda/src/express/multifile.h

@@ -25,6 +25,7 @@
 #include "indirectLess.h"
 #include "referenceCount.h"
 #include "pvector.h"
+#include "openSSLWrapper.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : Multifile
@@ -81,6 +82,22 @@ PUBLISHED:
                      int compression_level);
   string update_subfile(const string &subfile_name, const Filename &filename,
                         int compression_level);
+
+#ifdef HAVE_OPENSSL
+  bool add_signature(const Filename &certificate, const Filename &pkey,
+                     const string &password = "");
+  bool add_signature(X509 *certificate, EVP_PKEY *pkey);
+
+  int get_num_signatures() const;
+  X509 *get_signature(int n) const;
+  string get_signature_subject_name(int n) const;
+  string get_signature_common_name(int n) const;
+  void write_signature_certificate(int n, ostream &out) const;
+
+  void load_certificate_chains();
+  int validate_signature_certificate(int n) const;
+#endif  // HAVE_OPENSSL
+
   BLOCKING bool flush();
   BLOCKING bool repack();
 
@@ -97,6 +114,8 @@ PUBLISHED:
   time_t get_subfile_timestamp(int index) const;
   bool is_subfile_compressed(int index) const;
   bool is_subfile_encrypted(int index) const;
+  void set_subfile_is_cert_chain(int index, bool flag);
+  bool get_subfile_is_cert_chain(int index) const;
 
   streampos get_index_end() const;
   streampos get_subfile_internal_start(int index) const;
@@ -128,6 +147,8 @@ private:
     SF_data_invalid   = 0x0004,
     SF_compressed     = 0x0008,
     SF_encrypted      = 0x0010,
+    SF_cert_chain     = 0x0020,
+    SF_signature      = 0x0040,
   };
 
   class Subfile {
@@ -145,9 +166,12 @@ private:
     INLINE bool is_deleted() const;
     INLINE bool is_index_invalid() const;
     INLINE bool is_data_invalid() const;
+    INLINE bool is_cert_special() const;
+    INLINE streampos get_last_byte_pos() const;
 
     string _name;
     streampos _index_start;
+    size_t _index_length;
     streampos _data_start;
     size_t _data_length;
     size_t _uncompressed_length;
@@ -156,6 +180,9 @@ private:
     Filename _source_filename;
     int _flags;
     int _compression_level;  // Not preserved on disk.
+#ifdef HAVE_OPENSSL
+    EVP_PKEY *_pkey;         // Not preserved on disk.
+#endif
   };
 
   INLINE streampos word_to_streampos(size_t word) const;
@@ -164,24 +191,34 @@ private:
   streampos pad_to_streampos(streampos fpos);
 
   void add_new_subfile(Subfile *subfile, int compression_level);
+  istream *open_read_subfile(Subfile *subfile);
   string standardize_subfile_name(const string &subfile_name) const;
+  static bool read_to_pvector(pvector<unsigned char> &result, istream &stream);
 
   void clear_subfiles();
   bool read_index();
   bool write_header();
 
+  void check_signatures();
 
   typedef ov_set<Subfile *, IndirectLess<Subfile> > Subfiles;
   Subfiles _subfiles;
   typedef pvector<Subfile *> PendingSubfiles;
   PendingSubfiles _new_subfiles;
   PendingSubfiles _removed_subfiles;
+  PendingSubfiles _cert_special;
+
+#ifdef HAVE_OPENSSL
+  typedef pvector<X509 *> Certificates;
+  Certificates _signatures;
+#endif
 
   IStreamWrapper *_read;
   ostream *_write;
   bool _owns_stream;
   streampos _next_index;
   streampos _last_index;
+  streampos _last_data_byte;
 
   bool _needs_repack;
   time_t _timestamp;

+ 2 - 20
panda/src/downloader/ssl_utils.h → panda/src/express/openSSLWrapper.I

@@ -1,5 +1,5 @@
-// Filename: ssl_utils.h
-// Created by:  drose (15Dec03)
+// Filename: openSSLWrapper.I
+// Created by:  drose (05Sep09)
 //
 ////////////////////////////////////////////////////////////////////
 //
@@ -12,21 +12,3 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifndef SSL_UTILS_H
-#define SSL_UTILS_H
-
-#include "pandabase.h"
-
-// This module is not compiled if OpenSSL is not available.
-#ifdef HAVE_OPENSSL
-#define OPENSSL_NO_KRB5
-
-#include "openssl/ssl.h"
-
-EXPCL_PANDAEXPRESS void notify_ssl_errors();
-
-#endif  // HAVE_OPENSSL
-
-#endif
-
-

+ 241 - 0
panda/src/express/openSSLWrapper.cxx

@@ -0,0 +1,241 @@
+// Filename: openSSLWrapper.cxx
+// Created by:  drose (05Sep09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "openSSLWrapper.h"
+
+#ifdef HAVE_OPENSSL
+
+#include "virtualFileSystem.h"
+
+OpenSSLWrapper *OpenSSLWrapper::_global_ptr = NULL;
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::Constructor
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+OpenSSLWrapper::
+OpenSSLWrapper() {
+  // It is necessary to call this before making any other OpenSSL
+  // call, per the docs.  Also, the docs say that making this call
+  // will seed the random number generator.  Apparently you can get
+  // away with not calling it in versions prior to 0.9.8, however.
+  SSL_library_init();
+
+  OpenSSL_add_all_algorithms();
+
+  _x509_store = X509_STORE_new();
+
+  // Load in any default certificates listed in the Config.prc file.
+  int num_certs = ssl_certificates.get_num_unique_values();
+  for (int ci = 0; ci < num_certs; ci++) {
+    string cert_file = ssl_certificates.get_unique_value(ci);
+    Filename filename = Filename::expand_from(cert_file);
+    load_certificates(filename);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::Destructor
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+OpenSSLWrapper::
+~OpenSSLWrapper() {
+  // Actually, the destructor is never called.
+  X509_STORE_free(_x509_store);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::load_certificates
+//       Access: Public
+//  Description: Reads the certificate(s) (delimited by -----BEGIN
+//               CERTIFICATE----- and -----END CERTIFICATE-----) from
+//               the indicated file and adds them to the global store
+//               object, retrieved via get_x509_store().  
+//
+//               Returns the number of certificates read on success,
+//               or 0 on failure.
+////////////////////////////////////////////////////////////////////
+int OpenSSLWrapper::
+load_certificates(const Filename &filename) {
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+
+  // First, read the complete file into memory.
+  string data;
+  if (!vfs->read_file(filename, data, true)) {
+    // Could not find or read file.
+    express_cat.info()
+      << "Could not read " << filename << ".\n";
+    return 0;
+  }
+
+  int result = load_certificates_from_ram(data.data(), data.size());
+
+  if (result <= 0) {
+    express_cat.info()
+      << "Could not load certificates from " << filename << ".\n";
+    notify_ssl_errors();
+    return 0;
+  }
+
+  express_cat.info()
+    << "Appending " << result << " SSL certificates from "
+    << filename << "\n";
+
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::load_certificates_from_ram
+//       Access: Public
+//  Description: Reads a chain of certificates from the indicated
+//               data buffer and adds them to the X509_STORE object.
+//               Returns the number of certificates read on success,
+//               or 0 on failure.
+////////////////////////////////////////////////////////////////////
+int OpenSSLWrapper::
+load_certificates_from_ram(const char *data, size_t data_size) {
+  STACK_OF(X509_INFO) *inf;
+
+  // Create an in-memory BIO to read the "file" from the buffer, and
+  // call the low-level routines to read the certificates from the
+  // BIO.
+  BIO *mbio = BIO_new_mem_buf((void *)data, data_size);
+
+  // We have to be sure and clear the OpenSSL error state before we
+  // call this function, or it will get confused.
+  ERR_clear_error();
+  inf = PEM_X509_INFO_read_bio(mbio, NULL, NULL, NULL);
+  BIO_free(mbio);
+
+  if (!inf) {
+    // Could not scan certificates.
+    express_cat.info()
+      << "PEM_X509_INFO_read_bio() returned NULL.\n";
+    notify_ssl_errors();
+    return 0;
+  }
+  
+  if (express_cat.is_spam()) {
+    express_cat.spam()
+      << "PEM_X509_INFO_read_bio() found " << sk_X509_INFO_num(inf)
+      << " entries.\n";
+  }
+
+  // Now add the certificates to the store.
+
+  int count = 0;
+  int num_entries = sk_X509_INFO_num(inf);
+  for (int i = 0; i < num_entries; i++) {
+    X509_INFO *itmp = sk_X509_INFO_value(inf, i);
+
+    if (itmp->x509) {
+      X509_STORE_add_cert(_x509_store, itmp->x509);
+      count++;
+      if (express_cat.is_spam()) {
+        express_cat.spam()
+          << "Entry " << i << " is x509\n";
+      }
+
+    } else if (itmp->crl) {
+      X509_STORE_add_crl(_x509_store, itmp->crl);
+      count++;
+      if (express_cat.is_spam()) {
+        express_cat.spam()
+          << "Entry " << i << " is crl\n";
+      }
+
+    } else if (itmp->x_pkey) {
+      //      X509_STORE_add_crl(_x509_store, itmp->x_pkey);
+      //      count++;
+      if (express_cat.is_spam()) {
+        express_cat.spam()
+          << "Entry " << i << " is pkey\n";
+      }
+
+    } else {
+      if (express_cat.is_spam()) {
+        express_cat.spam()
+          << "Entry " << i << " is unknown type\n";
+      }
+    }
+  }
+  sk_X509_INFO_pop_free(inf, X509_INFO_free);
+
+  return count;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::get_x509_store
+//       Access: Public
+//  Description: Returns the global X509_STORE object.
+//
+//               It has to be a global object, because OpenSSL seems
+//               to store some global pointers associated with this
+//               object whether you want it to or not, and keeping
+//               independent copies of a local X509_STORE object
+//               doesn't seem to work that well.  So, we have one
+//               store that keeps all certificates the application
+//               might need.
+////////////////////////////////////////////////////////////////////
+X509_STORE *OpenSSLWrapper::
+get_x509_store() {
+  return _x509_store;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::notify_ssl_errors
+//       Access: Public
+//  Description: A convenience function that is itself a wrapper
+//               around the OpenSSL convenience function to output the
+//               recent OpenSSL errors.  This function sends the error
+//               string to express_cat.warning().  If
+//               REPORT_OPENSSL_ERRORS is not defined, the function
+//               does nothing.
+////////////////////////////////////////////////////////////////////
+void OpenSSLWrapper::
+notify_ssl_errors() {
+#ifdef REPORT_OPENSSL_ERRORS
+  static bool strings_loaded = false;
+  if (!strings_loaded) {
+    SSL_load_error_strings();
+    strings_loaded = true;
+  }
+
+  unsigned long e = ERR_get_error();
+  while (e != 0) {
+    static const size_t buffer_len = 256;
+    char buffer[buffer_len];
+    ERR_error_string_n(e, buffer, buffer_len);
+    express_cat.warning() << buffer << "\n";
+    e = ERR_get_error();
+  }
+#endif  //  REPORT_OPENSSL_ERRORS
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::get_global_ptr
+//       Access: Public, Static
+//  Description: 
+////////////////////////////////////////////////////////////////////
+OpenSSLWrapper *OpenSSLWrapper::
+get_global_ptr() {
+  if (_global_ptr == NULL) {
+    _global_ptr = new OpenSSLWrapper;
+  }
+  return _global_ptr;
+}
+
+#endif  // HAVE_OPENSSL

+ 63 - 0
panda/src/express/openSSLWrapper.h

@@ -0,0 +1,63 @@
+// Filename: openSSLWrapper.h
+// Created by:  drose (05Sep09)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef OPENSSLWRAPPER_H
+#define OPENSSLWRAPPER_H
+
+#include "pandabase.h"
+
+#ifdef HAVE_OPENSSL
+
+#define OPENSSL_NO_KRB5
+#include "openssl/ssl.h"
+#include "openssl/rand.h"
+#include "openssl/err.h"
+#include "openssl/x509.h"
+
+// Windows may define this macro inappropriately.
+#ifdef X509_NAME
+#undef X509_NAME
+#endif
+
+////////////////////////////////////////////////////////////////////
+//       Class : OpenSSLWrapper
+// Description : Provides an interface wrapper around the OpenSSL
+//               library, to ensure that the library is properly
+//               initialized in the application, and to provide some
+//               hooks into global OpenSSL context data.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS OpenSSLWrapper {
+private:
+  OpenSSLWrapper();
+  ~OpenSSLWrapper();
+
+public:
+  int load_certificates(const Filename &filename);
+  int load_certificates_from_ram(const char *data, size_t data_size);
+  X509_STORE *get_x509_store();
+
+  void notify_ssl_errors();
+
+  static OpenSSLWrapper *get_global_ptr();
+
+private:
+  X509_STORE *_x509_store;
+
+  static OpenSSLWrapper *_global_ptr;
+};
+
+#include "openSSLWrapper.I"
+
+#endif  // HAVE_OPENSSL
+#endif

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff