📄 security.cxx
字号:
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)
}
}
void
BaseSecurity::initialize ()
{
Timer::getTimeMs(); // initalize time offsets
}
Security::CertificateInfoContainer
BaseSecurity::getRootCertDescriptions() const
{
// !kh!
// need to be implemented.
assert(0); // TODO
return CertificateInfoContainer();
}
void
BaseSecurity::addRootCertPEM(const Data& x509PEMEncodedRootCerts)
{
assert( mRootTlsCerts && mRootSslCerts );
#if 1
addCertPEM(RootCert,Data::Empty,x509PEMEncodedRootCerts,false);
#else
assert( !x509PEMEncodedRootCerts.empty() );
static X509_LOOKUP_METHOD x509_pemstring_lookup =
{
"Load cert from PEM string into cache",
NULL, /* new */
NULL, /* free */
NULL, /* init */
NULL, /* shutdown */
pemstring_ctrl,/* ctrl */
NULL, /* get_by_subject */
NULL, /* get_by_issuer_serial */
NULL, /* get_by_fingerprint */
NULL, /* get_by_alias */
};
if (mRootCerts == 0)
{
mRootCerts = X509_STORE_new();
}
assert( mRootCerts );
X509_LOOKUP* lookup = X509_STORE_add_lookup(mRootCerts, &x509_pemstring_lookup);
if (lookup == NULL)
throw Exception("Error in BaseSecurity::addRootCertPEM()", __FILE__,__LINE__);
// !kh!
// bug, no error handling here.
X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, x509PEMEncodedRootCerts.c_str(), 0, 0);
#endif
}
void
BaseSecurity::addDomainCertPEM(const Data& domainName, const Data& certPEM)
{
addCertPEM(DomainCert, domainName, certPEM, true);
}
void
BaseSecurity::addDomainCertDER(const Data& domainName, const Data& certDER)
{
addCertDER(DomainCert, domainName, certDER, true);
}
bool
BaseSecurity::hasDomainCert(const Data& domainName) const
{
return hasCert(DomainCert, domainName);
}
void
BaseSecurity::removeDomainCert(const Data& domainName)
{
return removeCert(DomainCert, domainName);
}
Data
BaseSecurity::getDomainCertDER(const Data& domainName) const
{
return getCertDER(DomainCert, domainName);
}
void
BaseSecurity::addDomainPrivateKeyPEM(const Data& domainName, const Data& privateKeyPEM)
{
addPrivateKeyPEM(DomainPrivateKey, domainName, privateKeyPEM, true);
}
bool
BaseSecurity::hasDomainPrivateKey(const Data& domainName) const
{
return hasPrivateKey(DomainPrivateKey, domainName);
}
void
BaseSecurity::removeDomainPrivateKey(const Data& domainName)
{
removePrivateKey(DomainPrivateKey, domainName);
}
Data
BaseSecurity::getDomainPrivateKeyPEM(const Data& domainName) const
{
return getPrivateKeyPEM(DomainPrivateKey, domainName);
}
void
BaseSecurity::addUserCertPEM(const Data& aor, const Data& certPEM)
{
addCertPEM(UserCert, aor, certPEM, true);
}
void
BaseSecurity::addUserCertDER(const Data& aor, const Data& certDER)
{
addCertDER(UserCert, aor, certDER, true);
}
bool
BaseSecurity::hasUserCert(const Data& aor) const
{
return hasCert(UserCert, aor);
}
void
BaseSecurity::removeUserCert(const Data& aor)
{
removeCert(UserCert, aor);
}
Data
BaseSecurity::getUserCertDER(const Data& aor) const
{
return getCertDER(UserCert, aor);
}
void
BaseSecurity::setUserPassPhrase(const Data& aor, const Data& passPhrase)
{
assert(!aor.empty());
PassPhraseMap::iterator iter = mUserPassPhrases.find(aor);
if (iter == mUserPassPhrases.end())
{
mUserPassPhrases.insert(std::make_pair(aor, passPhrase));
}
}
bool
BaseSecurity::hasUserPassPhrase(const Data& aor) const
{
assert(aor.empty());
PassPhraseMap::const_iterator iter = mUserPassPhrases.find(aor);
if (iter == mUserPassPhrases.end())
{
return false;
}
else
{
return true;
}
}
void
BaseSecurity::removeUserPassPhrase(const Data& aor)
{
assert(aor.empty());
PassPhraseMap::iterator iter = mUserPassPhrases.find(aor);
if(iter != mUserPassPhrases.end())
{
mUserPassPhrases.erase(iter);
}
}
Data
BaseSecurity::getUserPassPhrase(const Data& aor) const
{
assert(aor.empty());
PassPhraseMap::const_iterator iter = mUserPassPhrases.find(aor);
if(iter == mUserPassPhrases.end())
{
return iter->second;
}
else
{
return Data::Empty;
}
}
void
BaseSecurity::addUserPrivateKeyPEM(const Data& aor, const Data& cert)
{
addPrivateKeyPEM(UserPrivateKey, aor, cert, true);
}
void
BaseSecurity::addUserPrivateKeyDER(const Data& aor, const Data& cert)
{
addPrivateKeyDER(UserPrivateKey, aor, cert, true);
}
bool
BaseSecurity::hasUserPrivateKey(const Data& aor) const
{
return hasPrivateKey(UserPrivateKey, aor);
}
void
BaseSecurity::removeUserPrivateKey(const Data& aor)
{
removePrivateKey(UserPrivateKey, aor);
}
Data
BaseSecurity::getUserPrivateKeyPEM(const Data& aor) const
{
return getPrivateKeyPEM(UserPrivateKey, aor);
}
Data
BaseSecurity::getUserPrivateKeyDER(const Data& aor) const
{
return getPrivateKeyDER(UserPrivateKey, aor);
}
void
BaseSecurity::generateUserCert (const Data& pAor, int expireDays, int keyLen )
{
int ret;
InfoLog( <<"Generating new user cert for " << pAor );
Data domain;
Data aor;
try
{
Uri uri( Data("sip:")+pAor );
aor = uri.getAor();
domain = uri.host();
}
catch (...)
{
ErrLog( <<"Invalid aor passed to generateUserCert");
throw Exception("Bad aor passed to generateUserCert", __FILE__,__LINE__);
}
// Make sure that necessary algorithms exist:
assert(EVP_sha1());
RSA* rsa = RSA_generate_key(keyLen, RSA_F4, NULL, NULL);
assert(rsa); // couldn't make key pair
EVP_PKEY* privkey = EVP_PKEY_new();
assert(privkey);
ret = EVP_PKEY_set1_RSA(privkey, rsa);
assert(ret);
X509* cert = X509_new();
assert(cert);
X509_NAME* subject = X509_NAME_new();
X509_EXTENSION* ext = X509_EXTENSION_new();
// set version to X509v3 (starts from 0)
X509_set_version(cert, 2L);
int serial = Random::getRandom(); // get an int worth of randomness
assert(sizeof(int)==4);
ASN1_INTEGER_set(X509_get_serialNumber(cert),serial);
ret = X509_NAME_add_entry_by_txt( subject, "O", MBSTRING_ASC,
(unsigned char *) domain.data(), domain.size(),
-1, 0);
assert(ret);
ret = X509_NAME_add_entry_by_txt( subject, "CN", MBSTRING_ASC,
(unsigned char *) aor.data(), aor.size(),
-1, 0);
assert(ret);
ret = X509_set_issuer_name(cert, subject);
assert(ret);
ret = X509_set_subject_name(cert, subject);
assert(ret);
const long duration = 60*60*24*expireDays;
X509_gmtime_adj(X509_get_notBefore(cert),0);
X509_gmtime_adj(X509_get_notAfter(cert), duration);
ret = X509_set_pubkey(cert, privkey);
assert(ret);
Data subjectAltNameStr = Data("URI:sip:") + aor
+ Data(",URI:im:")+aor
+ Data(",URI:pres:")+aor;
ext = X509V3_EXT_conf_nid( NULL , NULL , NID_subject_alt_name,
(char*) subjectAltNameStr.c_str() );
X509_add_ext( cert, ext, -1);
X509_EXTENSION_free(ext);
static char CA_FALSE[] = "CA:FALSE";
ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, CA_FALSE);
ret = X509_add_ext( cert, ext, -1);
assert(ret);
X509_EXTENSION_free(ext);
// TODO add extensions NID_subject_key_identifier and NID_authority_key_identifier
ret = X509_sign(cert, privkey, EVP_sha1());
assert(ret);
addCertX509( UserCert, aor, cert, true /* write */ );
addPrivateKeyPKEY( UserPrivateKey, aor, privkey, true /* write */ );
}
MultipartSignedContents*
BaseSecurity::sign(const Data& senderAor, Contents* contents)
{
assert( contents );
// form the multipart
MultipartSignedContents* multi = new MultipartSignedContents;
multi->header(h_ContentType).param( p_micalg ) = "sha1";
multi->header(h_ContentType).param( p_protocol ) = "application/pkcs7-signature";
// add the main body to it
Contents* body = contents->clone();
multi->parts().push_back( body );
Data bodyData;
DataStream strm( bodyData );
body->encodeHeaders( strm );
body->encode( strm );
strm.flush();
DebugLog( << "signing data <" << bodyData.escaped() << ">" );
//Security::dumpAsn("resip-sign-out-data",bodyData);
const char* p = bodyData.data();
int s = bodyData.size();
BIO* in=BIO_new_mem_buf( (void*)p,s);
assert(in);
DebugLog( << "created in BIO");
BIO* out = BIO_new(BIO_s_mem()); // TODO - mem leak
assert(out);
DebugLog( << "created out BIO" );
STACK_OF(X509)* chain = sk_X509_new_null();
assert(chain);
DebugLog( << "searching for cert/key for <" << senderAor << ">" );
if (mUserCerts.count(senderAor) == 0 ||
mUserPrivateKeys.count(senderAor) == 0)
{
BIO_free(in);
BIO_free(out);
sk_X509_free(chain);
WarningLog (<< "Tried to sign with no cert or private key for " << senderAor);
throw Exception("No cert or private key to sign with",__FILE__,__LINE__);
}
X509* publicCert = mUserCerts[senderAor];
EVP_PKEY* privateKey = mUserPrivateKeys[senderAor];
int rv = X509_check_private_key(publicCert, privateKey);
assert(rv);
// compute the signature
int flags = 0;
flags |= PKCS7_BINARY;
flags |= PKCS7_DETACHED;
if ( true ) // don't do caps
{
flags |= PKCS7_NOSMIMECAP;
flags |= PKCS7_NOATTR;
}
if ( true ) // don't do certs
{
flags |= PKCS7_NOCERTS;
}
PKCS7* pkcs7 = PKCS7_sign( publicCert, privateKey, chain, in, flags);
if ( !pkcs7 )
{
BIO_free(in);
BIO_free(out);
sk_X509_free(chain);
ErrLog( << "Error creating PKCS7 signature object" );
return 0;
}
DebugLog( << "created PKCS7 signature object " );
i2d_PKCS7_bio(out,pkcs7);
BIO_flush(out);
char* outBuf=0;
long size = BIO_get_mem_data(out,&outBuf);
assert( size > 0 );
Data outData(outBuf,size);
static char RESIP_SIGN_OUT_SIG[] = "resip-sign-out-sig";
Security::dumpAsn(RESIP_SIGN_OUT_SIG,outData);
Pkcs7SignedContents* sigBody = new Pkcs7SignedContents( outData );
assert( sigBody );
// add the signature to it
sigBody->header(h_ContentType).param( p_name ) = "smime.p7s";
sigBody->header(h_ContentDisposition).param( p_handling ) = "required";
sigBody->header(h_ContentDisposition).param( p_filename ) = "smime.p7s";
sigBody->header(h_ContentDisposition).value() = "attachment" ;
sigBody->header(h_ContentTransferEncoding).value() = "binary";
multi->parts().push_back( sigBody );
assert( multi->parts().size() == 2 );
BIO_free(in);
BIO_free(out);
sk_X509_free(chain);
return multi;
}
Pkcs7Contents*
BaseSecurity::encrypt(Contents* bodyIn, const Data& recipCertName )
{
assert( bodyIn );
int flags = 0 ;
flags |= PKCS7_BINARY;
flags |= PKCS7_NOCERTS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -