📄 security.cxx
字号:
}
BaseSecurity* mutable_this = const_cast<BaseSecurity*>(this);
mutable_this->addCertPEM(type, aor, certPEM, false);
}
catch (...)
{
return false;
}
assert( certs.find(aor) != certs.end() );
return true;
}
void
BaseSecurity::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() );
}
Data
BaseSecurity::getCertDER (PEMType type, const Data& key) const
{
assert( !key.empty() );
if (hasCert(type, key) == false)
{
ErrLog(<< "Could 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__);
}
return Data(Data::Take, (char*)buffer, len);
}
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(...)
{
BIO_free(bio);
throw;
}
BIO_free(bio);
}
}
void
BaseSecurity::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(...)
{
BIO_free(in);
throw;
}
BIO_free(in);
}
void
BaseSecurity::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(...)
{
BIO_free(in);
throw;
}
BIO_free(in);
}
bool
BaseSecurity::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(...)
{
return false;
}
return true;
}
Data
BaseSecurity::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;
}
Data
BaseSecurity::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;
}
void
BaseSecurity::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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -