📄 security.cxx
字号:
ErrLog(<<"Caught exception: "); return false; } assert( certs.find(aor) != certs.end() ); return true;}voidBaseSecurity::removeCert (PEMType type, const Data& aor){ assert( !aor.empty() ); X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts); X509Map::iterator iter = certs.find(aor); if (iter != certs.end()) { X509_free(iter->second); certs.erase(iter); onRemovePEM(aor, type); } assert( certs.find(aor) == certs.end() );}DataBaseSecurity::getCertDER (PEMType type, const Data& key) const{ assert( !key.empty() ); if (hasCert(type, key) == false) { ErrLog(<< "Could not find certificate for '" << key << "'"); throw BaseSecurity::Exception("Could not find certificate", __FILE__,__LINE__); } X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts); BaseSecurity::X509Map::iterator where = certs.find(key); if (where == certs.end()) { // not supposed to happen, // hasCert() should have inserted a value into certs // or we should have throwed. assert(0); } //assert(0); // the code following this has no hope of working X509* x = where->second; unsigned char* buffer=0; int len = i2d_X509(x, &buffer); // !kh! // Although len == 0 is not an error, I am not sure what quite to do. // Asserting for now. assert(len != 0); if(len < 0) { ErrLog(<< "Could encode certificate of '" << key << "' to DER form"); throw BaseSecurity::Exception("Could encode certificate to DER form", __FILE__,__LINE__); } Data certDER((char*)buffer, len); OPENSSL_free(buffer); return certDER;}void BaseSecurity::addPrivateKeyPKEY(PEMType type, const Data& name, EVP_PKEY* pKey, bool write) const { PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys); /* // make a copy of the the key assert( EVP_PKEY_type(pKey->type) == EVP_PKEY_RSA ); RSA* rsa = EVP_PKEY_get1_RSA(pKey); assert( rsa ); EVP_PKEY* nKey = EVP_PKEY_new(); assert( nKey ); EVP_PKEY_set1_RSA(nKey, rsa); */ //privateKeys.insert(std::make_pair(name, nKey)); privateKeys.insert(std::make_pair(name, pKey)); if (write) { // figure out a passPhrase to encrypt with char* kstr=NULL; int klen=0; if (type != DomainPrivateKey) { PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name); if(iter != mUserPassPhrases.end()) { kstr = (char*)iter->second.c_str(); klen = iter->second.size(); } } BIO *bio = BIO_new(BIO_s_mem()); assert(bio); try { assert( EVP_des_ede3_cbc() ); const EVP_CIPHER* cipher = EVP_des_ede3_cbc(); if (kstr == NULL ) { cipher = NULL; }#if 0 // TODO - need to figure out what format to write in int ret = PEM_write_bio_PrivateKey(bio, pKey, cipher, (unsigned char*)kstr, klen, NULL, NULL);#else int ret = PEM_write_bio_PKCS8PrivateKey(bio, pKey, cipher, kstr, klen, NULL, NULL);#endif assert(ret); BIO_flush(bio); char* p = 0; size_t len = BIO_get_mem_data(bio,&p); assert(p); assert(len); Data pem(Data::Borrow, p, len); onWritePEM(name, type, pem ); } catch(...) { ErrLog(<<"Caught exception: "); BIO_free(bio); throw; } BIO_free(bio); }}voidBaseSecurity::addPrivateKeyDER( PEMType type, const Data& name, const Data& privateKeyDER, bool write ) const{ assert( !name.empty() ); assert( !privateKeyDER.empty() ); char* passPhrase = 0; if (type != DomainPrivateKey) { PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name); if(iter != mUserPassPhrases.end()) { passPhrase = const_cast<char*>(iter->second.c_str()); } } BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyDER.c_str()), -1); if ( !in ) { ErrLog(<< "Could create BIO buffer from '" << privateKeyDER << "'"); throw Exception("Could not create BIO buffer", __FILE__,__LINE__); } try { EVP_PKEY* privateKey; if (d2i_PKCS8PrivateKey_bio(in, &privateKey, 0, passPhrase) == 0) { ErrLog(<< "Could not read private key from <" << privateKeyDER << ">" ); throw Exception("Could not read private key ", __FILE__,__LINE__); } addPrivateKeyPKEY(type,name,privateKey,write); } catch(...) { ErrLog(<<"Caught exception: "); BIO_free(in); throw; } BIO_free(in);}voidBaseSecurity::addPrivateKeyPEM( PEMType type, const Data& name, const Data& privateKeyPEM, bool write ) const { assert( !name.empty() ); assert( !privateKeyPEM.empty() ); BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyPEM.c_str()), -1); if ( !in ) { ErrLog(<< "Could create BIO buffer from '" << privateKeyPEM << "'"); throw Exception("Could not create BIO buffer", __FILE__,__LINE__); } char* passPhrase = 0; try { if (type == UserPrivateKey) { PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name); if(iter != mUserPassPhrases.end()) { passPhrase = const_cast<char*>(iter->second.c_str()); } } EVP_PKEY* privateKey=0; if ( ( privateKey = PEM_read_bio_PrivateKey(in, NULL, 0, passPhrase)) == NULL) { ErrLog(<< "Could not read private key from <" << privateKeyPEM << ">" ); throw Exception("Could not read private key ", __FILE__,__LINE__); } addPrivateKeyPKEY(type,name,privateKey,write); } catch(...) { ErrLog(<<"Caught exception: "); BIO_free(in); throw; } BIO_free(in);}boolBaseSecurity::hasPrivateKey( PEMType type, const Data& key ) const{ assert( !key.empty() ); PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys); PrivateKeyMap::const_iterator where = privateKeys.find(key); if (where != privateKeys.end()) { return true; } Data privateKeyPEM; try { onReadPEM(key, type, privateKeyPEM); BaseSecurity* mutable_this = const_cast<BaseSecurity*>(this); mutable_this->addPrivateKeyPEM(type, key, privateKeyPEM, false); } catch(...) { ErrLog(<<"Caught exception: "); return false; } return true;}DataBaseSecurity::getPrivateKeyPEM( PEMType type, const Data& key) const{ assert( !key.empty() ); if ( !hasPrivateKey(type, key) ) { ErrLog(<< "Could find private key for '" << key << "'"); throw Exception("Could not find private key", __FILE__,__LINE__); } PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys); PrivateKeyMap::const_iterator where = privateKeys.find(key); char* p = 0; if (type != DomainPrivateKey) { PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key); if (iter != mUserPassPhrases.end()) { p = const_cast<char*>(iter->second.c_str()); } } assert(0); // TODO - following code has no hope of working // !kh! // creates a read/write BIO buffer. BIO *out = BIO_new(BIO_s_mem()); assert(out); EVP_PKEY* pk = where->second; assert(pk); // write pk to out using key phrase p, with no cipher. int ret = PEM_write_bio_PrivateKey(out, pk, 0, 0, 0, 0, p); // paraters // are in the wrong order assert(ret == 1); // get content in BIO buffer to our buffer. // hand our buffer to a Data object. BIO_flush(out); char* buf = 0; int len = BIO_get_mem_data(out, &buf); Data retVal(Data::Borrow, buf, len); BIO_free(out); return retVal;}DataBaseSecurity::getPrivateKeyDER( PEMType type, const Data& key) const{ assert( !key.empty() ); if ( !hasPrivateKey(type, key) ) { ErrLog(<< "Could find private key for '" << key << "'"); throw Exception("Could not find private key", __FILE__,__LINE__); } PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys); PrivateKeyMap::const_iterator where = privateKeys.find(key); char* p = 0; if (type != DomainPrivateKey) { PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key); if(iter != mUserPassPhrases.end()) { p = const_cast<char*>(iter->second.c_str()); } } assert(0); // TODO - following code has no hope of working // !kh! // creates a read/write BIO buffer. BIO *out = BIO_new(BIO_s_mem()); assert(out); EVP_PKEY* pk = where->second; assert(pk); // write pk to out using key phrase p, with no cipher. int ret = i2d_PKCS8PrivateKey_bio(out, pk, 0, 0, 0, 0, p); assert(ret == 1); // get content in BIO buffer to our buffer. // hand our buffer to a Data object. BIO_flush(out); char* buf = 0; int len = BIO_get_mem_data(out, &buf); Data retVal(Data::Borrow, buf, len); BIO_free(out); return retVal;}voidBaseSecurity::removePrivateKey(PEMType type, const Data& key){ assert( !key.empty() ); PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys); assert( !key.empty() ); PrivateKeyMap::iterator iter = privateKeys.find(key); if (iter != privateKeys.end()) { EVP_PKEY_free(iter->second); privateKeys.erase(iter); onRemovePEM(key, type); }}Security::Exception::Exception(const Data& msg, const Data& file, const int line): BaseException(msg,file,line){}BaseSecurity::BaseSecurity (const CipherList& cipherSuite) : mTlsCtx(0), mSslCtx(0), mRootTlsCerts(0), mRootSslCerts(0){ DebugLog(<< "BaseSecurity::BaseSecurity"); int ret; initialize(); mRootTlsCerts = X509_STORE_new(); mRootSslCerts = X509_STORE_new(); assert(mRootTlsCerts && mRootSslCerts); mTlsCtx = SSL_CTX_new( TLSv1_method() ); if (!mTlsCtx) { ErrLog(<< "SSL_CTX_new failed, dumping OpenSSL error stack:"); while (ERR_peek_error()) { char errBuf[120]; ERR_error_string(ERR_get_error(), errBuf); ErrLog(<< "OpenSSL error stack: " << errBuf); } } assert(mTlsCtx); SSL_CTX_set_cert_store(mTlsCtx, mRootTlsCerts); SSL_CTX_set_verify(mTlsCtx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verifyCallback); ret = SSL_CTX_set_cipher_list(mTlsCtx, cipherSuite.cipherList().c_str()); assert(ret); mSslCtx = SSL_CTX_new( SSLv23_method() ); assert(mSslCtx); SSL_CTX_set_cert_store(mSslCtx, mRootSslCerts); SSL_CTX_set_verify(mSslCtx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, verifyCallback); ret = SSL_CTX_set_cipher_list(mSslCtx,cipherSuite.cipherList().c_str()); assert(ret);}template<class T, class Func> void clearMap(T& m, Func& clearFunc){ for (typename T::iterator it = m.begin(); it != m.end(); it++) { clearFunc(it->second); } m.clear();} BaseSecurity::~BaseSecurity (){ DebugLog(<< "BaseSecurity::~BaseSecurity"); // cleanup certificates clearMap(mDomainCerts, X509_free); clearMap(mUserCerts, X509_free); // cleanup private keys clearMap(mDomainPrivateKeys, EVP_PKEY_free); clearMap(mUserPrivateKeys, EVP_PKEY_free);/*// !abr! This intentional memory leak appears to be unnecessary. Derek to verify.// !dcm! - still crashses...I think if there were no certs to load. // sailesh@counterpath.com : this code leaks memory but it's necessary on // mac and windows. if we don't have this code then SSL_CTX_new( TLSv1_method() ) // returns NULL when BaseSecurity::BaseSecurity() is called the second time. X509_STORE_free(mRootTlsCerts); X509_STORE_free(mRootSslCerts);*/ // cleanup SSL_CTXes if (mTlsCtx) { SSL_CTX_free(mTlsCtx);mTlsCtx=0; // This free's X509_STORE (mRootTlsCerts) } if (mSslCtx) { SSL_CTX_free(mSslCtx);mSslCtx=0; // This free's X509_STORE (mRootSslCerts) }}voidBaseSecurity::initialize (){ Timer::getTimeMs(); // initalize time offsets}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -