convert express to new config system; add more options to pencrypt and OEncryptStream

This commit is contained in:
David Rose 2004-12-09 21:20:23 +00:00
parent 04ac1fd281
commit 18ced11d6c
17 changed files with 658 additions and 263 deletions

View File

@ -131,7 +131,7 @@ help() {
" encrypted using different passwords (although this requires running\n"
" multify multiple times). It is not possible to encrypt the multifile's\n"
" table of contents using this interface, but see the pencrypt program to\n"
" encrypt the entire multifile after it has been generated).\n\n"
" encrypt the entire multifile after it has been generated.\n\n"
" -p \"password\"\n"

View File

@ -46,17 +46,44 @@ usage() {
<< " Specifies the password to use for encryption. There are no\n"
<< " restrictions on the password length or contents, but longer passwords\n"
<< " are more secure. If this is not specified, the user is prompted from\n"
<< " standard input.\n\n";
<< " standard input.\n\n"
<< " -a \"algorithm\"\n"
<< " Specifies the particular encryption algorithm to use. The complete\n"
<< " set of available algorithms is defined by the current version of\n"
<< " OpenSSL. The default algorithm is taken from the encryption-\n"
<< " algorithm config variable.\n\n"
<< " -k key_length\n"
<< " Specifies the key length, in bits, for the selected encryption\n"
<< " algorithm. This only makes sense for those algorithms that support\n"
<< " a variable key length. The default value is taken from the\n"
<< " encryption-key-length config variable.\n\n"
<< " -i iteration_count\n"
<< " Specifies the number of times the password is hashed to generate\n"
<< " a key. The only purpose of this is to make it computationally\n"
<< " more expensive for an attacker to search the key space exhaustively.\n"
<< " This should be a multiple of 1,000 and should not exceed about 65\n"
<< " million; the value 0 indicates just one application of the hashing\n"
<< " algorithm. The default value is taken from the encryption-iteration-\n"
<< " count config variable.\n\n";
}
int
main(int argc, char *argv[]) {
extern char *optarg;
extern int optind;
const char *optstr = "p:h";
const char *optstr = "p:a:k:i:h";
string password;
bool got_password = false;
string algorithm;
bool got_algorithm = false;
int key_length = 0;
bool got_key_length = false;
int iteration_count = 0;
bool got_iteration_count = false;
int flag = getopt(argc, argv, optstr);
@ -67,6 +94,21 @@ main(int argc, char *argv[]) {
got_password = true;
break;
case 'a':
algorithm = optarg;
got_algorithm = true;
break;
case 'k':
key_length = atoi(optarg);
got_key_length = true;
break;
case 'i':
iteration_count = atoi(optarg);
got_iteration_count = true;
break;
case 'h':
case '?':
default:
@ -119,7 +161,17 @@ main(int argc, char *argv[]) {
bool fail = false;
{
OEncryptStream encrypt(&write_stream, false, password);
OEncryptStream encrypt;
if (got_algorithm) {
encrypt.set_algorithm(algorithm);
}
if (got_key_length) {
encrypt.set_key_length(key_length);
}
if (got_iteration_count) {
encrypt.set_iteration_count(iteration_count);
}
encrypt.open(&write_stream, false, password);
int ch = read_stream.get();
while (!read_stream.eof() && !read_stream.fail()) {

View File

@ -23,7 +23,7 @@
datagramGenerator.h \
datagramIterator.I datagramIterator.h datagramSink.I datagramSink.h \
dcast.T dcast.h \
encryptStreamBuf.h encryptStream.h encryptStream.I \
encryptStreamBuf.h encryptStreamBuf.I encryptStream.h encryptStream.I \
error_utils.h \
get_config_path.h \
hashGeneratorBase.I hashGeneratorBase.h \
@ -144,7 +144,7 @@
datagramGenerator.I datagramGenerator.h \
datagramIterator.I datagramIterator.h \
datagramSink.I datagramSink.h dcast.T dcast.h \
encryptStreamBuf.h encryptStream.h encryptStream.I \
encryptStreamBuf.h encryptStreamBuf.I encryptStream.h encryptStream.I \
error_utils.h get_config_path.h \
hashGeneratorBase.I \
hashGeneratorBase.h hashVal.I hashVal.h \

View File

@ -19,6 +19,7 @@
#include "clockObject.h"
#include "config_express.h"
#include "configVariableEnum.h"
#if defined(WIN32)
#define WINDOWS_LEAN_AND_MEAN
@ -243,10 +244,12 @@ void ClockObject::
make_global_clock() {
nassertv(_global_clock == (ClockObject *)NULL);
// Make sure we have run init_libexpress() by this time. This
// function is responsible for initializing the clock_mode Configrc
// variable.
init_libexpress();
ConfigVariableEnum<ClockObject::Mode> clock_mode
("clock-mode", ClockObject::M_normal,
"Specifies the mode of the global clock. The default mode, normal, "
"is a real-time clock; other modes allow non-real-time special "
"effects like simulated reduced frame rate. See "
"ClockObject::set_mode().");
_global_clock = new ClockObject;
_global_clock->set_mode(clock_mode);
@ -259,3 +262,52 @@ make_global_clock() {
void get_time_of_day(TimeVal &tv) {
get_true_time_of_day(tv.tv[0], tv.tv[1]);
}
////////////////////////////////////////////////////////////////////
// Function: ClockObject::Mode ostream operator
// Description:
////////////////////////////////////////////////////////////////////
ostream &
operator << (ostream &out, ClockObject::Mode mode) {
switch (mode) {
case ClockObject::M_normal:
return out << "normal";
case ClockObject::M_non_real_time:
return out << "non-real-time";
case ClockObject::M_forced:
return out << "forced";
case ClockObject::M_degrade:
return out << "degrade";
};
return out << "**invalid ClockObject::Mode(" << (int)mode << ")**";
}
////////////////////////////////////////////////////////////////////
// Function: ClockObject::Mode istream operator
// Description:
////////////////////////////////////////////////////////////////////
istream &
operator >> (istream &in, ClockObject::Mode &mode) {
string word;
in >> word;
if (word == "normal") {
mode = ClockObject::M_normal;
} else if (word == "non-real-time") {
mode = ClockObject::M_non_real_time;
} else if (word == "forced") {
mode = ClockObject::M_forced;
} else if (word == "degrade") {
mode = ClockObject::M_degrade;
} else {
express_cat.error()
<< "Invalid ClockObject::Mode: " << word << "\n";
mode = ClockObject::M_normal;
}
return in;
}

View File

@ -132,6 +132,9 @@ private:
static ClockObject *_global_clock;
};
ostream &operator << (ostream &out, ClockObject::Mode mode);
istream &operator >> (istream &in, ClockObject::Mode &mode);
#include "clockObject.I"
#endif

View File

@ -43,83 +43,94 @@ ConfigureFn(config_express) {
init_libexpress();
}
const int patchfile_window_size =
config_express.GetInt("patchfile-window-size", 16);
ConfigVariableInt patchfile_window_size
("patchfile-window-size", 16);
const int patchfile_increment_size =
config_express.GetInt("patchfile-increment-size", 8);
ConfigVariableInt patchfile_increment_size
("patchfile-increment-size", 8);
const int patchfile_buffer_size =
config_express.GetInt("patchfile-buffer-size", 4096);
ConfigVariableInt patchfile_buffer_size
("patchfile-buffer-size", 4096);
const int patchfile_zone_size =
config_express.GetInt("patchfile-zone-size", 10000);
ConfigVariableInt patchfile_zone_size
("patchfile-zone-size", 10000);
// Set this true to keep around the temporary files from downloading,
// decompressing, and patching, or false (the default) to delete
// these. Mainly useful for debugging when the process goes wrong.
const bool keep_temporary_files =
config_express.GetBool("keep-temporary-files", false);
ConfigVariableBool keep_temporary_files
("keep-temporary-files", false,
"Set this true to keep around the temporary files from downloading, "
"decompressing, and patching, or false (the default) to delete "
"these. Mainly useful for debugging when the process goes wrong.");
const double average_frame_rate_interval =
config_express.GetDouble("average-frame-rate-interval", 1.0);
ConfigVariableDouble average_frame_rate_interval
("average-frame-rate-interval", 1.0);
ClockObject::Mode clock_mode = ClockObject::M_normal;
const double clock_frame_rate =
config_express.GetDouble("clock-frame-rate", 1.0);
const double clock_degrade_factor =
config_express.GetDouble("clock-degrade-factor", 1.0);
const double max_dt =
config_express.GetDouble("max-dt", -1.0);
ConfigVariableDouble clock_frame_rate
("clock-frame-rate", 1.0);
ConfigVariableDouble clock_degrade_factor
("clock-degrade-factor", 1.0);
ConfigVariableDouble max_dt
("max-dt", -1.0);
// This is the accuracy within which we can expect select() to return
// precisely. That is, if we use select() to request a timeout of 1.0
// seconds, we can expect to actually sleep for somewhere between 1.0
// and 1.0 + sleep-precision seconds.
const double sleep_precision =
config_express.GetDouble("sleep-precision", 0.01);
ConfigVariableDouble sleep_precision
("sleep-precision", 0.01,
"This is the accuracy within which we can expect select() to return "
"precisely. That is, if we use select() to request a timeout of 1.0 "
"seconds, we can expect to actually sleep for somewhere between 1.0 "
"and 1.0 + sleep-precision seconds.");
// This defines the OpenSSL encryption algorithm which is used to
// encrypt any streams created by the current runtime. The default is
// Blowfish; the complete set of available algorithms is defined by
// the current version of OpenSSL. This value is used only to control
// encryption; the correct algorithm will automatically be selected on
// decryption.
const string encryption_algorithm =
config_express.GetString("encryption-algorithm", "bf-cbc");
ConfigVariableString encryption_algorithm
("encryption-algorithm", "bf-cbc",
"This defines the OpenSSL encryption algorithm which is used to "
"encrypt any streams created by the current runtime. The default is "
"Blowfish; the complete set of available algorithms is defined by "
"the current version of OpenSSL. This value is used only to control "
"encryption; the correct algorithm will automatically be selected on "
"decryption.");
// This defines the key length, in bits, for the selected encryption
// algorithm. Some algorithms have a variable key length. Specifying
// a value of 0 here means to use the default key length for the
// algorithm as defined by OpenSSL. This value is used only to
// control encryption; the correct key length will automatically be
// selected on decryption.
const int encryption_key_length =
config_express.GetInt("encryption-key-length", 0);
ConfigVariableInt encryption_key_length
("encryption-key-length", 0,
"This defines the key length, in bits, for the selected encryption "
"algorithm. Some algorithms have a variable key length. Specifying "
"a value of 0 here means to use the default key length for the "
"algorithm as defined by OpenSSL. This value is used only to "
"control encryption; the correct key length will automatically be "
"selected on decryption.");
// This defines the number of times a password is hashed to generate a
// key when encrypting. Its purpose is to make it computationally
// more expensive for an attacker to search the key space
// exhaustively. This should be a multiple of 1,000 and should not
// exceed about 65 million; the value 0 indicates just one application
// of the hashing algorithm. This value is used only to control
// encryption; the correct count will automatically be selected on
// decryption.
const int encryption_iteration_count =
config_express.GetInt("encryption-iteration-count", 100000);
ConfigVariableInt encryption_iteration_count
("encryption-iteration-count", 100000,
"This defines the number of times a password is hashed to generate a "
"key when encrypting. Its purpose is to make it computationally "
"more expensive for an attacker to search the key space "
"exhaustively. This should be a multiple of 1,000 and should not "
"exceed about 65 million; the value 0 indicates just one application "
"of the hashing algorithm. This value is used only to control "
"encryption; the correct count will automatically be selected on "
"decryption.");
// Set this true to use the VirtualFileSystem mechanism for loading
// models, etc. Since the VirtualFileSystem maps to the same as the
// actual file system by default, there is probably no reason to set
// this false, except for testing or if you mistrust the new code.
const bool use_vfs = config_express.GetBool("use-vfs", true);
ConfigVariableInt multifile_encryption_iteration_count
("multifile-encryption-iteration-count", 0,
"This is a special value of encryption-iteration-count used to encrypt "
"subfiles within a multifile. It has a default value of 0 (just one "
"application), on the assumption that the files from a multifile must "
"be loaded quickly, without paying the cost of an expensive hash on "
"each subfile in order to decrypt it.");
// Set this true to enable accumulation of several small consecutive
// TCP datagrams into one large datagram before sending it, to reduce
// overhead from the TCP/IP protocol. See
// Connection::set_collect_tcp() or SocketStream::set_collect_tcp().
const bool collect_tcp = config_express.GetBool("collect-tcp", false);
const double collect_tcp_interval = config_express.GetDouble("collect-tcp-interval", 0.2);
ConfigVariableBool use_vfs
("use-vfs", true,
"Set this true to use the VirtualFileSystem mechanism for loading "
"models, etc. Since the VirtualFileSystem maps to the same as the "
"actual file system by default, there is probably no reason to set "
"this false, except for testing or if you mistrust the new code.");
ConfigVariableBool collect_tcp
("collect-tcp", false,
"Set this true to enable accumulation of several small consecutive "
"TCP datagrams into one large datagram before sending it, to reduce "
"overhead from the TCP/IP protocol. See "
"Connection::set_collect_tcp() or SocketStream::set_collect_tcp().");
ConfigVariableDouble collect_tcp_interval
("collect-tcp-interval", 0.2);
////////////////////////////////////////////////////////////////////
// Function: init_libexpress
@ -151,115 +162,104 @@ init_libexpress() {
VirtualFileSimple::init_type();
init_system_type_handles();
string text_encoding = config_express.GetString("text-encoding", "iso8859");
if (text_encoding == "iso8859") {
TextEncoder::set_default_encoding(TextEncoder::E_iso8859);
} else if (text_encoding == "utf8") {
TextEncoder::set_default_encoding(TextEncoder::E_utf8);
} else if (text_encoding == "unicode") {
TextEncoder::set_default_encoding(TextEncoder::E_unicode);
} else {
express_cat.error()
<< "Invalid text-encoding: " << text_encoding << "\n";
}
string clock_mode_str = config_express.GetString("clock-mode", "normal");
if (clock_mode_str == "normal") {
clock_mode = ClockObject::M_normal;
} else if (clock_mode_str == "non-real-time") {
clock_mode = ClockObject::M_non_real_time;
} else if (clock_mode_str == "forced") {
clock_mode = ClockObject::M_forced;
} else if (clock_mode_str == "degrade") {
clock_mode = ClockObject::M_degrade;
} else {
express_cat.error()
<< "Invalid clock-mode: " << clock_mode_str << "\n";
}
}
// Set leak-memory true to disable the actual deletion of
// ReferenceCount-derived objects. This is sometimes useful to track
// a reference counting bug, since the formerly deleted objects will
// still remain (with a reference count of -100) without being
// overwritten with a newly-allocated object, and the assertion tests
// in ReferenceCount may more accurately detect the first instance of
// an error.
bool
get_leak_memory() {
static bool got_leak_memory = false;
static bool leak_memory;
static ConfigVariableBool *leak_memory = NULL;
if (!got_leak_memory) {
leak_memory = config_express.GetBool("leak-memory", false);
got_leak_memory = true;
if (leak_memory == (ConfigVariableBool *)NULL) {
leak_memory = new ConfigVariableBool
("leak-memory", false,
"Set leak-memory true to disable the actual deletion of "
"ReferenceCount-derived objects. This is sometimes useful to track "
"a reference counting bug, since the formerly deleted objects will "
"still remain (with a reference count of -100) without being "
"overwritten with a newly-allocated object, and the assertion tests "
"in ReferenceCount may more accurately detect the first instance of "
"an error.");
}
return leak_memory;
return *leak_memory;
}
// never-destruct is similar to leak-memory, above, except that not
// only will memory not be freed, but the destructor will not even be
// called (on ReferenceCount objects, at least). This will leak gobs
// of memory, but ensures that every pointer to a ReferenceCount
// object will always be valid, and may be useful for tracking down
// certain kinds of errors.
// never-destruct is only respected if leak-memory, above, is true.
bool
get_never_destruct() {
static bool got_never_destruct = false;
static bool never_destruct;
static ConfigVariableBool *never_destruct = NULL;
if (!got_never_destruct) {
never_destruct = config_express.GetBool("never-destruct", false);
got_never_destruct = true;
if (never_destruct == (ConfigVariableBool *)NULL) {
never_destruct = new ConfigVariableBool
("never-destruct", false,
"never-destruct is similar to leak-memory, except that not "
"only will memory not be freed, but the destructor will not even be "
"called (on ReferenceCount objects, at least). This will leak gobs "
"of memory, but ensures that every pointer to a ReferenceCount "
"object will always be valid, and may be useful for tracking down "
"certain kinds of errors. "
"never-destruct is only respected if leak-memory is true.");
}
return never_destruct;
return *never_destruct;
}
//const bool track_memory_usage = config_express.GetBool("track-memory-usage", false);
// Set this to false to avoid using the high-precision clock, even if
// it is available.
bool
get_use_high_res_clock() {
return config_express.GetBool("use-high-res-clock", true);
}
static ConfigVariableBool *use_high_res_clock = NULL;
// Set this to true to double-check the results of the high-resolution
// clock against the system clock. This has no effect if NDEBUG is
// defined.
bool
get_paranoid_clock() {
return config_express.GetBool("paranoid-clock", false);
}
// Set this to true to double-check the test for inheritance of
// TypeHandles, e.g. via is_of_type(). This has no effect if NDEBUG
// is defined.
bool
get_paranoid_inheritance() {
return config_express.GetBool("paranoid-inheritance", true);
}
// Set this to true to verify that every attempted DCAST operation in
// fact references the correct type, or false otherwise. This has no
// effect if NDEBUG is defined, in which case it is never tested.
bool
get_verify_dcast() {
static bool got_verify_dcast = false;
static bool verify_dcast;
if (!got_verify_dcast) {
verify_dcast = config_express.GetBool("verify-dcast", true);
got_verify_dcast = true;
if (use_high_res_clock == (ConfigVariableBool *)NULL) {
use_high_res_clock = new ConfigVariableBool
("use-high-res-clock", true,
"Set this to false to avoid using the high-precision clock, even if "
"it is available.");
}
return verify_dcast;
return *use_high_res_clock;
}
bool
get_paranoid_clock() {
static ConfigVariableBool *paranoid_clock = NULL;
if (paranoid_clock == (ConfigVariableBool *)NULL) {
paranoid_clock = new ConfigVariableBool
("paranoid-clock", false,
"Set this to true to double-check the results of the high-resolution "
"clock against the system clock. This has no effect if NDEBUG is "
"defined.");
}
return *paranoid_clock;
}
bool
get_paranoid_inheritance() {
static ConfigVariableBool *paranoid_inheritance = NULL;
if (paranoid_inheritance == (ConfigVariableBool *)NULL) {
paranoid_inheritance = new ConfigVariableBool
("paranoid-inheritance", true,
"Set this to true to double-check the test for inheritance of "
"TypeHandles, e.g. via is_of_type(). This has no effect if NDEBUG "
"is defined.");
}
return *paranoid_inheritance;
}
bool
get_verify_dcast() {
static ConfigVariableBool *verify_dcast = NULL;
if (verify_dcast == (ConfigVariableBool *)NULL) {
verify_dcast = new ConfigVariableBool
("verify-dcast", true,
"Set this to true to verify that every attempted DCAST operation in "
"fact references the correct type, or false otherwise. This has no "
"effect if NDEBUG is defined, in which case it is never tested.");
}
return *verify_dcast;
}
// Returns the configure object for accessing config variables from a

View File

@ -59,28 +59,28 @@ EXPCL_PANDAEXPRESS bool get_paranoid_clock();
EXPCL_PANDAEXPRESS bool get_paranoid_inheritance();
EXPCL_PANDAEXPRESS bool get_verify_dcast();
extern const int patchfile_window_size;
extern const int patchfile_increment_size;
extern const int patchfile_buffer_size;
extern const int patchfile_zone_size;
extern ConfigVariableInt patchfile_window_size;
extern ConfigVariableInt patchfile_increment_size;
extern ConfigVariableInt patchfile_buffer_size;
extern ConfigVariableInt patchfile_zone_size;
extern const bool keep_temporary_files;
extern const double average_frame_rate_interval;
extern ConfigVariableBool keep_temporary_files;
extern ConfigVariableDouble average_frame_rate_interval;
extern ClockObject::Mode clock_mode;
extern const double clock_frame_rate;
extern const double clock_degrade_factor;
extern const double max_dt;
extern const double sleep_precision;
extern ConfigVariableDouble clock_frame_rate;
extern ConfigVariableDouble clock_degrade_factor;
extern ConfigVariableDouble max_dt;
extern ConfigVariableDouble sleep_precision;
extern const string encryption_algorithm;
extern const int encryption_key_length;
extern const int encryption_iteration_count;
extern ConfigVariableString encryption_algorithm;
extern ConfigVariableInt encryption_key_length;
extern ConfigVariableInt encryption_iteration_count;
extern ConfigVariableInt multifile_encryption_iteration_count;
extern EXPCL_PANDAEXPRESS const bool use_vfs;
extern EXPCL_PANDAEXPRESS ConfigVariableBool use_vfs;
extern EXPCL_PANDAEXPRESS const bool collect_tcp;
extern EXPCL_PANDAEXPRESS const double collect_tcp_interval;
extern EXPCL_PANDAEXPRESS ConfigVariableBool collect_tcp;
extern EXPCL_PANDAEXPRESS ConfigVariableDouble collect_tcp_interval;
// Expose the Config variable for Python access.
BEGIN_PUBLISH

View File

@ -61,6 +61,38 @@ close() {
return *this;
}
////////////////////////////////////////////////////////////////////
// Function: IDecryptStream::get_algorithm
// Access: Public
// Description: Returns the encryption algorithm that was read from
// the stream.
////////////////////////////////////////////////////////////////////
INLINE const string &IDecryptStream::
get_algorithm() const {
return _buf.get_algorithm();
}
////////////////////////////////////////////////////////////////////
// Function: IDecryptStream::get_key_length
// Access: Public
// Description: Returns the encryption key length, in bits, that was
// read from the stream.
////////////////////////////////////////////////////////////////////
INLINE int IDecryptStream::
get_key_length() const {
return _buf.get_key_length();
}
////////////////////////////////////////////////////////////////////
// Function: IDecryptStream::get_iteration_count
// Access: Public
// Description: Returns the value that was was read from the stream.
////////////////////////////////////////////////////////////////////
INLINE int IDecryptStream::
get_iteration_count() const {
return _buf.get_iteration_count();
}
////////////////////////////////////////////////////////////////////
// Function: OEncryptStream::Constructor
@ -107,3 +139,59 @@ close() {
return *this;
}
////////////////////////////////////////////////////////////////////
// Function: OEncryptStream::set_algorithm
// Access: Public
// Description: Specifies the encryption algorithm that should be
// used for future calls to open(). The default
// is whatever is specified by the encryption-algorithm
// config variable. The complete set of available
// algorithms is defined by the current version of
// OpenSSL.
//
// If an invalid algorithm is specified, there is no
// immediate error return code, but open() will
// fail.
////////////////////////////////////////////////////////////////////
INLINE void OEncryptStream::
set_algorithm(const string &algorithm) {
_buf.set_algorithm(algorithm);
}
////////////////////////////////////////////////////////////////////
// Function: OEncryptStream::set_key_length
// Access: Public
// Description: Specifies the length of the key, in bits, that should
// be used to encrypt the stream in future calls to
// open(). The default is whatever is specified
// by the encryption-key-length config variable.
//
// If an invalid key_length for the chosen algorithm is
// specified, there is no immediate error return code,
// but open() will fail.
////////////////////////////////////////////////////////////////////
INLINE void OEncryptStream::
set_key_length(int key_length) {
_buf.set_key_length(key_length);
}
////////////////////////////////////////////////////////////////////
// Function: OEncryptStream::set_iteration_count
// Access: Public
// Description: Specifies the number of times to repeatedly hash the
// key before writing it to the stream in future calls
// to open(). Its purpose is to make it
// computationally more expensive for an attacker to
// search the key space exhaustively. This should be a
// multiple of 1,000 and should not exceed about 65
// million; the value 0 indicates just one application
// of the hashing algorithm.
//
// The default is whatever is specified by the
// encryption-iteration-count config variable.
////////////////////////////////////////////////////////////////////
INLINE void OEncryptStream::
set_iteration_count(int iteration_count) {
_buf.set_iteration_count(iteration_count);
}

View File

@ -48,6 +48,10 @@ public:
const string &password);
INLINE IDecryptStream &close();
INLINE const string &get_algorithm() const;
INLINE int get_key_length() const;
INLINE int get_iteration_count() const;
private:
EncryptStreamBuf _buf;
};
@ -73,6 +77,10 @@ public:
const string &password);
INLINE OEncryptStream &close();
INLINE void set_algorithm(const string &algorithm);
INLINE void set_key_length(int key_length);
INLINE void set_iteration_count(int iteration_count);
private:
EncryptStreamBuf _buf;
};

View File

@ -0,0 +1,110 @@
// Filename: encryptStreamBuf.I
// Created by: drose (09Dec04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: EncryptStreamBuf::set_algorithm
// Access: Public
// Description: Specifies the encryption algorithm that should be
// used for future calls to open_write(). The default
// is whatever is specified by the encryption-algorithm
// config variable. The complete set of available
// algorithms is defined by the current version of
// OpenSSL.
//
// If an invalid algorithm is specified, there is no
// immediate error return code, but open_write() will
// fail.
////////////////////////////////////////////////////////////////////
INLINE void EncryptStreamBuf::
set_algorithm(const string &algorithm) {
_algorithm = algorithm;
}
////////////////////////////////////////////////////////////////////
// Function: EncryptStreamBuf::get_algorithm
// Access: Public
// Description: Returns the encryption algorithm that was specified
// by set_algorithm(), or was read from the stream by
// the last successful open_read().
////////////////////////////////////////////////////////////////////
INLINE const string &EncryptStreamBuf::
get_algorithm() const {
return _algorithm;
}
////////////////////////////////////////////////////////////////////
// Function: EncryptStreamBuf::set_key_length
// Access: Public
// Description: Specifies the length of the key, in bits, that should
// be used to encrypt the stream in future calls to
// open_write(). The default is whatever is specified
// by the encryption-key-length config variable.
//
// If an invalid key_length for the chosen algorithm is
// specified, there is no immediate error return code,
// but open_write() will fail.
////////////////////////////////////////////////////////////////////
INLINE void EncryptStreamBuf::
set_key_length(int key_length) {
_key_length = key_length;
}
////////////////////////////////////////////////////////////////////
// Function: EncryptStreamBuf::get_key_length
// Access: Public
// Description: Returns the encryption key length, in bits, that was
// specified by set_key_length(), or was read from the
// stream by the last successful open_read().
////////////////////////////////////////////////////////////////////
INLINE int EncryptStreamBuf::
get_key_length() const {
return _key_length;
}
////////////////////////////////////////////////////////////////////
// Function: EncryptStreamBuf::set_iteration_count
// Access: Public
// Description: Specifies the number of times to repeatedly hash the
// key before writing it to the stream in future calls
// to open_write(). Its purpose is to make it
// computationally more expensive for an attacker to
// search the key space exhaustively. This should be a
// multiple of 1,000 and should not exceed about 65
// million; the value 0 indicates just one application
// of the hashing algorithm.
//
// The default is whatever is specified by the
// encryption-iteration-count config variable.
////////////////////////////////////////////////////////////////////
INLINE void EncryptStreamBuf::
set_iteration_count(int iteration_count) {
_iteration_count = iteration_count;
}
////////////////////////////////////////////////////////////////////
// Function: EncryptStreamBuf::get_iteration_count
// Access: Public
// Description: Returns the value that was specified by
// set_iteration_count(), or was read from the stream by
// the last successful open_read().
////////////////////////////////////////////////////////////////////
INLINE int EncryptStreamBuf::
get_iteration_count() const {
return _iteration_count;
}

View File

@ -46,6 +46,10 @@ EncryptStreamBuf() {
_dest = (ostream *)NULL;
_owns_dest = false;
_algorithm = encryption_algorithm;
_key_length = encryption_key_length;
_iteration_count = encryption_iteration_count;
_read_valid = false;
_write_valid = false;
@ -103,9 +107,17 @@ open_read(istream *source, bool owns_source, const string &password) {
return;
}
express_cat.debug()
<< "Using decryption algorithm " << OBJ_nid2sn(nid) << " with key length "
<< key_length * 8 << " bits.\n";
_algorithm = OBJ_nid2sn(nid);
_key_length = key_length * 8;
_iteration_count = count * iteration_count_factor;
if (express_cat.is_debug()) {
express_cat.debug()
<< "Using decryption algorithm " << _algorithm << " with key length "
<< _key_length << " bits.\n";
express_cat.debug()
<< "Key is hashed " << _iteration_count << " extra times.\n";
}
int iv_length = EVP_CIPHER_iv_length(cipher);
_read_block_size = EVP_CIPHER_block_size(cipher);
@ -186,11 +198,11 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
_write_valid = false;
const EVP_CIPHER *cipher =
EVP_get_cipherbyname(encryption_algorithm.c_str());
EVP_get_cipherbyname(_algorithm.c_str());
if (cipher == NULL) {
express_cat.error()
<< "Unknown encryption algorithm: " << encryption_algorithm << "\n";
<< "Unknown encryption algorithm: " << _algorithm << "\n";
return;
};
@ -210,7 +222,7 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
nassertv(result > 0);
// Store the appropriate key length in the context.
int key_length = (encryption_key_length + 7) / 8;
int key_length = (_key_length + 7) / 8;
if (key_length == 0) {
key_length = EVP_CIPHER_CTX_key_length(cipher);
}
@ -223,12 +235,18 @@ open_write(ostream *dest, bool owns_dest, const string &password) {
return;
}
express_cat.debug()
<< "Using encryption algorithm " << OBJ_nid2sn(nid) << " with key length "
<< key_length * 8 << " bits.\n";
int count = _iteration_count / iteration_count_factor;
if (express_cat.is_debug()) {
express_cat.debug()
<< "Using encryption algorithm " << OBJ_nid2sn(nid) << " with key length "
<< key_length * 8 << " bits.\n";
express_cat.debug()
<< "Hashing key " << count * iteration_count_factor
<< " extra times.\n";
}
// Hash the supplied password into a key of the appropriate length.
int count = encryption_iteration_count / iteration_count_factor;
unsigned char *key = (unsigned char *)alloca(key_length);
result =
PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(),

View File

@ -42,6 +42,15 @@ public:
void open_write(ostream *dest, bool owns_dest, const string &password);
void close_write();
INLINE void set_algorithm(const string &algorithm);
INLINE const string &get_algorithm() const;
INLINE void set_key_length(int key_length);
INLINE int get_key_length() const;
INLINE void set_iteration_count(int iteration_count);
INLINE int get_iteration_count() const;
protected:
virtual int overflow(int c);
virtual int sync(void);
@ -57,6 +66,10 @@ private:
ostream *_dest;
bool _owns_dest;
string _algorithm;
int _key_length;
int _iteration_count;
bool _read_valid;
EVP_CIPHER_CTX _read_ctx;
@ -69,6 +82,8 @@ private:
size_t _write_block_size;
};
#include "encryptStreamBuf.I"
#endif // HAVE_SSL
#endif

View File

@ -379,19 +379,19 @@ MemoryUsage() {
// time, and who knows when the code in config_express will be
// executed.
// track-memory-usage should be true to enable full-force tracking
// of C++ allocations and recordkeeping by type. It's quite
// expensive.
_track_memory_usage =
config_express.GetBool("track-memory-usage", false);
_track_memory_usage = ConfigVariableBool
("track-memory-usage", false,
"Set this to true to enable full-force tracking of C++ allocations "
"and recordkeeping by type. It's quite expensive.");
// count-memory-usage is a much lighter-weight version, and only
// tracks the total memory allocation. However, it only works for
// certain build environments (in particular, only in an Opt1 or
// Opt2 build on Windows).
#if defined(WIN32_VC) && defined(_DEBUG)
_count_memory_usage = config_express.GetBool("count-memory-usage",
_track_memory_usage);
_count_memory_usage = ConfigVariableBool
("count-memory-usage", _track_memory_usage,
"This is a much lighter-weight version of track-memory-usage, and it "
"only tracks the total memory allocation. However, it only exists in "
"certain build environments (in particular, only in an Opt1 or "
"Opt2 build on Windows.");
#else
_count_memory_usage = false;
#endif

View File

@ -1573,8 +1573,11 @@ write_data(ostream &write, istream *read, streampos fpos,
#else // HAVE_ZLIB
if ((_flags & SF_encrypted) != 0) {
// Write it encrypted.
putter = new OEncryptStream(putter, delete_putter,
multifile->_encryption_password);
OEncryptStream *encrypt = new OEncryptStream;
encrypt->set_iteration_count(multifile_encryption_iteration_count);
encrypt->open(putter, delete_putter, multifile->_encryption_password);
putter = encrypt;
delete_putter = true;
// Also write the encrypt_header to the beginning of the

View File

@ -21,7 +21,10 @@
#include "unicodeLatinMap.h"
TypeHandle TextEncoder::_type_handle;
TextEncoder::Encoding TextEncoder::_default_encoding;
ConfigVariableEnum<TextEncoder::Encoding> TextEncoder::_default_encoding
("default-encoding", TextEncoder::E_iso8859,
"Specifies how international characters are represented in strings "
"of 8-byte characters presented to Panda. See TextEncoder::set_encoding().");
////////////////////////////////////////////////////////////////////
// Function: TextEncoder::make_upper
@ -321,3 +324,47 @@ expand_amp_sequence(StringDecoder &decoder) const {
}
*/
////////////////////////////////////////////////////////////////////
// Function: TextEncoder::Encoding ostream operator
// Description:
////////////////////////////////////////////////////////////////////
ostream &
operator << (ostream &out, TextEncoder::Encoding encoding) {
switch (encoding) {
case TextEncoder::E_iso8859:
return out << "iso8859";
case TextEncoder::E_utf8:
return out << "utf8";
case TextEncoder::E_unicode:
return out << "unicode";
};
return out << "**invalid TextEncoder::Encoding(" << (int)encoding << ")**";
}
////////////////////////////////////////////////////////////////////
// Function: TextEncoder::Encoding istream operator
// Description:
////////////////////////////////////////////////////////////////////
istream &
operator >> (istream &in, TextEncoder::Encoding &encoding) {
string word;
in >> word;
if (word == "iso8859") {
encoding = TextEncoder::E_iso8859;
} else if (word == "utf8") {
encoding = TextEncoder::E_utf8;
} else if (word == "unicode") {
encoding = TextEncoder::E_unicode;
} else {
express_cat.error()
<< "Invalid TextEncoder::Encoding: " << word << "\n";
encoding = TextEncoder::E_iso8859;
}
return in;
}

View File

@ -21,6 +21,7 @@
#include "pandabase.h"
#include "unicodeLatinMap.h"
#include "configVariableEnum.h"
class StringDecoder;
@ -112,7 +113,7 @@ private:
string _text;
wstring _wtext;
static Encoding _default_encoding;
static ConfigVariableEnum<Encoding> _default_encoding;
public:
static TypeHandle get_class_type() {
@ -126,6 +127,9 @@ private:
static TypeHandle _type_handle;
};
ostream &operator << (ostream &out, TextEncoder::Encoding encoding);
istream &operator >> (istream &in, TextEncoder::Encoding &encoding);
#include "textEncoder.I"
#endif

View File

@ -504,72 +504,67 @@ get_global_ptr() {
_global_ptr->chdir(ExecutionEnvironment::get_cwd());
// Then, we add whatever mounts are listed in the Configrc file.
Config::ConfigTable::Symbol mounts;
config_express.GetAll("vfs-mount", mounts);
ConfigVariableList mounts
("vfs-mount",
"vfs-mount system-filename mount-point [options]");
// When we use GetAll(), we might inadvertently read duplicate
// lines. Filter them out with a set.
pset<string> already_read;
int num_unique_values = mounts.get_num_unique_values();
for (int i = 0; i < num_unique_values; i++) {
string mount_desc = mounts.get_unique_value(i);
Config::ConfigTable::Symbol::iterator si;
for (si = mounts.begin(); si != mounts.end(); ++si) {
string mount_desc = (*si).Val();
if (already_read.insert(mount_desc).second) {
// The vfs-mount syntax is:
// vfs-mount system-filename mount-point [options]
// The last two spaces mark the beginning of the mount point,
// and of the options, respectively. There might be multiple
// spaces in the system filename, which are part of the
// filename.
// The last space marks the beginning of the mount point.
// Spaces before that are part of the system filename.
size_t space = mount_desc.rfind(' ');
if (space == string::npos) {
express_cat.warning()
<< "No space in vfs-mount descriptor: " << mount_desc << "\n";
} else {
string mount_point = mount_desc.substr(space + 1);
// The vfs-mount syntax is:
// vfs-mount system-filename mount-point [options]
// The last two spaces mark the beginning of the mount point,
// and of the options, respectively. There might be multiple
// spaces in the system filename, which are part of the
// filename.
// The last space marks the beginning of the mount point.
// Spaces before that are part of the system filename.
size_t space = mount_desc.rfind(' ');
if (space == string::npos) {
express_cat.warning()
<< "No space in vfs-mount descriptor: " << mount_desc << "\n";
} else {
string mount_point = mount_desc.substr(space + 1);
while (space > 0 && isspace(mount_desc[space - 1])) {
space--;
}
mount_desc = mount_desc.substr(0, space);
string options;
space = mount_desc.rfind(' ');
if (space != string::npos) {
// If there's another space, we have the optional options field.
options = mount_point;
mount_point = mount_desc.substr(space + 1);
while (space > 0 && isspace(mount_desc[space - 1])) {
space--;
}
mount_desc = mount_desc.substr(0, space);
string options;
space = mount_desc.rfind(' ');
if (space != string::npos) {
// If there's another space, we have the optional options field.
options = mount_point;
mount_point = mount_desc.substr(space + 1);
while (space > 0 && isspace(mount_desc[space - 1])) {
space--;
}
mount_desc = mount_desc.substr(0, space);
}
mount_desc = ExecutionEnvironment::expand_string(mount_desc);
Filename physical_filename = Filename::from_os_specific(mount_desc);
int flags = 0;
string password;
// Split the options up by commas.
size_t p = 0;
size_t q = options.find(',', p);
while (q != string::npos) {
parse_option(options.substr(p, q - p),
flags, password);
p = q + 1;
q = options.find(',', p);
}
parse_option(options.substr(p), flags, password);
_global_ptr->mount(physical_filename, mount_point, flags, password);
}
mount_desc = ExecutionEnvironment::expand_string(mount_desc);
Filename physical_filename = Filename::from_os_specific(mount_desc);
int flags = 0;
string password;
// Split the options up by commas.
size_t p = 0;
size_t q = options.find(',', p);
while (q != string::npos) {
parse_option(options.substr(p, q - p),
flags, password);
p = q + 1;
q = options.find(',', p);
}
parse_option(options.substr(p), flags, password);
_global_ptr->mount(physical_filename, mount_point, flags, password);
}
}
}