1#if defined(HAVE_CONFIG_H)
37#if defined(__ANDROID__)
47#include <openssl/opensslv.h>
48#include <openssl/dh.h>
49#include <openssl/evp.h>
50#include <openssl/crypto.h>
51#include <openssl/err.h>
52#include <openssl/pem.h>
53#include <openssl/pkcs7.h>
54#include <openssl/ossl_typ.h>
55#include <openssl/rsa.h>
56#include <openssl/x509.h>
57#include <openssl/x509v3.h>
58#include <openssl/ssl.h>
63#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
79 case Security::RootCert:
return rootCert;
81 case Security::DomainPrivateKey:
return domainKey;
82 case Security::UserCert:
return userCert;
83 case Security::UserPrivateKey:
return userKey;
86 ErrLog( <<
"Unknown pem type prefix requested" << (
int)(pType) );
103 static int idx = SSL_get_ex_new_index(0,
nullptr,
nullptr,
nullptr,
nullptr);
115 char subjectNameBuf[256] = {0};
116 X509* cert = X509_STORE_CTX_get_current_cert(storeCtx);
117 int errorCode = X509_STORE_CTX_get_error(storeCtx);
121 int errorDepth = X509_STORE_CTX_get_error_depth(storeCtx);
126 BIO* bio = BIO_new(BIO_s_mem());
129 const X509_NAME* subjectName = X509_get_subject_name(cert);
133 X509_NAME_print_ex(bio, subjectName, 0, XN_FLAG_RFC2253);
134 BIO_gets(bio, subjectNameBuf,
sizeof(subjectNameBuf));
141 SSL* ssl = (
SSL*)X509_STORE_CTX_get_ex_data(storeCtx, SSL_get_ex_data_X509_STORE_CTX_idx());
151 ds <<
"'" << X509_verify_cert_error_string(errorCode) <<
"', errorDepth=" << errorDepth <<
", subjectName=[" << subjectNameBuf <<
"]";
157 ErrLog(<<
"Error when verifying peer's chain of certificates: tuple=" << connection->
who() <<
", error=" << errorString);
161 ErrLog(<<
"Error when verifying peer's chain of certificates: error=" << errorString);
189 BaseSecurity(cipherSuite, defaultPrivateKeyPassPhrase, dHParamsFilename)
192 mPath =
"C:\\sipCerts\\";
194 const char* env=getenv(
"HOME");
199 mPath +=
"/.sipCerts/";
204 BaseSecurity(cipherSuite, defaultPrivateKeyPassPhrase, dHParamsFilename),
217 mCADirectories.push_back(caDirectory);
218 Data &_dir = mCADirectories.back();
228 mCAFiles.push_back(caFile);
236 for (; it != dir.
end(); ++it)
243 Data fileName = _dir + name;
249 ErrLog(<<
"loadCADirectory: Some problem reading " << *it <<
": " << e);
253 ErrLog(<<
"loadCADirectory: Some problem reading " << *it);
264 InfoLog(<<
"Successfully loaded " << _file);
268 ErrLog(<<
"loadCAFile: Some problem reading " << _file <<
": " << e);
272 ErrLog(<<
"loadCAFile: Some problem reading " << _file);
286 Data fileName(mPath);
287 if (fileName.postfix(
"/"))
289 fileName.truncate(fileName.size() - 1);
291 if (fileName.size() > 0)
293 StackLog(<<
"calling stat() for " << fileName);
294 if (stat(fileName.c_str(), &s) < 0)
296 ErrLog(<<
"Error calling stat() for " << fileName.c_str()
301 if (!S_ISDIR(s.st_mode))
303 WarningLog(<<
"mPath argument is a file rather than a directory, "
304 "treating mPath as a file of trusted root certificates");
314 for (; it != dir.
end(); ++it)
320 Data fileName = mPath + name;
321 bool attemptedToLoad =
true;
323 DebugLog(<<
"Checking to load file " << name);
348 DebugLog(<<
"PEM file " << name <<
" does not have appropriate resip prefix, skipping...");
349 attemptedToLoad =
false;
354 ErrLog(<<
"Some problem reading " << fileName <<
": " << e);
358 ErrLog(<<
"Some problem reading " << fileName);
363 InfoLog(<<
"Successfully loaded " << fileName);
368 InfoLog(<<
"Files loaded by prefix: " << count);
370 if (count == 0 && mCADirectories.empty() && mCAFiles.empty() && mPath.
size() > 0)
374 InfoLog(<<
"No root certificates found using legacy prefixes, "
375 "treating mPath=" << mPath <<
" as a normal directory of root certs");
379 std::list<Data>::iterator it_d = mCADirectories.begin();
380 for (; it_d != mCADirectories.end(); ++it_d)
385 std::list<Data>::iterator it_f = mCAFiles.begin();
386 for (; it_f != mCAFiles.end(); ++it_f)
397 snprintf(buf, size,
"%s", (
char*)password);
398 return (
int)strlen(buf);
409 SSL_CTX* ctx = SSL_CTX_new(method);
419 updateDomainCtx(ctx, domain, certificateFilename, privateKeyFilename, privateKeyPassPhrase);
427 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
verifyCallback);
438 const Data sessionContext(
Data(
"resip:") + domain);
439 unsigned char sessionIdContext[EVP_MAX_MD_SIZE];
440 unsigned int sessionIdContextLength = 0;
441 if(EVP_Digest(sessionContext.
data(), sessionContext.
size(), sessionIdContext,
442 &sessionIdContextLength, EVP_sha256(),
nullptr) != 1 ||
443 sessionIdContextLength > SSL_MAX_SID_CTX_LENGTH ||
444 SSL_CTX_set_session_id_context(ctx, sessionIdContext, sessionIdContextLength) != 1)
446 WarningLog(<<
"Failed to set the TLS session id context for domain " << domain
447 <<
", clients verified with a certificate can't resume sessions");
461 if(!privateKeyPassPhrase.
empty())
463 SSL_CTX_set_default_passwd_cb_userdata(ctx, (
void*)privateKeyPassPhrase.
c_str());
466 if(SSL_CTX_use_certificate_chain_file(ctx, certFilename.c_str()) != 1)
468 ErrLog (<<
"Error reading domain chain file " << certFilename);
477 InfoLog(<<
"Security::updateDomainCtx: Successfully loaded domain cert and added to Security storage, domain=" << domain <<
", filename=" << certFilename);
481 InfoLog(<<
"Security::updateDomainCtx: Successfully loaded domain cert, domain=" << domain <<
", filename=" << certFilename);
485 if(SSL_CTX_use_PrivateKey_file(ctx, keyFilename.c_str(), SSL_FILETYPE_PEM) != 1)
487 ErrLog (<<
"Error reading domain private key file " << keyFilename);
490 if (!SSL_CTX_check_private_key(ctx))
492 ErrLog (<<
"Invalid domain private key from file: " << keyFilename);
501 InfoLog(<<
"Security::updateDomainCtx: Successfully loaded domain private key and added to Security storage, domain=" << domain <<
", filename=" << keyFilename);
505 InfoLog(<<
"Security::updateDomainCtx: Successfully loaded domain private key, domain=" << domain <<
", filename=" << keyFilename);
515 InfoLog (<<
"Reading PEM file " << filename <<
" for " << name);
524 InfoLog (<<
"Writing PEM file " << filename <<
" for " << name);
525 ofstream str(filename.
c_str(), ios::binary);
528 ErrLog (<<
"Can't write to " << filename);
533 str.write(buffer.
data(), buffer.
size());
536 ErrLog (<<
"Failed writing to " << filename <<
" " << buffer.
size() <<
" bytes");
555 if( certDER.
empty() )
557 ErrLog(<<
"File is empty. Skipping.");
563 unsigned const char* in = (
unsigned const char*)certDER.
data();
564 if (d2i_X509(&cert,&in,(
long)certDER.
size()) == 0)
566 ErrLog(<<
"Could not read DER certificate from " << certDER );
579 if( certPEM.
empty() )
581 ErrLog(<< name <<
" is empty. Skipping.");
586 BIO* in = BIO_new_mem_buf(
const_cast<char*
>(certPEM.
c_str()), -1);
589 ErrLog(<<
"Could not create BIO buffer from '" << certPEM <<
"'");
590 throw Exception(
"Could not create BIO buffer", __FILE__,__LINE__);
594 cert = PEM_read_bio_X509(in,0,0,0);
597 ErrLog( <<
"Could not load X509 cert from '" << certPEM <<
"'" );
599 throw Exception(
"Could not load X509 cert from BIO buffer", __FILE__,__LINE__);
643 BIO *out = BIO_new(BIO_s_mem());
646 ErrLog(<<
"Failed to create BIO: this cert will not be added.");
653 int ret = PEM_write_bio_X509(out, cert);
657 throw Exception(
"PEM_write_bio_X509 failed: this cert will not be "
658 "added.", __FILE__,__LINE__);
661 (void)BIO_flush(out);
664 size_t len = BIO_get_mem_data(out,&p);
668 throw Exception(
"BIO_get_mem_data failed: this cert will not be "
669 "added.", __FILE__,__LINE__);
677 ErrLog(<<
"Caught exception: " << e);
679 catch(std::exception& e)
681 ErrLog(<<
"Caught unknown exception, rethrowing");
695 X509Map::const_iterator where = certs.find(aor);
696 if (where != certs.end())
710 mutable_this->
addCertPEM(type, aor, certPEM,
false);
714 if(logErrors)
ErrLog(<<
"Caught exception: " << e);
717 catch (
const std::exception& e)
719 if (logErrors)
ErrLog(<<
"Caught exception: " << e.
what());
724 if (logErrors)
ErrLog(<<
"Caught exception: ");
739 X509Map::iterator iter = certs.find(aor);
740 if (iter != certs.end())
742 X509_free(iter->second);
756 if (
hasCert(type, key) ==
false)
758 ErrLog(<<
"Could not find certificate for '" << key <<
"'");
763 BaseSecurity::X509Map::const_iterator where = certs.find(key);
764 if (where == certs.end())
772 X509* x = where->second;
773 unsigned char* buffer=0;
774 int len = i2d_X509(x, &buffer);
782 ErrLog(<<
"Could encode certificate of '" << key <<
"' to DER form");
785 Data certDER((
char*)buffer, len);
786 OPENSSL_free(buffer);
799 privateKeys.insert(std::make_pair(name, pKey));
811 kstr = (
char*)iter->second.c_str();
812 klen = (int)iter->second.size();
816 BIO *bio = BIO_new(BIO_s_mem());
819 ErrLog(<<
"BIO_new failed: cannot add private key.");
826 const EVP_CIPHER* cipher = EVP_des_ede3_cbc();
832 int ret = PEM_write_bio_PrivateKey(bio, pKey, cipher,
833 (
unsigned char*)kstr, klen,
836 int ret = PEM_write_bio_PKCS8PrivateKey(bio, pKey, cipher,
843 throw Exception(
"PEM_write_bio_PKCS8PrivateKey failed: cannot add"
844 " private key.", __FILE__, __LINE__);
847 (void)BIO_flush(bio);
849 size_t len = BIO_get_mem_data(bio,&p);
853 throw Exception(
"BIO_get_mem_data failed: cannot add"
854 " private key.", __FILE__, __LINE__);
861 ErrLog( <<
"Caught exception: " << e);
863 catch(std::exception& e)
865 ErrLog(<<
"Caught unknown exception, rethrowing: " << e.
what());
876 const Data& privateKeyDER,
878 const Data& privateKeyPassPhrase)
881 if( privateKeyDER.
empty() )
883 ErrLog(<< name <<
" is empty. Skipping.");
887 char* passPhrase = 0;
888 if (privateKeyPassPhrase.
empty())
895 passPhrase =
const_cast<char*
>(iter->second.c_str());
908 passPhrase =
const_cast<char*
>(privateKeyPassPhrase.
c_str());
911 BIO* in = BIO_new_mem_buf(
const_cast<char*
>(privateKeyDER.
c_str()), -1);
914 ErrLog(<<
"Could create BIO buffer from '" << privateKeyDER <<
"'");
915 throw Exception(
"Could not create BIO buffer", __FILE__,__LINE__);
921 if (d2i_PKCS8PrivateKey_bio(in, &privateKey, 0, passPhrase) == 0)
923 ErrLog(<<
"Could not read private key from <" << privateKeyDER <<
">" );
924 throw Exception(
"Could not read private key ", __FILE__,__LINE__);
929 catch(std::exception& e)
931 ErrLog(<<
"Caught exception: ");
942 const Data& privateKeyPEM,
944 const Data& privateKeyPassPhrase)
947 if( privateKeyPEM.
empty() )
949 ErrLog(<< name <<
" is empty. Skipping.");
953 BIO* in = BIO_new_mem_buf(
const_cast<char*
>(privateKeyPEM.
c_str()), -1);
956 ErrLog(<<
"Could create BIO buffer from '" << privateKeyPEM <<
"'");
957 throw Exception(
"Could not create BIO buffer", __FILE__,__LINE__);
960 char* passPhrase = 0;
963 if (privateKeyPassPhrase.
empty())
970 passPhrase =
const_cast<char*
>(iter->second.c_str());
983 passPhrase =
const_cast<char*
>(privateKeyPassPhrase.
c_str());
987 if ( ( privateKey = PEM_read_bio_PrivateKey(in, NULL,
pem_passwd_cb, passPhrase)) == NULL)
990 unsigned long err = ERR_get_error();
991 ERR_error_string(err, buffer);
992 if(ERR_GET_LIB(err) == ERR_LIB_EVP && ERR_GET_REASON(err) == EVP_R_BAD_DECRYPT)
994 ErrLog(<<
"Could not read private key (error=" << buffer <<
") - likely incorrect password provided, may load correctly when transports are added with appropriate password");
998 ErrLog(<<
"Could not read private key (error=" << buffer <<
") from <" << privateKeyPEM <<
">" );
1000 throw Exception(
"Could not read private key ", __FILE__,__LINE__);
1005 catch(std::exception& e)
1007 ErrLog(<<
"Caught exception: ");
1017 const Data& key )
const
1024 PrivateKeyMap::const_iterator where = privateKeys.find(key);
1025 if (where != privateKeys.end())
1037 catch(std::exception& e)
1039 ErrLog(<<
"Caught exception: " << e.what());
1044 ErrLog(<<
"Caught unknown class!");
1053 const Data& key)
const
1059 ErrLog(<<
"Could find private key for '" << key <<
"'");
1060 throw Exception(
"Could not find private key", __FILE__,__LINE__);
1065 PrivateKeyMap::const_iterator where = privateKeys.find(key);
1072 p =
const_cast<char*
>(iter->second.c_str());
1078 BIO *out = BIO_new(BIO_s_mem());
1084 int ret = PEM_write_bio_PrivateKey(out, pk, 0, 0, 0, 0, p);
1091 (void)BIO_flush(out);
1093 int len = BIO_get_mem_data(out, &buf);
1094 Data retVal(buf, len);
1103 const Data& key)
const
1109 ErrLog(<<
"Could not find private key for '" << key <<
"'");
1110 throw Exception(
"Could not find private key", __FILE__,__LINE__);
1115 PrivateKeyMap::const_iterator where = privateKeys.find(key);
1122 p =
const_cast<char*
>(iter->second.c_str());
1128 BIO *out = BIO_new(BIO_s_mem());
1134 int ret = i2d_PKCS8PrivateKey_bio(out, pk, 0, 0, 0, 0, p);
1140 (void)BIO_flush(out);
1142 int len = BIO_get_mem_data(out, &buf);
1143 Data retVal(buf, len);
1158 PrivateKeyMap::iterator iter = privateKeys.find(key);
1159 if (iter != privateKeys.end())
1161 EVP_PKEY_free(iter->second);
1162 privateKeys.erase(iter);
1169Security::Exception::Exception(
const Data& msg,
const Data& file,
const int line)
1177 mCipherList(cipherSuite),
1178 mDefaultPrivateKeyPassPhrase(defaultPrivateKeyPassPhrase),
1179 mDHParamsFilename(dHParamsFilename),
1183 DebugLog(<<
"BaseSecurity::BaseSecurity");
1192 mTlsCtx = SSL_CTX_new( TLS_method() );
1195 ErrLog(<<
"SSL_CTX_new failed, dumping OpenSSL error stack:");
1196 while (ERR_peek_error())
1199 ERR_error_string(ERR_get_error(), errBuf);
1200 ErrLog(<<
"OpenSSL error stack: " << errBuf);
1203 SSL_CTX_set_min_proto_version(
mTlsCtx, TLS1_VERSION);
1204 SSL_CTX_set_max_proto_version(
mTlsCtx, TLS1_VERSION);
1216 mSslCtx = SSL_CTX_new( TLS_method() );
1229template<
class T,
class Func>
1232 for (
typename T::iterator it = m.begin(); it != m.end(); it++)
1234 clearFunc(it->second);
1239template<
class T,
class Func>
1242 for (
typename T::iterator it = m.begin(); it != m.end(); it++)
1251 DebugLog(<<
"BaseSecurity::~BaseSecurity");
1298 static X509_LOOKUP_METHOD x509_pemstring_lookup =
1300 "Load cert from PEM string into cache",
1319 X509_LOOKUP* lookup = X509_STORE_add_lookup(
mRootCerts, &x509_pemstring_lookup);
1322 throw Exception(
"Error in BaseSecurity::addRootCertPEM()", __FILE__,__LINE__);
1326 X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, x509PEMEncodedRootCerts.
c_str(), 0, 0);
1462 return iter->second;
1511 InfoLog( <<
"Generating new user cert for " << pAor );
1520 domain = uri.
host();
1524 ErrLog( <<
"Invalid aor passed to generateUserCert");
1525 throw Exception(
"Bad aor passed to generateUserCert", __FILE__,__LINE__);
1533 EVP_PKEY_CTX* keyCtx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
1534 bool generated = keyCtx &&
1535 EVP_PKEY_keygen_init(keyCtx) == 1 &&
1536 EVP_PKEY_CTX_set_rsa_keygen_bits(keyCtx, keyLen) == 1 &&
1537 EVP_PKEY_keygen(keyCtx, &privkey) == 1;
1538 EVP_PKEY_CTX_free(keyCtx);
1541 ErrLog( <<
"Unable to generate a " << keyLen <<
" bit RSA key for " << aor );
1542 throw Exception(
"Unable to generate a key pair in generateUserCert", __FILE__,__LINE__);
1545 X509* cert = X509_new();
1548 X509_NAME* subject = X509_NAME_new();
1549 X509_EXTENSION* ext;
1552 X509_set_version(cert, 2L);
1558 ASN1_INTEGER_set(X509_get_serialNumber(cert),serial);
1560 ret = X509_NAME_add_entry_by_txt( subject,
"O", MBSTRING_ASC,
1561 (
unsigned char *) domain.
data(), (
int)domain.
size(),
1564 ret = X509_NAME_add_entry_by_txt( subject,
"CN", MBSTRING_ASC,
1565 (
unsigned char *) aor.
data(), (
int)aor.
size(),
1569 ret = X509_set_issuer_name(cert, subject);
1571 ret = X509_set_subject_name(cert, subject);
1573 X509_NAME_free(subject);
1575 const long duration = 60*60*24*expireDays;
1576 X509_gmtime_adj(X509_getm_notBefore(cert),0);
1577 X509_gmtime_adj(X509_getm_notAfter(cert), duration);
1579 ret = X509_set_pubkey(cert, privkey);
1582 Data subjectAltNameStr =
Data(
"URI:sip:") + aor
1583 +
Data(
",URI:im:")+aor
1584 +
Data(
",URI:pres:")+aor;
1585 ext = X509V3_EXT_conf_nid( NULL , NULL , NID_subject_alt_name,
1586 (
char*) subjectAltNameStr.
c_str() );
1587 X509_add_ext( cert, ext, -1);
1588 X509_EXTENSION_free(ext);
1590 static const char CA_FALSE[] =
"CA:FALSE";
1591 ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, CA_FALSE);
1592 ret = X509_add_ext( cert, ext, -1);
1594 X509_EXTENSION_free(ext);
1598 ret = X509_sign(cert, privkey, EVP_sha256());
1612 multi->
header(h_ContentType).param( p_micalg ) =
"sha256";
1613 multi->
header(h_ContentType).param( p_protocol ) =
"application/pkcs7-signature";
1617 multi->
parts().push_back( body );
1630 BIO* in=BIO_new_mem_buf( (
void*)p,s);
1634 BIO* out = BIO_new(BIO_s_mem());
1638 STACK_OF(
X509)* chain = sk_X509_new_null();
1641 DebugLog( <<
"searching for cert/key for <" << senderAor <<
">" );
1647 sk_X509_free(chain);
1648 WarningLog (<<
"Tried to sign with no cert or private key for " << senderAor);
1649 throw Exception(
"No cert or private key to sign with",__FILE__,__LINE__);
1655 int rv = X509_check_private_key(publicCert, privateKey);
1660 sk_X509_free(chain);
1661 ErrLog (<<
"X509_check_private_key failed for " << senderAor);
1667 flags |= PKCS7_BINARY;
1668 flags |= PKCS7_DETACHED;
1671 flags |= PKCS7_NOSMIMECAP;
1672 flags |= PKCS7_NOATTR;
1676 flags |= PKCS7_NOCERTS;
1679 PKCS7* pkcs7 = PKCS7_sign( publicCert, privateKey, chain, in,
flags);
1684 sk_X509_free(chain);
1685 ErrLog( <<
"Error creating PKCS7 signature object" );
1688 DebugLog( <<
"created PKCS7 signature object " );
1690 i2d_PKCS7_bio(out,pkcs7);
1691 (void)BIO_flush(out);
1694 long size = BIO_get_mem_data(out,&outBuf);
1697 Data outData(outBuf,size);
1698 static const char RESIP_SIGN_OUT_SIG[] =
"resip-sign-out-sig";
1705 sigBody->
header(h_ContentType).param( p_name ) =
"smime.p7s";
1706 sigBody->
header(h_ContentDisposition).param( p_handling ) =
"required";
1707 sigBody->
header(h_ContentDisposition).param( p_filename ) =
"smime.p7s";
1708 sigBody->
header(h_ContentDisposition).value() =
"attachment" ;
1709 sigBody->
header(h_ContentTransferEncoding).value() =
"binary";
1710 multi->
parts().push_back( sigBody );
1716 sk_X509_free(chain);
1729 flags |= PKCS7_BINARY;
1730 flags |= PKCS7_NOCERTS;
1743 BIO* in = BIO_new_mem_buf( (
void*)p,s);
1747 BIO* out = BIO_new(BIO_s_mem());
1751 InfoLog( <<
"target cert name is <" << recipCertName <<
">" );
1756 WarningLog (<<
"Tried to encrypt with no cert or private key for " << recipCertName);
1757 throw Exception(
"No cert or private key to encrypt with",__FILE__,__LINE__);
1763 STACK_OF(
X509) *certs = sk_X509_new_null();
1765 sk_X509_push(certs, cert);
1770 const EVP_CIPHER* cipher = EVP_aes_128_cbc();
1773 PKCS7* pkcs7 = PKCS7_encrypt( certs, in, cipher,
flags);
1778 sk_X509_free(certs);
1779 ErrLog( <<
"Error creating PKCS7 encrypt object" );
1783 DebugLog( <<
"created PKCS7 encrypt object " );
1785 i2d_PKCS7_bio(out,pkcs7);
1787 (void)BIO_flush(out);
1790 long size = BIO_get_mem_data(out,&outBuf);
1793 Data outData(outBuf,size);
1796 InfoLog( <<
"Encrypted body size is " << outData.
size() );
1799 static const char RESIP_ENCRYPT_OUT[] =
"resip-encrypt-out";
1805 outBody->
header(h_ContentType).param( p_smimeType ) =
"enveloped-data";
1806 outBody->
header(h_ContentType).param( p_name ) =
"smime.p7m";
1807 outBody->
header(h_ContentDisposition).param( p_handling ) =
"required";
1808 outBody->
header(h_ContentDisposition).param( p_filename ) =
"smime.p7";
1809 outBody->
header(h_ContentDisposition).value() =
"attachment" ;
1810 outBody->
header(h_ContentTransferEncoding).value() =
"binary";
1814 sk_X509_free(certs);
1826 return sign(senderAor,
encrypt(body, recipCertName));
1833 DebugLog( <<
"Compute identity for " << in );
1838 InfoLog( <<
"No private key for " << signerDomain );
1839 throw Exception(
"Missing private key when computing identity",__FILE__,__LINE__);
1845 if ( EVP_PKEY_base_id(pKey) != EVP_PKEY_RSA )
1847 ErrLog( <<
"Private key (type=" << EVP_PKEY_id(pKey) <<
") for "
1848 << signerDomain <<
" is not of type RSA" );
1849 throw Exception(
"No RSA private key when computing identity",__FILE__,__LINE__);
1852 unsigned char digest[EVP_MAX_MD_SIZE];
1853 unsigned int digestSize =
sizeof(
digest);
1854 auto digestType = EVP_sha256();
1855 if (!EVP_Digest(in.
data(), in.
size(),
digest, &digestSize, digestType, NULL))
1857 ErrLog( <<
"Failed to compute digest of identity" );
1858 throw Exception(
"Failed to compute digest of identity",__FILE__, __LINE__);
1863 unsigned char result[4096];
1864 size_t resultSize =
sizeof(result);
1865 EVP_PKEY_CTX* signCtx = EVP_PKEY_CTX_new(pKey, NULL);
1866 bool signedOk = signCtx &&
1867 EVP_PKEY_sign_init(signCtx) == 1 &&
1868 EVP_PKEY_CTX_set_rsa_padding(signCtx, RSA_PKCS1_PADDING) == 1 &&
1869 EVP_PKEY_CTX_set_signature_md(signCtx, digestType) == 1 &&
1870 EVP_PKEY_sign(signCtx, result, &resultSize,
digest, digestSize) == 1;
1871 EVP_PKEY_CTX_free(signCtx);
1874 ErrLog(<<
"Signing the identity digest failed");
1879 Data res(result,resultSize);
1880 DebugLog( <<
"rsa encrypt of hash is 0x"<< res.
hex() );
1884 static const char IDENTITY_IN[] =
"identity-in";
1885 static const char IDENTITY_IN_HASH[] =
"identity-in-hash";
1886 static const char IDENTITY_IN_RSA[] =
"identity-in-rsa";
1887 static const char IDENTITY_IN_BASE64[] =
"identity-in-base64";
1907 ErrLog( <<
"No public key for " << signerDomain );
1908 throw Exception(
"Missing public key when verifying identity",__FILE__,__LINE__);
1913 DebugLog( <<
"Check identity for " << in );
1914 DebugLog( <<
" base64 data is " << sigBase64 );
1919 unsigned char digest[EVP_MAX_MD_SIZE];
1920 unsigned int digestSize =
sizeof(
digest);
1921 auto digestType = EVP_sha256();
1923 if (!EVP_Digest(in.
data(), in.
size(),
digest, &digestSize, digestType, NULL))
1925 ErrLog( <<
"Failed to compute digest of identity" );
1926 throw Exception(
"Failed to compute digest of identity",__FILE__, __LINE__);
1930 EVP_PKEY* pKey = X509_get_pubkey( cert );
1931 if ( !pKey || EVP_PKEY_base_id(pKey) != EVP_PKEY_RSA )
1933 ErrLog( <<
"Public key for " << signerDomain <<
" is not of type RSA" );
1934 EVP_PKEY_free(pKey);
1939 EVP_PKEY_CTX* verifyCtx = EVP_PKEY_CTX_new(pKey, NULL);
1940 int ret = verifyCtx &&
1941 EVP_PKEY_verify_init(verifyCtx) == 1 &&
1942 EVP_PKEY_CTX_set_rsa_padding(verifyCtx, RSA_PKCS1_PADDING) == 1 &&
1943 EVP_PKEY_CTX_set_signature_md(verifyCtx, digestType) == 1 &&
1944 EVP_PKEY_verify(verifyCtx, (
const unsigned char*)sig.
data(), sig.
size(),
digest, digestSize) == 1;
1945 EVP_PKEY_CTX_free(verifyCtx);
1946 EVP_PKEY_free(pKey);
1947 DebugLog( <<
"rsa verify result is " << ret );
1949 static const char IDENTITY_OUT_MSG[] =
"identity-out-msg";
1950 static const char IDENTITY_OUT_BASE64[] =
"identity-out-base64";
1951 static const char IDENTITY_OUT_SIG[] =
"identity-out-sig";
1952 static const char IDENTITY_OUT_HASH[] =
"identity-out-hash";
1972 if ( !certDer.
empty() )
1974 unsigned const char* in = (
unsigned const char*)certDer.
data();
1975 if (d2i_X509(&cert,&in,(
long)certDer.
size()) == 0)
1977 DebugLog(<<
"Could not read DER certificate from " << certDer );
1981 if ( certDer.
empty() || cert )
2005 ErrLog(<<
"Caught exception: "<< e);
2018 DebugLog( <<
"decryptor Aor: <" << decryptorAor <<
">" );
2021 flags |= PKCS7_BINARY;
2030 static const char RESIP_ASN_DECRYPT[] =
"resip-asn-decrypt";
2033 BIO* in = BIO_new_mem_buf( (
void*)text.
c_str(), (
int)text.
size());
2035 InfoLog( <<
"created in BIO");
2038 out = BIO_new(BIO_s_mem());
2040 InfoLog( <<
"created out BIO" );
2042 PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0);
2045 ErrLog( <<
"Problems doing decode of PKCS7 object" );
2052#if OPENSSL_VERSION_NUMBER < 0x30000000L
2053 unsigned long code = ERR_get_error_line(&file,&line);
2055 unsigned long code = ERR_get_error_all(&file, &line, NULL, NULL, NULL);
2063 ERR_error_string_n(code,buf,
sizeof(buf));
2065 InfoLog( <<
"Error code = " << code <<
" file=" << file <<
" line=" << line );
2073 (void)BIO_flush(in);
2075 int type=OBJ_obj2nid(pkcs7->type);
2076 InfoLog( <<
"data is " << OBJ_nid2ln(type) );
2078 STACK_OF(
X509)* certs = sk_X509_new_null();
2087 case NID_pkcs7_signedAndEnveloped:
2091 sk_X509_free(certs);
2093 throw Exception(
"Signed and enveloped is not supported", __FILE__, __LINE__);
2097 case NID_pkcs7_enveloped:
2103 sk_X509_free(certs);
2105 InfoLog( <<
"Don't have a private key for " << decryptorAor <<
" for PKCS7_decrypt" );
2106 throw Exception(
"Missing private key", __FILE__, __LINE__);
2112 sk_X509_free(certs);
2114 InfoLog( <<
"Don't have a public cert for " << decryptorAor <<
" for PKCS7_decrypt" );
2115 throw Exception(
"Missing cert", __FILE__, __LINE__);
2121 if ( PKCS7_decrypt(pkcs7, privateKey, publicCert, out,
flags ) != 1 )
2123 ErrLog( <<
"Problems doing PKCS7_decrypt" );
2129#if OPENSSL_VERSION_NUMBER < 0x30000000L
2130 unsigned long code = ERR_get_error_line(&file,&line);
2132 unsigned long code = ERR_get_error_all(&file, &line, NULL, NULL, NULL);
2140 ERR_error_string_n(code,buf,
sizeof(buf));
2142 InfoLog( <<
"Error code = " << code <<
" file=" << file <<
" line=" << line );
2147 sk_X509_free(certs);
2157 sk_X509_free(certs);
2159 ErrLog(<<
"Got PKCS7 data that could not be handled type=" << type );
2160 throw Exception(
"Unsupported PKCS7 data type", __FILE__, __LINE__);
2163 (void)BIO_flush(out);
2165 BIO_get_mem_ptr(out, &bufMem);
2167 int len = (int)bufMem->length;
2168 char* buffer =
new char[len];
2169 memcpy(buffer, bufMem->data, len);
2171 (void)BIO_set_close(out, BIO_CLOSE);
2174 sk_X509_free(certs);
2181 const char* headerStart = pb.
position();
2192 const char* typeStart = pb.
position();
2201 contentType.
parse(subPb);
2206 pb.
reset(typeStart);
2214 pb.
data(tmp, bodyStart);
2220 ParseBuffer headersPb(headerStart, bodyStart-4-headerStart);
2243 if ( multi->
parts().size() != 2 )
2245 ErrLog(<<
"Trying to decode a message with wrong number of contents " << multi->
parts().size());
2246 throw Exception(
"Invalid contents passed to checkSignature", __FILE__, __LINE__);
2249 MultipartSignedContents::Parts::const_iterator it = multi->
parts().begin();
2258 InfoLog( <<
"message to signature-check is " << *first );
2263 ErrLog( <<
"Don't know how to deal with signature type " );
2271 if (!rawFirst.
empty())
2273 textData = rawFirst;
2291 InfoLog( <<
"No received bytes recorded for the first body part; "
2292 <<
"verifying against a re-encoding. Expected for a locally "
2293 <<
"built body and for a copy of an already parsed one; a "
2294 <<
"regression if this body was parsed here, which happens when "
2295 <<
"a caller reaches it through the mutable "
2296 <<
"MultipartMixedContents::parts()." );
2307 static const char RESIP_ASN_UNCODE_SIGNED_TEXT[] =
"resip-asn-uncode-signed-text";
2308 static const char RESIP_ASN_UNCODE_SIGNED_SIG[] =
"resip-asn-uncode-signed-sig";
2313 BIO* in = BIO_new_mem_buf( (
void*)sigData.
data(),(
int)sigData.
size());
2315 InfoLog( <<
"created in BIO");
2317 BIO* out = BIO_new(BIO_s_mem());
2319 InfoLog( <<
"created out BIO" );
2321 BIO* pkcs7Bio = BIO_new_mem_buf( (
void*) textData.
data(),(
int)textData.
size());
2323 InfoLog( <<
"created pkcs7 BIO");
2325 PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0);
2328 ErrLog( <<
"Problems doing decode of PKCS7 object <"
2329 << sigData.
escaped() <<
">" );
2336#if OPENSSL_VERSION_NUMBER < 0x30000000L
2337 unsigned long code = ERR_get_error_line(&file,&line);
2339 unsigned long code = ERR_get_error_all(&file, &line, NULL, NULL, NULL);
2347 ERR_error_string_n(code,buf,
sizeof(buf));
2349 InfoLog( <<
"Error code = "<< code <<
" file=" << file <<
" line=" << line );
2357 (void)BIO_flush(in);
2359 int type=OBJ_obj2nid(pkcs7->type);
2360 InfoLog( <<
"data is " << OBJ_nid2ln(type) );
2362 STACK_OF(
X509)* certs = 0;
2363 certs = sk_X509_new_null();
2372 sk_X509_push(certs, it->second);
2379 InfoLog( <<
"Adding cert from " << *signedBy <<
" to check sig" );
2382 sk_X509_push(certs, cert);
2387 flags |= PKCS7_NOINTERN;
2390 STACK_OF(
X509)* signers = PKCS7_get0_signers(pkcs7, certs,
flags);
2394 DebugLog( <<
"Found " << sk_X509_num(signers) <<
" signers." );
2395 for (
int i=0; i<sk_X509_num(signers); i++)
2397 X509* x = sk_X509_value(signers, i);
2400 GENERAL_NAMES* gens = 0;
2401 gens = (GENERAL_NAMES*)X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
2403 for (
int j = 0; j < sk_GENERAL_NAME_num(gens); j++)
2405 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, j);
2406 if (gen->type == GEN_URI)
2408 ASN1_IA5STRING* uri = gen->d.uniformResourceIdentifier;
2409 Data name(ASN1_STRING_get0_data(uri), ASN1_STRING_length(uri));
2410 InfoLog(<<
"subjectAltName of signing cert contains <" << name <<
">" );
2414 if ( n.
scheme() ==
"sip" )
2417 InfoLog(<<
"choose <" << name <<
"> signature" );
2422 ErrLog(<<
"Caught exception: "<< e);
2427 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
2435 sk_X509_free(certs);
2438 InfoLog(<<
"No valid signers of this messages" );
2445 STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
2446 PKCS7_SIGNER_INFO *si;
2447 PKCS7_ISSUER_AND_SERIAL *ias;
2448 ASN1_INTEGER* asnSerial;
2452 sinfos = PKCS7_get_signer_info(pkcs7);
2455 int num = sk_PKCS7_SIGNER_INFO_num(sinfos);
2456 for (
int i=0; i<num; i++ )
2458 si = sk_PKCS7_SIGNER_INFO_value (sinfos, i) ;
2459 ias = si->issuer_and_serial;
2461 asnSerial = ias->serial;
2462 longSerial = ASN1_INTEGER_get( (ASN1_INTEGER*)asnSerial );
2463 InfoLog( <<
"Signed with serial " << hex << longSerial );
2464 InfoLog( <<
"Name " << name );
2473 case NID_pkcs7_signed:
2479 flags |= PKCS7_NOVERIFY;
2484 ErrLog( <<
"Problems doing PKCS7_verify" );
2496#if OPENSSL_VERSION_NUMBER < 0x30000000L
2497 unsigned long code = ERR_get_error_line(&file,&line);
2499 unsigned long code = ERR_get_error_all(&file, &line, NULL, NULL, NULL);
2507 ERR_error_string_n(code,buf,
sizeof(buf));
2509 InfoLog( <<
"Error code = " << code <<
" file=" << file <<
" line=" << line );
2514 sk_X509_free(certs);
2520 if ( (
flags & PKCS7_NOVERIFY) )
2524 DebugLog( <<
"Signature is selfSigned");
2529 DebugLog( <<
"Signature is notTrusted" );
2537 DebugLog( <<
"Signature is trusted" );
2542 DebugLog( <<
"Signature is caTrusted" );
2554 sk_X509_free(certs);
2556 ErrLog(<<
"Got PKCS7 data that could not be handled type=" << type );
2560 (void)BIO_flush(out);
2562 long size = BIO_get_mem_data(out,&outBuf);
2565 Data outData(outBuf,size);
2571 sk_X509_free(certs);
2599 if(peerNames.size() > 0)
2605 const X509_NAME* subject = X509_get_subject_name(cert);
2608 ErrLog( <<
"Invalid certificate: subject not found ");
2616 i = X509_NAME_get_index_by_NID(
const_cast<X509_NAME*
>(subject), NID_commonName,i);
2622 const X509_NAME_ENTRY* entry = X509_NAME_get_entry(subject,i);
2625 const ASN1_STRING* s = X509_NAME_ENTRY_get_data(entry);
2628 int t = ASN1_STRING_type(s);
2629 int l = ASN1_STRING_length(s);
2630 const unsigned char* d = ASN1_STRING_get0_data(s);
2632 DebugLog( <<
"got x509 string type=" << t <<
" len="<< l <<
" data=" << d );
2635 DebugLog( <<
"Found common name in cert of " << name );
2641 int numExt = X509_get_ext_count(cert);
2642 ErrLog(<<
"Got peer certificate with " << numExt <<
" extensions" );
2644 for (
int i=0; i<numExt; i++ )
2646 X509_EXTENSION* ext = X509_get_ext(cert,i);
2649 const char* str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
2651 DebugLog(<<
"Got certificate extension" << str );
2653 if ( OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_subject_alt_name )
2655 DebugLog(<<
"Got subjectAltName extension" );
2661 GENERAL_NAMES* gens;
2662 gens = (GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
2663 for(
int i = 0; i < sk_GENERAL_NAME_num(gens); i++)
2665 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);
2667 DebugLog(<<
"subjectAltName of cert contains type <" << gen->type <<
">" );
2669 if (gen->type == GEN_DNS)
2671 ASN1_IA5STRING* asn = gen->d.dNSName;
2672 Data dns(ASN1_STRING_get0_data(asn), ASN1_STRING_length(asn));
2674 peerNames.push_back(peerName);
2675 InfoLog(<<
"subjectAltName of TLS session cert contains DNS <" << dns <<
">" );
2678 if (gen->type == GEN_EMAIL)
2682 ASN1_IA5STRING* asn = gen->d.rfc822Name;
2683 Data email(ASN1_STRING_get0_data(asn), ASN1_STRING_length(asn));
2685 peerNames.push_back(peerName);
2686 InfoLog(<<
"subjectAltName of TLS session cert contains EMAIL <" << email <<
">" );
2689 DebugLog(<<
"subjectAltName of cert has EMAIL type" );
2692 if (gen->type == GEN_IPADD)
2697 ASN1_OCTET_STRING* asn = gen->d.iPAddress;
2698 const unsigned char* asnData = ASN1_STRING_get0_data(asn);
2699 const int asnLen = ASN1_STRING_length(asn);
2703 (asnData[1] << 16) |
2708 sa.sin_family = AF_INET;
2709 sa.sin_addr.s_addr = htonl(ip);
2711 char addrStr[INET_ADDRSTRLEN];
2712 if (inet_ntop(sa.sin_family, &(sa.sin_addr), addrStr, INET_ADDRSTRLEN) != NULL)
2716 peerNames.push_back(peerName);
2717 InfoLog(<<
"subjectAltName of TLS session cert contains IP ADDRESS <" << ipv4 <<
">" );
2720 else if (asnLen == 16)
2723 sa.sin6_family = AF_INET6;
2724 sa.sin6_addr.s6_addr[0] = asnData[0];
2725 sa.sin6_addr.s6_addr[1] = asnData[1];
2726 sa.sin6_addr.s6_addr[2] = asnData[2];
2727 sa.sin6_addr.s6_addr[3] = asnData[3];
2728 sa.sin6_addr.s6_addr[4] = asnData[4];
2729 sa.sin6_addr.s6_addr[5] = asnData[5];
2730 sa.sin6_addr.s6_addr[6] = asnData[6];
2731 sa.sin6_addr.s6_addr[7] = asnData[7];
2732 sa.sin6_addr.s6_addr[8] = asnData[8];
2733 sa.sin6_addr.s6_addr[9] = asnData[9];
2734 sa.sin6_addr.s6_addr[10] = asnData[10];
2735 sa.sin6_addr.s6_addr[11] = asnData[11];
2736 sa.sin6_addr.s6_addr[12] = asnData[12];
2737 sa.sin6_addr.s6_addr[13] = asnData[13];
2738 sa.sin6_addr.s6_addr[14] = asnData[14];
2739 sa.sin6_addr.s6_addr[15] = asnData[15];
2741 char addrStr[INET6_ADDRSTRLEN];
2742 if (inet_ntop(sa.sin6_family, &(sa.sin6_addr), addrStr, INET6_ADDRSTRLEN) != NULL)
2746 peerNames.push_back(peerName);
2747 InfoLog(<<
"subjectAltName of TLS session cert contains IP ADDRESS <" << ipv6 <<
">" );
2751 DebugLog(<<
"subjectAltName of cert contains invalid IP ADDRESS" );
2754 if(gen->type == GEN_URI)
2756 ASN1_IA5STRING* asn = gen->d.uniformResourceIdentifier;
2757 Data uriString(ASN1_STRING_get0_data(asn), ASN1_STRING_length(asn));
2764 peerNames.push_back(peerName);
2765 InfoLog(<<
"subjectAltName of TLS session cert contains URI <" << uri <<
">" );
2769 InfoLog(<<
"subjectAltName of TLS session cert contains unparsable URI <" << uriString <<
">, ignoring it");
2773 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
2777 if(peerNames.empty() && !commonName.
empty())
2780 peerNames.push_back(peerName);
2788 std::list<PeerName> cNames;
2794 for(std::list<PeerName>::const_iterator it = cNames.begin(); it != cNames.end(); it++)
2803 for(std::list<PeerName>::const_iterator it = cNames.begin(); it != cNames.end(); it++)
2810 ErrLog(<<
"This certificate doesn't have neither subjectAltName nor commonName");
2820 if(certificateName.
empty() || domainName.
empty())
2843 Data error =
"Not a recognized SSL type: " + typeName;
2844 throw invalid_argument(error.
c_str());
2870 static const Data wildcardLabel(
"*.");
2878 const Data certificateBase = certificateName.
substr(wildcardLabel.
size());
2880 if(baseDot ==
Data::npos || baseDot == 0 || baseDot + 1 == certificateBase.
size())
2897 X509 *mutableCert =
const_cast<X509*
>(cert);
2898 int iRet = X509_NAME_cmp(X509_get_issuer_name(mutableCert), X509_get_subject_name(mutableCert));
2910 ofstream strm(name, std::ios_base::trunc);
2913 ErrLog( <<
"Could not write to " << name );
2917 strm.write( data.
data() , data.
size() );
2973 InfoLog(<<
"Unable to load DH parameters (required for PFS): TlsDHParamsFilename not specified");
2987 bool loaded =
false;
2988#if OPENSSL_VERSION_NUMBER >= 0x30000000L
2990 EVP_PKEY* dh = PEM_read_bio_Parameters(bio, NULL);
2991 if(dh == NULL || !(EVP_PKEY_is_a(dh,
"DH") || EVP_PKEY_is_a(dh,
"DHX")))
2996 else if(!SSL_CTX_set0_tmp_dh_pkey(ctx, dh))
3006 DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3013 if(!SSL_CTX_set_tmp_dh(ctx, dh))
3028#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3033 options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE;
3034 options = SSL_CTX_set_options(ctx, options);
3035 DebugLog(<<
"DH parameters loaded, PFS cipher-suites enabled");
struct ssl_ctx_st SSL_CTX
struct evp_pkey_st EVP_PKEY
static Data digest("digest")
#define WarningLog(args_)
int verifyCallback(int iInCode, X509_STORE_CTX *pInStore)
#define resip_assert(x)
This file needs to work for both C and C++ code.
static const Data unknownKey("user_key_")
static const Data userKey("user_key_")
void clearList(T &m, Func &clearFunc)
static Data getAor(const Data &filename, const Security::PEMType &pemType)
static const Data rootCert("root_cert_")
static const Data PEM(".pem")
static const Data userCert("user_cert_")
static const Data domainKey("domain_key_")
int pem_passwd_cb(char *buf, int size, int rwflag, void *password)
static const Data pemTypePrefixes(Security::PEMType pType)
void clearMap(T &m, Func &clearFunc)
static const Data domainCert("domain_cert_")
Handles cross-platform sockets compatibility.
static const Data bodyData("Body")
static const struct nv flags[]
The abstract base-class for all exceptions thrown by resip code.
const char * what() const noexcept override
Data mDefaultPrivateKeyPassPhrase
void addCertDER(PEMType type, const Data &name, const Data &certDER, bool write)
EVP_PKEY * getUserPrivateKey(const Data &aor)
static int getResipConnectionExDataIdx()
virtual void onReadPEM(const Data &name, PEMType type, Data &buffer) const =0
Data getUserPassPhrase(const Data &aor) const
static SecurityTypes::SSLType parseSSLType(const Data &typeName)
Converts a string containing an SSL type name to the corresponding enum value.
Data getUserPrivateKeyDER(const Data &aor) const
static void dumpAsn(const char *, Data)
void generateUserCert(const Data &aor, int expireDays=365, int keyLen=2048)
void addUserCertPEM(const Data &aor, const Data &certPEM)
static long OpenSSLCTXClearOptions
MultipartSignedContents * signAndEncrypt(const Data &senderAor, Contents *, const Data &recipCertName)
bool hasUserCert(const Data &aor) const
void addPrivateKeyPEM(PEMType type, const Data &name, const Data &privateKeyPEM, bool write, const Data &privateKeyPassPhrase=Data::Empty)
void addCertPEM(PEMType type, const Data &name, const Data &certPEM, bool write)
void removeUserPrivateKey(const Data &aor)
PrivateKeyMap mUserPrivateKeys
Data computeIdentity(const Data &signerDomain, const Data &in) const
virtual void onWritePEM(const Data &name, PEMType type, const Data &buffer) const =0
void addRootCertPEM(const Data &x509PEMEncodedRootCerts)
void addUserCertDER(const Data &aor, const Data &certDER)
X509 * getUserCert(const Data &aor)
static Data getCertName(X509 *cert)
virtual void onRemovePEM(const Data &name, PEMType type) const =0
void addUserPrivateKeyDER(const Data &aor, const Data &certDER, const Data &privateKeyPassPhrase=Data::Empty)
Contents * checkSignature(MultipartSignedContents *, Data *signedBy, SignatureStatus *sigStat)
void setDHParams(SSL_CTX *ctx)
void addPrivateKeyDER(PEMType type, const Data &name, const Data &privateKeyDER, bool write, const Data &privateKeyPassPhrase=Data::Empty)
BaseSecurity(const CipherList &cipherSuite=StrongestSuite, const Data &defaultPrivateKeyPassPhrase=Data::Empty, const Data &dHParamsFilename=Data::Empty)
Data getPrivateKeyPEM(PEMType type, const Data &name) const
void setUserPassPhrase(const Data &aor, const Data &passPhrase)
void addCertX509(PEMType type, const Data &name, X509 *cert, bool write)
Data getDomainCertDER(const Data &domainName) const
EVP_PKEY * getDomainKey(const Data &domain)
static int matchHostNameWithWildcards(const Data &certificateName, const Data &domainName)
Matches a certificate name, which may hold a wildcard, against the domain name we connected to,...
static CipherList StrongestSuite
void removeDomainPrivateKey(const Data &domainName)
static void getCertNames(X509 *cert, std::list< PeerName > &peerNames, bool useEmailAsSIP=false)
static int matchHostName(const Data &certificateName, const Data &domainName)
Applies the certificate and domain name matching rules.
std::map< Data, EVP_PKEY * > PrivateKeyMap
Contents * decrypt(const Data &decryptorAor, const Pkcs7Contents *)
void removeDomainCert(const Data &domainName)
bool checkIdentity(const Data &signerDomain, const Data &in, const Data &sig, X509 *cert=NULL) const
void removeCert(PEMType type, const Data &name)
void checkAndSetIdentity(SipMessage &msg, const Data &derCert=Data::Empty) const
static bool mAllowWildcardCertificates
void addPrivateKeyPKEY(PEMType type, const Data &name, EVP_PKEY *pKey, bool write)
bool hasUserPassPhrase(const Data &aor) const
static CipherList ExportableSuite
Data getDomainPrivateKeyPEM(const Data &domainName) const
void addDomainPrivateKeyPEM(const Data &domainName, const Data &privateKeyPEM, const Data &privateKeyPassPhrase=Data::Empty)
static bool isSelfSigned(const X509 *cert)
bool hasCert(PEMType type, const Data &name, bool logErrors=true) const
void addUserPrivateKeyPEM(const Data &aor, const Data &certPEM, const Data &privateKeyPassPhrase=Data::Empty)
std::map< Data, X509 * > X509Map
Data getUserCertDER(const Data &aor) const
X509_STORE * mRootTlsCerts
PrivateKeyMap mDomainPrivateKeys
void removeUserCert(const Data &aor)
void addDomainCertDER(const Data &domainName, const Data &certDER)
Data getPrivateKeyDER(PEMType type, const Data &name) const
static long parseOpenSSLCTXOption(const Data &optionName)
Converts a string containing an OpenSSL option name (for SSL_CTX_set_options) to the numeric value fr...
X509_STORE * mRootSslCerts
bool hasUserPrivateKey(const Data &aor) const
void removePrivateKey(PEMType type, const Data &name)
void removeUserPassPhrase(const Data &aor)
static long OpenSSLCTXSetOptions
Note:
bool hasPrivateKey(PEMType type, const Data &name) const
PassPhraseMap mUserPassPhrases
X509 * getDomainCert(const Data &domain)
bool hasDomainPrivateKey(const Data &domainName) const
std::vector< CertificateInfo > CertificateInfoContainer
Data getCertDER(PEMType type, const Data &name) const
CertificateInfoContainer getRootCertDescriptions() const
void addDomainCertPEM(const Data &domainName, const Data &certPEM)
MultipartSignedContents * sign(const Data &senderAor, Contents *)
Data getUserPrivateKeyPEM(const Data &aor) const
Pkcs7Contents * encrypt(Contents *, const Data &recipCertName)
bool hasDomainCert(const Data &domainName, bool logErrors=true) const
void addAdditionalFailureString(const Data &additionalFailureString)
Base class for all SIP body types.
void addBuffer(char *buf)
virtual Data getBodyData() const
const H_ContentType::Type & header(const H_ContentType &headerType) const
returns the value of the Content-Type header Throws an Contents::Exception if the header doesn't exis...
EncodeStream & encodeHeaders(EncodeStream &str) const
encodes headers to an output stream
static Contents * createContents(const Mime &contentType, const Data &contents)
factory method to create a Contents object from a mime type and a payload
void preParseHeaders(ParseBuffer &pb)
Preforms preparsing on the headers stored in the ParseBuffer pb.
virtual Contents * clone() const =0
returns a copy of a Contents object
An iostream that operates on an existing Data.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Data base64decode() const
Performs RFC 3548 Base 64 decoding of the contents of this data.
static const Data Empty
Constant that represents a zero-length data.
const char * c_str() const
Returns a null-terminated string representing.
@ Borrow
The Data instance is borrowing the memory from the passed in buffer.
Data base64encode(bool useUrlSafe=false) const
Performs RFC 3548 Base 64 encoding of the contents of this data.
static Data fromFile(const Data &filename)
bool prefix(const Data &pre) const noexcept
Returns true if this Data starts with the bytes indicated by the passed-in Data.
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
bool empty() const noexcept
Checks whether the Data is empty.
size_type size() const noexcept
Returns the number of bytes in this Data.
size_type find(const Data &match, size_type start=0) const
Finds a specified sequence of bytes in this Data.
static const size_type npos
Represents an impossible position; returned to indicate failure to find.
Data hex() const
Returns a hexadecimal representation of the contents of this Data.
Data escaped() const
Returns a representation of the contents of the data with any non-printable characters escaped.
bool postfix(const Data &post) const noexcept
Returns true if this Data ends with the bytes indicated by the passed-in Data.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
static bool isIpAddress(const Data &ipAddress)
bool is_directory() const
EncodeStream & encode(EncodeStream &str) const
Encodes this element to a stream, in the fashion it should be represented on the wire.
Represents the "media-type" element in the RFC 3261 grammar.
virtual void parse(ParseBuffer &pb)
Data getRawFirstPart() const
The first body part exactly as it arrived: header block, the empty line, and the body.
SIP body type for holding Multipart-Signed body contents (MIME content-type multipart/signed).
Provides string-parsing functionality with protection from buffer overflow.
CurrentPosition skipToEnd()
CurrentPosition skipWhitespace()
CurrentPosition skipToChars(const char *cs)
CurrentPosition skipToChar(char c)
CurrentPosition position() const
void reset(const char *pos)
void assertNotEof() const
CurrentPosition skipChar()
CurrentPosition skipToTermCRLF()
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
BaseException used to indicate parse failures.
SIP body type for holding PKCS7 contents (MIME content-type application/pkcs7-mime).
SIP body type for holding PKCS7 Signed contents (MIME content-type application/pkcs7-signature).
static int getCryptoRandom()
void addCADirectory(const Data &caDirectory)
Security(const Data &pathToCerts, const CipherList &=StrongestSuite, const Data &defaultPrivateKeyPassPhrase=Data::Empty, const Data &dHParamsFilename=Data::Empty)
virtual SSL_CTX * createDomainCtx(const SSL_METHOD *method, const Data &domain, const Data &certificateFilename, const Data &privateKeyFilename, const Data &privateKeyPassPhrase)
Throws BaseSecurity::Exception if the certificate or private key can't be loaded; nothing is left all...
virtual void onWritePEM(const Data &name, PEMType type, const Data &buffer) const
virtual void onReadPEM(const Data &name, PEMType type, Data &buffer) const
virtual void updateDomainCtx(SSL_CTX *ctx, const Data &domain, const Data &certificateFilename, const Data &privateKeyFilename, const Data &privateKeyPassPhrase)
Loads the domain's certificate chain and private key into ctx.
virtual void onRemovePEM(const Data &name, PEMType type) const
void loadCAFile(const Data &fileName)
void addCAFile(const Data &caFile)
void loadCADirectory(const Data &directoryName)
Represents a SIP message.
void setSecurityAttributes(std::unique_ptr< SecurityAttributes >) noexcept
const RequestLine & const_header(const RequestLineType &l) const
Data getCanonicalIdentityString() const
static const char * COLON
static const char * SLASH
static const char * CRLFCRLF
static uint64_t getTimeMs()
Returns the current clock time in milliseconds.
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
SSLType
Note: Before adding to the SSLType enum, please see the comments about mTlsCtx in resip/stack/ssl/Sec...
dcm! – add UnusedChecking(_enum) below;
bool isEqualNoCase(const Data &left, const Data &right)
unsigned long long uint64_t
long parseOpenSSLCTXOption(const Data &optionName)
Converts an OpenSSL option name (eg.
std::string strError(int err)