diff options
author | Mark Spruiell <mes@zeroc.com> | 2006-03-29 23:17:36 +0000 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2006-03-29 23:17:36 +0000 |
commit | 48fb89f2954f8120c67131431c718c61890a0717 (patch) | |
tree | 4843a837bfe7517497fbe181faa4ff72ae6ac423 /cpp | |
parent | ensure that all servers are destroyed (diff) | |
download | ice-48fb89f2954f8120c67131431c718c61890a0717.tar.bz2 ice-48fb89f2954f8120c67131431c718c61890a0717.tar.xz ice-48fb89f2954f8120c67131431c718c61890a0717.zip |
fixing leak when exception is thrown from constructor
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/src/IceSSL/Context.cpp | 570 |
1 files changed, 289 insertions, 281 deletions
diff --git a/cpp/src/IceSSL/Context.cpp b/cpp/src/IceSSL/Context.cpp index 8f508bedcf2..c70fd1f3992 100644 --- a/cpp/src/IceSSL/Context.cpp +++ b/cpp/src/IceSSL/Context.cpp @@ -104,110 +104,54 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, throw ex; } - // - // Store a pointer to ourself for use in OpenSSL callbacks. - // - SSL_CTX_set_ex_data(_ctx, 0, this); - - PropertiesPtr properties = _instance->communicator()->getProperties(); - - // - // Check for a default directory. We look in this directory for - // files mentioned in the configuration. - // + try { - _defaultDir = properties->getProperty(propPrefix + "DefaultDir"); - } + // + // Store a pointer to ourself for use in OpenSSL callbacks. + // + SSL_CTX_set_ex_data(_ctx, 0, this); - // - // Select protocols. - // - { - string protocols = properties->getProperty(propPrefix + "Protocols"); - if(!protocols.empty()) + PropertiesPtr properties = _instance->communicator()->getProperties(); + + // + // Check for a default directory. We look in this directory for + // files mentioned in the configuration. + // { - parseProtocols(protocols); + _defaultDir = properties->getProperty(propPrefix + "DefaultDir"); } - } - // - // Determine whether a certificate is required from the peer. - // - { - int verifyPeer = properties->getPropertyAsIntWithDefault(propPrefix + "VerifyPeer", 2); - int sslVerifyMode; - switch(verifyPeer) - { - case 0: - sslVerifyMode = SSL_VERIFY_NONE; - break; - case 1: - sslVerifyMode = SSL_VERIFY_PEER; - break; - case 2: - sslVerifyMode = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - break; - default: + // + // Select protocols. + // { - string msg = "IceSSL: invalid value for " + propPrefix + "VerifyPeer"; - if(_instance->securityTraceLevel() >= 1) + string protocols = properties->getProperty(propPrefix + "Protocols"); + if(!protocols.empty()) { - _logger->trace(_instance->securityTraceCategory(), msg); + parseProtocols(protocols); } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; - } - } - SSL_CTX_set_verify(_ctx, sslVerifyMode, opensslVerifyCallback); - } - - // - // If the configuration defines a password, or the application has supplied - // a password prompt object, then register a password callback. Otherwise, - // let OpenSSL use its default behavior. - // - { - // TODO: Support quoted value? - string password = properties->getProperty(propPrefix + "Password"); - if(!password.empty() || _instance->passwordPrompt()) - { - SSL_CTX_set_default_passwd_cb(_ctx, opensslPasswordCallback); - SSL_CTX_set_default_passwd_cb_userdata(_ctx, this); - _password = password; } - } - int passwordRetryMax = properties->getPropertyAsIntWithDefault(propPrefix + "PasswordRetryMax", 3); - - // - // Establish the location of CA certificates. - // - { - string caFile = properties->getProperty(propPrefix + "CertAuthFile"); - string caDir = properties->getPropertyWithDefault(propPrefix + "CertAuthDir", _defaultDir); - const char* file = 0; - const char* dir = 0; - if(!caFile.empty()) + // + // Determine whether a certificate is required from the peer. + // { - if(!checkPath(caFile, false)) + int verifyPeer = properties->getPropertyAsIntWithDefault(propPrefix + "VerifyPeer", 2); + int sslVerifyMode; + switch(verifyPeer) { - string msg = "IceSSL: CA certificate file not found:\n" + caFile; - if(_instance->securityTraceLevel() >= 1) - { - _logger->trace(_instance->securityTraceCategory(), msg); - } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; - } - file = caFile.c_str(); - } - if(!caDir.empty()) - { - if(!checkPath(caDir, true)) + case 0: + sslVerifyMode = SSL_VERIFY_NONE; + break; + case 1: + sslVerifyMode = SSL_VERIFY_PEER; + break; + case 2: + sslVerifyMode = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + break; + default: { - string msg = "IceSSL: CA certificate directory not found:\n" + caDir; + string msg = "IceSSL: invalid value for " + propPrefix + "VerifyPeer"; if(_instance->securityTraceLevel() >= 1) { _logger->trace(_instance->securityTraceCategory(), msg); @@ -216,86 +160,56 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, ex.reason = msg; throw ex; } - dir = caDir.c_str(); + } + SSL_CTX_set_verify(_ctx, sslVerifyMode, opensslVerifyCallback); } - if(file || dir) + + // + // If the configuration defines a password, or the application has supplied + // a password prompt object, then register a password callback. Otherwise, + // let OpenSSL use its default behavior. + // { - // - // The certificate may be stored in an encrypted file, so handle - // password retries. - // - int count = 0; - int err; - while(count < passwordRetryMax) + // TODO: Support quoted value? + string password = properties->getProperty(propPrefix + "Password"); + if(!password.empty() || _instance->passwordPrompt()) { - ERR_clear_error(); - err = SSL_CTX_load_verify_locations(_ctx, file, dir); - if(err || !passwordError()) - { - break; - } - ++count; - } - if(err == 0) - { - string msg = "IceSSL: unable to establish CA certificates"; - if(passwordError()) - { - msg += ":\ninvalid password"; - } - else - { - string err = _instance->sslErrors(); - if(!err.empty()) - { - msg += ":\n" + err; - } - } - if(_instance->securityTraceLevel() >= 1) - { - _logger->trace(_instance->securityTraceCategory(), msg); - } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; + SSL_CTX_set_default_passwd_cb(_ctx, opensslPasswordCallback); + SSL_CTX_set_default_passwd_cb_userdata(_ctx, this); + _password = password; } } - } - // - // Establish the certificate chains and private keys. One RSA certificate and - // one DSA certificate are allowed. - // - { -#ifdef _WIN32 - const string sep = ";"; -#else - const string sep = ":"; -#endif - string certFile = properties->getProperty(propPrefix + "CertFile"); - string keyFile = properties->getProperty(propPrefix + "KeyFile"); - vector<string>::size_type numCerts = 0; - if(!certFile.empty()) + int passwordRetryMax = properties->getPropertyAsIntWithDefault(propPrefix + "PasswordRetryMax", 3); + + // + // Establish the location of CA certificates. + // { - vector<string> files; - if(!splitString(certFile, sep, false, files) || files.size() > 2) + string caFile = properties->getProperty(propPrefix + "CertAuthFile"); + string caDir = properties->getPropertyWithDefault(propPrefix + "CertAuthDir", _defaultDir); + const char* file = 0; + const char* dir = 0; + if(!caFile.empty()) { - string msg = "IceSSL: invalid value for " + propPrefix + "CertFile:\n" + certFile; - if(_instance->securityTraceLevel() >= 1) + if(!checkPath(caFile, false)) { - _logger->trace(_instance->securityTraceCategory(), msg); + string msg = "IceSSL: CA certificate file not found:\n" + caFile; + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; + file = caFile.c_str(); } - numCerts = files.size(); - for(vector<string>::iterator p = files.begin(); p != files.end(); ++p) + if(!caDir.empty()) { - string file = *p; - if(!checkPath(file, false)) + if(!checkPath(caDir, true)) { - string msg = "IceSSL: certificate file not found:\n" + file; + string msg = "IceSSL: CA certificate directory not found:\n" + caDir; if(_instance->securityTraceLevel() >= 1) { _logger->trace(_instance->securityTraceCategory(), msg); @@ -304,6 +218,10 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, ex.reason = msg; throw ex; } + dir = caDir.c_str(); + } + if(file || dir) + { // // The certificate may be stored in an encrypted file, so handle // password retries. @@ -313,7 +231,7 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, while(count < passwordRetryMax) { ERR_clear_error(); - err = SSL_CTX_use_certificate_chain_file(_ctx, file.c_str()); + err = SSL_CTX_load_verify_locations(_ctx, file, dir); if(err || !passwordError()) { break; @@ -322,7 +240,7 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, } if(err == 0) { - string msg = "IceSSL: unable to load certificate chain from file " + file; + string msg = "IceSSL: unable to establish CA certificates"; if(passwordError()) { msg += ":\ninvalid password"; @@ -345,41 +263,100 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, } } } - if(keyFile.empty()) - { - keyFile = certFile; // Assume the certificate file also contains the private key. - } - if(!keyFile.empty()) + + // + // Establish the certificate chains and private keys. One RSA certificate and + // one DSA certificate are allowed. + // { - vector<string> files; - if(!splitString(keyFile, sep, false, files) || files.size() > 2) +#ifdef _WIN32 + const string sep = ";"; +#else + const string sep = ":"; +#endif + string certFile = properties->getProperty(propPrefix + "CertFile"); + string keyFile = properties->getProperty(propPrefix + "KeyFile"); + vector<string>::size_type numCerts = 0; + if(!certFile.empty()) { - string msg = "IceSSL: invalid value for " + propPrefix + "KeyFile:\n" + keyFile; - if(_instance->securityTraceLevel() >= 1) + vector<string> files; + if(!splitString(certFile, sep, false, files) || files.size() > 2) { - _logger->trace(_instance->securityTraceCategory(), msg); + string msg = "IceSSL: invalid value for " + propPrefix + "CertFile:\n" + certFile; + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; - } - if(files.size() != numCerts) - { - string msg = "IceSSL: " + propPrefix + "KeyFile does not agree with " + propPrefix + "CertFile"; - if(_instance->securityTraceLevel() >= 1) + numCerts = files.size(); + for(vector<string>::iterator p = files.begin(); p != files.end(); ++p) { - _logger->trace(_instance->securityTraceCategory(), msg); + string file = *p; + if(!checkPath(file, false)) + { + string msg = "IceSSL: certificate file not found:\n" + file; + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; + } + // + // The certificate may be stored in an encrypted file, so handle + // password retries. + // + int count = 0; + int err; + while(count < passwordRetryMax) + { + ERR_clear_error(); + err = SSL_CTX_use_certificate_chain_file(_ctx, file.c_str()); + if(err || !passwordError()) + { + break; + } + ++count; + } + if(err == 0) + { + string msg = "IceSSL: unable to load certificate chain from file " + file; + if(passwordError()) + { + msg += ":\ninvalid password"; + } + else + { + string err = _instance->sslErrors(); + if(!err.empty()) + { + msg += ":\n" + err; + } + } + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; + } } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; } - for(vector<string>::iterator p = files.begin(); p != files.end(); ++p) + if(keyFile.empty()) { - string file = *p; - if(!checkPath(file, false)) + keyFile = certFile; // Assume the certificate file also contains the private key. + } + if(!keyFile.empty()) + { + vector<string> files; + if(!splitString(keyFile, sep, false, files) || files.size() > 2) { - string msg = "IceSSL: key file not found:\n" + file; + string msg = "IceSSL: invalid value for " + propPrefix + "KeyFile:\n" + keyFile; if(_instance->securityTraceLevel() >= 1) { _logger->trace(_instance->securityTraceCategory(), msg); @@ -388,37 +365,75 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, ex.reason = msg; throw ex; } - // - // The private key may be stored in an encrypted file, so handle - // password retries. - // - int count = 0; - int err; - while(count < passwordRetryMax) + if(files.size() != numCerts) { - ERR_clear_error(); - err = SSL_CTX_use_PrivateKey_file(_ctx, file.c_str(), SSL_FILETYPE_PEM); - if(err || !passwordError()) + string msg = "IceSSL: " + propPrefix + "KeyFile does not agree with " + propPrefix + "CertFile"; + if(_instance->securityTraceLevel() >= 1) { - break; + _logger->trace(_instance->securityTraceCategory(), msg); } - ++count; + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } - if(err == 0) + for(vector<string>::iterator p = files.begin(); p != files.end(); ++p) { - string msg = "IceSSL: unable to load private key from file " + file; - if(passwordError()) + string file = *p; + if(!checkPath(file, false)) { - msg += ":\ninvalid password"; + string msg = "IceSSL: key file not found:\n" + file; + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } - else + // + // The private key may be stored in an encrypted file, so handle + // password retries. + // + int count = 0; + int err; + while(count < passwordRetryMax) { - string err = _instance->sslErrors(); - if(!err.empty()) + ERR_clear_error(); + err = SSL_CTX_use_PrivateKey_file(_ctx, file.c_str(), SSL_FILETYPE_PEM); + if(err || !passwordError()) { - msg += ":\n" + err; + break; } + ++count; } + if(err == 0) + { + string msg = "IceSSL: unable to load private key from file " + file; + if(passwordError()) + { + msg += ":\ninvalid password"; + } + else + { + string err = _instance->sslErrors(); + if(!err.empty()) + { + msg += ":\n" + err; + } + } + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; + } + } + if(!SSL_CTX_check_private_key(_ctx)) + { + string err = _instance->sslErrors(); + string msg = "IceSSL: unable to validate private key(s):\n" + err; if(_instance->securityTraceLevel() >= 1) { _logger->trace(_instance->securityTraceCategory(), msg); @@ -428,109 +443,102 @@ IceSSL::Context::Context(const InstancePtr& instance, const string& propPrefix, throw ex; } } - if(!SSL_CTX_check_private_key(_ctx)) - { - string err = _instance->sslErrors(); - string msg = "IceSSL: unable to validate private key(s):\n" + err; - if(_instance->securityTraceLevel() >= 1) - { - _logger->trace(_instance->securityTraceCategory(), msg); - } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; - } } - } - // - // Establish the cipher list. - // - { - string ciphers = properties->getProperty(propPrefix + "Ciphers"); - if(!ciphers.empty()) + // + // Establish the cipher list. + // { - if(!SSL_CTX_set_cipher_list(_ctx, ciphers.c_str())) + string ciphers = properties->getProperty(propPrefix + "Ciphers"); + if(!ciphers.empty()) { - string err = _instance->sslErrors(); - string msg = "IceSSL: unable to set ciphers using `" + ciphers + "':\n" + err; - if(_instance->securityTraceLevel() >= 1) + if(!SSL_CTX_set_cipher_list(_ctx, ciphers.c_str())) { - _logger->trace(_instance->securityTraceCategory(), msg); + string err = _instance->sslErrors(); + string msg = "IceSSL: unable to set ciphers using `" + ciphers + "':\n" + err; + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; } } - } - // - // Establish the maximum verify depth. - // - { - int depth = properties->getPropertyAsIntWithDefault(propPrefix + "VerifyDepthMax", -1); - if(depth >= 0) + // + // Establish the maximum verify depth. + // { - SSL_CTX_set_verify_depth(_ctx, depth); + int depth = properties->getPropertyAsIntWithDefault(propPrefix + "VerifyDepthMax", -1); + if(depth >= 0) + { + SSL_CTX_set_verify_depth(_ctx, depth); + } } - } - // - // Diffie Hellman configuration. - // - { -#ifndef OPENSSL_NO_DH - _dhParams = new DHParams; - SSL_CTX_set_options(_ctx, SSL_OP_SINGLE_DH_USE); - SSL_CTX_set_tmp_dh_callback(_ctx, opensslDHCallback); -#endif // - // Properties have the following form: + // Diffie Hellman configuration. // - // ...DH.<keyLength>=file - // - const string dhPrefix = propPrefix + "DH."; - PropertyDict d = properties->getPropertiesForPrefix(dhPrefix); - if(!d.empty()) { +#ifndef OPENSSL_NO_DH + _dhParams = new DHParams; + SSL_CTX_set_options(_ctx, SSL_OP_SINGLE_DH_USE); + SSL_CTX_set_tmp_dh_callback(_ctx, opensslDHCallback); +#endif + // + // Properties have the following form: + // + // ...DH.<keyLength>=file + // + const string dhPrefix = propPrefix + "DH."; + PropertyDict d = properties->getPropertiesForPrefix(dhPrefix); + if(!d.empty()) + { #ifdef OPENSSL_NO_DH - _logger->warning("IceSSL: OpenSSL is not configured for Diffie Hellman"); + _logger->warning("IceSSL: OpenSSL is not configured for Diffie Hellman"); #else - for(PropertyDict::iterator p = d.begin(); p != d.end(); ++p) - { - string s = p->first.substr(dhPrefix.size()); - int keyLength = atoi(s.c_str()); - if(keyLength > 0) + for(PropertyDict::iterator p = d.begin(); p != d.end(); ++p) { - string file = p->second; - if(!checkPath(file, false)) + string s = p->first.substr(dhPrefix.size()); + int keyLength = atoi(s.c_str()); + if(keyLength > 0) { - string msg = "IceSSL: DH parameter file not found:\n" + file; - if(_instance->securityTraceLevel() >= 1) + string file = p->second; + if(!checkPath(file, false)) { - _logger->trace(_instance->securityTraceCategory(), msg); + string msg = "IceSSL: DH parameter file not found:\n" + file; + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; - } - if(!_dhParams->add(keyLength, file)) - { - string msg = "IceSSL: unable to read DH parameter file " + file; - if(_instance->securityTraceLevel() >= 1) + if(!_dhParams->add(keyLength, file)) { - _logger->trace(_instance->securityTraceCategory(), msg); + string msg = "IceSSL: unable to read DH parameter file " + file; + if(_instance->securityTraceLevel() >= 1) + { + _logger->trace(_instance->securityTraceCategory(), msg); + } + PluginInitializationException ex(__FILE__, __LINE__); + ex.reason = msg; + throw ex; } - PluginInitializationException ex(__FILE__, __LINE__); - ex.reason = msg; - throw ex; } } - } #endif + } } } + catch(...) + { + SSL_CTX_free(_ctx); + throw; + } } IceSSL::Context::~Context() |