15 #include "configPage.h" 16 #include "configDeclaration.h" 17 #include "configVariableCore.h" 18 #include "configVariableManager.h" 19 #include "prcKeyRegistry.h" 20 #include "config_prc.h" 21 #include "encryptStream.h" 26 #include "openssl/evp.h" 40 ConfigPage(
const string &name,
bool implicit_load,
int page_seq) :
42 _implicit_load(implicit_load),
44 _sort(implicit_load ? 10 : 0),
72 _default_page =
new ConfigPage(
"default",
false, 0);
88 _local_page =
new ConfigPage(
"local",
false, 0);
120 Declarations::iterator di;
121 for (di = _declarations.begin(); di != _declarations.end(); ++di) {
125 _declarations.clear();
127 _signature = string();
151 static const size_t buffer_size = 1024;
152 char buffer[buffer_size];
158 _md_ctx = EVP_MD_CTX_create();
160 _md_ctx =
new EVP_MD_CTX;
162 EVP_VerifyInit((EVP_MD_CTX *)_md_ctx, EVP_sha1());
163 #endif // HAVE_OPENSSL 167 in.read(buffer, buffer_size);
168 size_t count = in.gcount();
170 char *buffer_end = buffer + count;
173 char *newline = (
char *)memchr((
void *)buffer,
'\n', count);
174 if (newline == (
char *)NULL) {
176 prev_line += string(buffer, count);
180 size_t length = newline - buffer;
181 read_prc_line(prev_line +
string(buffer, length + 1));
184 char *start = newline + 1;
185 newline = (
char *)memchr((
void *)start,
'\n', buffer_end - start);
186 while (newline != (
char *)NULL) {
187 length = newline - start;
188 read_prc_line(
string(start, length + 1));
190 newline = (
char *)memchr((
void *)start,
'\n', buffer_end - start);
195 length = buffer_end - start;
196 prev_line = string(start, length);
199 if (in.fail() || in.eof()) {
206 in.read(buffer, buffer_size);
211 if (!prev_line.empty()) {
212 read_prc_line(prev_line);
217 if (!_signature.empty()) {
218 PrcKeyRegistry *pkr = PrcKeyRegistry::get_global_ptr();
219 int num_keys = pkr->get_num_keys();
220 for (
int i = 1; i < num_keys && _trust_level == 0; i++) {
221 EVP_PKEY *pkey = pkr->get_key(i);
222 if (pkey != (EVP_PKEY *)NULL) {
224 EVP_VerifyFinal((EVP_MD_CTX *)_md_ctx,
225 (
unsigned char *)_signature.data(),
226 _signature.size(), pkey);
227 if (verify_result == 1) {
232 if (_trust_level == 0) {
234 <<
"invalid signature found in " <<
get_name() <<
"\n";
238 EVP_MD_CTX_destroy((EVP_MD_CTX *)_md_ctx);
240 delete (EVP_MD_CTX *)_md_ctx;
242 #endif // HAVE_OPENSSL 244 bool failed = (in.fail() && !in.eof());
259 IDecryptStream decrypt(&in,
false, password);
263 #endif // HAVE_OPENSSL 287 (
this, variable, value, _next_decl_seq);
290 _declarations.push_back(decl);
306 Declarations::iterator di;
307 for (di = _declarations.begin(); di != _declarations.end(); ++di) {
309 _declarations.erase(di);
326 return _declarations.size();
337 return _declarations[n];
351 return _declarations[n];
362 nassertr(n >= 0 && n < (
int)_declarations.size(), string());
363 return _declarations[n]->get_variable()->get_name();
374 nassertr(n >= 0 && n < (
int)_declarations.size(), string());
375 return _declarations[n]->get_string_value();
386 nassertr(n >= 0 && n < (
int)_declarations.size(),
false);
387 return _declarations[n]->get_variable()->is_used();
396 output(ostream &out)
const {
408 size_t num_bytes = min(_signature.size(), (size_t)8);
409 for (
size_t p = 0; p < num_bytes; ++p) {
410 unsigned int byte = _signature[p];
412 unsigned int hi = (byte >> 4) & 0xf;
414 out << (char)((hi - 10) +
'a');
416 out << (char)(hi +
'0');
419 unsigned int lo = byte & 0xf;
421 out << (char)((lo - 10) +
'a');
423 out << (char)(lo +
'0');
434 write(ostream &out)
const {
435 Declarations::const_iterator di;
436 for (di = _declarations.begin(); di != _declarations.end(); ++di) {
449 read_prc_line(
const string &line) {
450 if (line.substr(0, 7) ==
"##!sig ") {
453 for (
size_t p = 7; p < line.length() - 1; p += 2) {
454 unsigned char digit = (hex_digit(line[p]) << 4) | hex_digit(line[p + 1]);
463 EVP_VerifyUpdate((EVP_MD_CTX *)_md_ctx, line.data(), line.size());
464 #endif // HAVE_OPENSSL 468 while (p < line.length() && isspace((
unsigned char)line[p])) {
472 if (p == line.length() || line[p] ==
'#') {
477 size_t variable_begin = p;
478 while (p < line.length() && !isspace((
unsigned char)line[p])) {
481 size_t variable_end = p;
483 while (p < line.length() && isspace((
unsigned char)line[p])) {
486 size_t value_begin = p;
489 p = line.find(
" #", value_begin);
490 if (p == string::npos) {
498 while (p > value_begin && isspace((
unsigned char)line[p - 1])) {
501 size_t value_end = p;
503 string variable = line.substr(variable_begin, variable_end - variable_begin);
504 string value = line.substr(value_begin, value_end - value_begin);
514 unsigned int ConfigPage::
515 hex_digit(
unsigned char digit) {
516 if (isalpha(digit)) {
517 return tolower(digit) -
'a' + 10;
518 }
else if (isdigit(digit)) {
bool read_encrypted_prc(istream &in, const string &password)
Automatically decrypts and reads the stream, given the indicated password.
void clear()
Removes all of the declarations from the page.
The internal definition of a ConfigVariable.
const ConfigDeclaration * get_declaration(int n) const
Returns the nth declaration on the page.
static ConfigPage * get_local_page()
Returns a pointer to the global "local page".
ConfigDeclaration * modify_declaration(int n)
Returns a modifiable pointer to the nth declaration on the page.
void output_brief_signature(ostream &out) const
Outputs the first few hex digits of the signature.
static ConfigPage * get_default_page()
Returns a pointer to the global "default page".
A global object that maintains the set of ConfigVariables (actually, ConfigVariableCores) everywhere ...
ConfigDeclaration * make_declaration(const string &variable, const string &value)
Adds the indicated variable/value pair as a new declaration on the page.
const string & get_name() const
Returns the name of the page.
string get_string_value(int n) const
Returns the value assigned by the nth declaration on the page.
ConfigVariableCore * make_variable(const string &name)
Creates and returns a new, undefined ConfigVariableCore with the indicated name; or if a variable wit...
bool read_prc(istream &in)
Reads the contents of a complete prc file, as returned by the indicated istream, into the current pag...
void mark_unsorted()
This method is meant to be used internally to this module; there is no need to call it directly...
A page of ConfigDeclarations that may be loaded or unloaded.
int get_num_declarations() const
Returns the number of declarations on the page.
bool is_variable_used(int n) const
Returns true if the nth active variable on the page has been used by code, false otherwise.
string get_variable_name(int n) const
Returns the variable named by the nth declaration on the page.
A single declaration of a config variable, typically defined as one line in a .prc file...
void set_sort(int sort)
Changes the explicit sort order of this particular ConfigPage.
bool delete_declaration(ConfigDeclaration *decl)
Removes the indicated declaration from the page and deletes it.