diff --git a/esp/bindings/SOAP/Platform/soapbind.cpp b/esp/bindings/SOAP/Platform/soapbind.cpp index 9f3e7c969ed..4e032dbcb90 100644 --- a/esp/bindings/SOAP/Platform/soapbind.cpp +++ b/esp/bindings/SOAP/Platform/soapbind.cpp @@ -271,24 +271,37 @@ int CHttpSoapBinding::HandleSoapRequest(CHttpRequest* request, CHttpResponse* re return 0; } - -static IPropertyTree *createSecClientConfig(const char *clientCertPath, const char *clientPrivateKey, const char *caCertsPath, bool acceptSelfSigned) +static IPropertyTree *createSecClientConfig(const char *clientCertFileOrBuf, const char *clientPrivKeyFileOrBuf, const char *caCertsPathOrBuf, bool acceptSelfSigned) { Owned info = createPTree(); - if (!isEmptyString(clientCertPath)) + if (!isEmptyString(clientCertFileOrBuf)) { - info->setProp("certificate", clientCertPath); - if (!isEmptyString(clientPrivateKey)) - info->setProp("privatekey", clientPrivateKey); + if (containsEmbeddedKey(clientCertFileOrBuf)) + info->setProp("certificatebuf", clientCertFileOrBuf); + else + info->setProp("certificate", clientCertFileOrBuf); + + if (!isEmptyString(clientPrivKeyFileOrBuf)) + { + if (containsEmbeddedKey(clientPrivKeyFileOrBuf)) + info->setProp("privatekeybuf", clientPrivKeyFileOrBuf); + else + info->setProp("privatekey", clientPrivKeyFileOrBuf); + } } IPropertyTree *verify = ensurePTree(info, "verify"); - if (!isEmptyString(caCertsPath)) + + if (!isEmptyString(caCertsPathOrBuf)) { IPropertyTree *ca = ensurePTree(verify, "ca_certificates"); - ca->setProp("@path", caCertsPath); + if (containsEmbeddedKey(caCertsPathOrBuf)) + ca->setProp("pem", caCertsPathOrBuf); + else + ca->setProp("@path", caCertsPathOrBuf); } + verify->setPropBool("@enable", true); verify->setPropBool("@accept_selfsigned", acceptSelfSigned); verify->setProp("trusted_peers", "anyone"); @@ -313,6 +326,7 @@ void CSoapRequestBinding::post(const char *proxy, const char* url, IRpcResponseB soapclient.setReadTimeoutSecs(readTimeoutSecs_); if (mtls_secret_.length()) soapclient.setMtlsSecretName(mtls_secret_); + if (client_cert_.length() || ca_certs_.length() || accept_self_signed_) soapclient.setSecureSocketConfig(createSecClientConfig(client_cert_, client_priv_key_, ca_certs_, accept_self_signed_)); diff --git a/esp/bindings/SOAP/Platform/soapbind.hpp b/esp/bindings/SOAP/Platform/soapbind.hpp index e93eed6a2eb..c0b8a9375fe 100644 --- a/esp/bindings/SOAP/Platform/soapbind.hpp +++ b/esp/bindings/SOAP/Platform/soapbind.hpp @@ -181,12 +181,17 @@ class esp_http_decl CSoapRequestBinding : public CSoapComplexType, void setMtlsSecretName(const char *name){mtls_secret_.set(name);} const char *getMtlsSecretName(){return mtls_secret_.str();} - void setCACertificates(const char *path) override {ca_certs_.set(path);} + void setCACertificates(const char *path) override + { + ca_certs_.set(path); + } + virtual void setClientCertificate(const char *certPath, const char *privateKeyPath) override { client_cert_.set(certPath); client_priv_key_.set(privateKeyPath); } + virtual void setAcceptSelfSigned(bool acceptSelfSigned) override {accept_self_signed_=acceptSelfSigned;} void post(const char *proxy, const char* url, IRpcResponseBinding& response, const char *action=NULL); @@ -208,20 +213,25 @@ inline void setRpcSSLOptions(IEspClientRpcSettings &rpc, bool useSSL, const char { if (!isEmptyString(clientCert)) { - if (!checkFileExists(clientCert)) - throw makeStringExceptionV(-1,"Client certificate not found %s.", clientCert); if (isEmptyString(clientPrivateKey)) throw makeStringException(-1,"Client private key not provided."); - if (!checkFileExists(clientPrivateKey)) + + if (!containsEmbeddedKey(clientCert) && !checkFileExists(clientCert)) + throw makeStringExceptionV(-1,"Client certificate not found %s.", clientCert); + if (!containsEmbeddedKey(clientPrivateKey) && !checkFileExists(clientPrivateKey)) throw makeStringExceptionV(-1,"Client private key not found %s.", clientPrivateKey); + rpc.setClientCertificate(clientCert, clientPrivateKey); } + if (!isEmptyString(caCert)) { - if (!checkFileExists(caCert)) + if (!containsEmbeddedKey(caCert) && !checkFileExists(caCert)) throw makeStringExceptionV(-1,"CA certificate not found %s.", caCert); + rpc.setCACertificates(caCert); } + rpc.setAcceptSelfSigned(acceptSelfSigned); } } diff --git a/esp/clients/ws_dfsclient/ws_dfsclient.cpp b/esp/clients/ws_dfsclient/ws_dfsclient.cpp index a1d0f544f2d..d622a790210 100644 --- a/esp/clients/ws_dfsclient/ws_dfsclient.cpp +++ b/esp/clients/ws_dfsclient/ws_dfsclient.cpp @@ -471,7 +471,7 @@ class CServiceSuperDistributedFile : public CServiceDistributedFileBaseexistsPhysicalPartFiles(0)) { const char * logicalName = queryLogicalName(); - throw MakeStringException(-1, "Some physical parts do not exists, for logical file : %s",(isEmptyString(logicalName) ? "[unattached]" : logicalName)); + throw makeStringExceptionV(-1, "Some physical parts do not exists, for logical file : %s",(isEmptyString(logicalName) ? "[unattached]" : logicalName)); } } @@ -573,68 +573,22 @@ IClientWsDfs *getDfsClient(const char *serviceUrl, IUserDescriptor *userDesc) return dfsClient.getClear(); } -static CriticalSection localSecretCrit; -static constexpr unsigned cachedSecretTimeoutSecs = 120; // 2 mins static void configureClientSSL(IEspClientRpcSettings &rpc, const char *secretName) { - /* - * This is a bit of a kludge, it gets the certificates from secrets, and writes them to local temp strorage. - * It does this so that it can pass the filename paths to rpc ssl / secure socket layer, which currently only - * accepts filenames, not binary blobs from memory. - */ - StringBuffer clientCertFilename, clientPrivateKeyFilename, caCertFilename; - - StringBuffer tempDirStr; - verifyex(getConfigurationDirectory(getGlobalConfigSP()->queryPropTree("Directories"), "temp", "ssl", "ssl", tempDirStr)); - addPathSepChar(tempDirStr); - tempDirStr.append(secretName); - addPathSepChar(tempDirStr); - - clientCertFilename.append(tempDirStr).append("tls.crt"); - clientPrivateKeyFilename.append(tempDirStr).append("tls.key"); - caCertFilename.append(tempDirStr).append("ca.crt"); - - bool cacheEntryValid = false; - CriticalBlock b(localSecretCrit); - Owned tempDir = createIFile(tempDirStr); - CDateTime timeOutTime, nowTime; - bool dirExists = false; - if (tempDir->getTime(&timeOutTime, nullptr, nullptr)) - { - dirExists = true; - timeOutTime.adjustTimeSecs(cachedSecretTimeoutSecs); - nowTime.setNow(); - if (nowTime.compare(timeOutTime, false) < 0) - cacheEntryValid = true; - } - - if (!cacheEntryValid) - { - if (dirExists) - verifyex(tempDir->setTime(&nowTime, &nowTime, nullptr)); - else - verifyex(tempDir->createDirectory()); - StringBuffer secretValue; - - Owned file = createIFile(clientCertFilename); - Owned io = file->open(IFOcreate); - getSecretValue(secretValue, "storage", secretName, "tls.crt", true); - io->write(0, secretValue.length(), secretValue.str()); - io->close(); - - file.setown(createIFile(clientPrivateKeyFilename)); - io.setown(file->open(IFOcreate)); - getSecretValue(secretValue.clear(), "storage", secretName, "tls.key", true); - io->write(0, secretValue.length(), secretValue.str()); - io->close(); - - file.setown(createIFile(caCertFilename)); - io.setown(file->open(IFOcreate)); - getSecretValue(secretValue.clear(), "storage", secretName, "ca.crt", true); - io->write(0, secretValue.length(), secretValue.str()); - io->close(); - } - setRpcSSLOptions(rpc, true, clientCertFilename, clientPrivateKeyFilename, caCertFilename, false); + Owned secretPTree = getSecret("storage", secretName); + if (!secretPTree) + throw makeStringExceptionV(-1, "secret %s.%s not found", "storage", secretName); + + StringBuffer certSecretBuf; + getSecretKeyValue(certSecretBuf, secretPTree, "tls.crt"); + + StringBuffer privKeySecretBuf; + getSecretKeyValue(privKeySecretBuf, secretPTree, "tls.key"); + + StringBuffer caCertFileBuf; + getSecretKeyValue(caCertFileBuf, secretPTree, "ca.crt"); + + setRpcSSLOptions(rpc, true, certSecretBuf.str(), privKeySecretBuf.str(), caCertFileBuf.str(), false); } static CriticalSection serviceLeaseMapCS; diff --git a/system/jlib/jsecrets.cpp b/system/jlib/jsecrets.cpp index 0bd6f034426..8a99f467dc7 100644 --- a/system/jlib/jsecrets.cpp +++ b/system/jlib/jsecrets.cpp @@ -1066,6 +1066,25 @@ const MemoryAttr &getSecretUdpKey(bool required) return udpKey; } +jlib_decl bool containsEmbeddedKey(const char *certificate) +{ + // look for any of: + // -----BEGIN PRIVATE KEY----- + // -----BEGIN RSA PRIVATE KEY----- + // -----BEGIN CERTIFICATE----- + // -----BEGIN PUBLIC KEY----- + // or maybe just: + // -----BEGIN + + if ( (strstr(certificate, "-----BEGIN PRIVATE KEY-----")) || + (strstr(certificate, "-----BEGIN RSA PRIVATE KEY-----")) || + (strstr(certificate, "-----BEGIN PUBLIC KEY-----")) || + (strstr(certificate, "-----BEGIN CERTIFICATE-----")) ) + return true; + + return false; +} + IPropertyTree *createTlsClientSecretInfo(const char *issuer, bool mutual, bool acceptSelfSigned, bool addCACert) { if (isEmptyString(issuer)) diff --git a/system/jlib/jsecrets.hpp b/system/jlib/jsecrets.hpp index 652c3a09ca2..c473cdc0c84 100644 --- a/system/jlib/jsecrets.hpp +++ b/system/jlib/jsecrets.hpp @@ -36,6 +36,8 @@ extern jlib_decl bool getSecretValue(StringBuffer & result, const char *category extern jlib_decl void initSecretUdpKey(); extern jlib_decl const MemoryAttr &getSecretUdpKey(bool required); +extern jlib_decl bool containsEmbeddedKey(const char *certificate); + extern jlib_decl IPropertyTree *queryTlsSecretInfo(const char *issuer); extern jlib_decl IPropertyTree *createTlsClientSecretInfo(const char *issuer, bool mutual, bool acceptSelfSigned, bool addCACert=true); diff --git a/system/security/cryptohelper/cryptocommon.hpp b/system/security/cryptohelper/cryptocommon.hpp index 0644b456c71..0261dfe201d 100644 --- a/system/security/cryptohelper/cryptocommon.hpp +++ b/system/security/cryptohelper/cryptocommon.hpp @@ -21,10 +21,12 @@ #if defined(_USE_OPENSSL) #include +#include #include #include #include #include +#include #include "jiface.hpp" #include "jbuff.hpp" @@ -39,7 +41,19 @@ jlib_decl void throwEVPExceptionV(int code, const char *format, ...) __attribute inline void voidBIOfree(BIO *bio) { BIO_free(bio); } inline void voidOpenSSLFree(void *m) { OPENSSL_free(m); } +inline void voidSSLCTXfree(SSL_CTX *ctx) +{ + if (ctx) + SSL_CTX_free(ctx); +} +inline void voidX509StkPopFree(STACK_OF(X509_INFO) *infoStk) +{ + if (infoStk) + sk_X509_INFO_pop_free(infoStk, X509_INFO_free); +} +typedef OwnedPtrCustomFree OwnedX509Stkptr; +typedef OwnedPtrCustomFree OwnedSSLCTXptr; typedef OwnedPtrCustomFree OwnedEVPBio; typedef OwnedPtrCustomFree OwnedEVPPkey; typedef OwnedPtrCustomFree OwnedEVPPkeyCtx; diff --git a/system/security/securesocket/CMakeLists.txt b/system/security/securesocket/CMakeLists.txt index 6562eff4dac..68d0427059d 100644 --- a/system/security/securesocket/CMakeLists.txt +++ b/system/security/securesocket/CMakeLists.txt @@ -32,6 +32,7 @@ set ( SRCS include_directories ( ./../../include ./../../jlib + ./../cryptohelper ./../../security/shared ${OPENSSL_INCLUDE_DIR} ) diff --git a/system/security/securesocket/securesocket.cpp b/system/security/securesocket/securesocket.cpp index 32a6639c58f..9e05ccf5635 100644 --- a/system/security/securesocket/securesocket.cpp +++ b/system/security/securesocket/securesocket.cpp @@ -62,8 +62,11 @@ #include #include "jsmartsock.ipp" +#include "cryptocommon.hpp" #include "securesocket.hpp" +using namespace cryptohelper; + static JSocketStatistics *SSTATS; #define CHK_NULL(x) if((x)==NULL) exit(1) @@ -76,7 +79,6 @@ static JSocketStatistics *SSTATS; throw createJSocketException(err, msg); \ } - static int pem_passwd_cb(char* buf, int size, int rwflag, void* password) { strncpy(buf, (char*)password, size); @@ -1157,10 +1159,115 @@ const char* strtok__(const char* s, const char* d, StringBuffer& tok) return s; } -class CSecureSocketContext : implements ISecureSocketContext, public CInterface +static bool usePrivateKeyPEMBuffer(SSL_CTX *ctx, const char *privKeyBuf, int privKeyLen=-1) +{ + // single RSA key in buffer + + OwnedEVPBio cbio(BIO_new_mem_buf(privKeyBuf, privKeyLen)); + if (!cbio) + return false; + + OwnedEVPRSA rsa(PEM_read_bio_RSAPrivateKey(cbio, NULL, 0, NULL)); + if (!rsa) + return false; + + if (!SSL_CTX_use_RSAPrivateKey(ctx, rsa)) + return false; + + return true; +} + +static bool useCertificateChainPEMBuffer(SSL_CTX *ctx, const char *certBuf, int certLen=-1) +{ + // this routine based on code originally from: + // https://stackoverflow.com/questions/3810058/read-certificate-files-from-memory-instead-of-a-file-using-openssl + + // can have multiple certs in buffer + + OwnedEVPBio cbio(BIO_new_mem_buf(certBuf, certLen)); + if (!cbio) + return false; + + OwnedX509Stkptr infoStk(PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL)); + if (!infoStk) + return false; + + bool first = true; + X509_INFO *infoVal; + for (int i=0; ix509) + { + // First cert is server/main cert. Remaining, if any, are intermediate certs. + if (first) + { + first = false; + + // Set server certificate. Note that this operation increments the + // reference count, which means that it is okay for cleanup to free it. + if (!SSL_CTX_use_certificate(ctx, infoVal->x509)) + return false; + + if (ERR_peek_last_error() != 0) + return false; + + // Get ready to store intermediate certs, if any. + SSL_CTX_clear_chain_certs(ctx); + } + else + { + // Add intermediate cert to chain. + if (!SSL_CTX_add0_chain_cert(ctx, infoVal->x509)) + return false; + + // Above function doesn't increment cert reference count. NULL the + // reference to it in order to prevent it from being freed during cleanup. + infoVal->x509 = NULL; + } + } + } + + return true; +} + +static bool loadVerifyLocationsPEMBuffer(SSL_CTX *ctx, const char *caCertBuf, int caCertLen=-1) +{ + // this routine based on code originally from: + // https://stackoverflow.com/questions/5052563/c-openssl-use-root-ca-from-buffer-rather-than-file-ssl-ctx-load-verify-locat + + // can have multiple certs in buffer + + OwnedEVPBio cbio(BIO_new_mem_buf(caCertBuf, caCertLen)); + if (!cbio) + return false; + + OwnedX509Stkptr infoStk(PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL)); + if (!infoStk) + return false; + + X509_STORE *store = SSL_CTX_get_cert_store(ctx); + + X509_INFO *infoVal; + for (int i = 0; i < sk_X509_INFO_num(infoStk); i++) + { + infoVal = sk_X509_INFO_value(infoStk, i); + if (infoVal->x509) + { + if (!X509_STORE_add_cert(store, infoVal->x509)) + return false; + + infoVal->x509 = NULL; + } + } + + return true; +} + +class CSecureSocketContext : public CInterfaceOf { private: - SSL_CTX* m_ctx = nullptr; + OwnedSSLCTXptr m_ctx; #if (OPENSSL_VERSION_NUMBER > 0x00909000L) const SSL_METHOD* m_meth = nullptr; #else @@ -1177,97 +1284,99 @@ class CSecureSocketContext : implements ISecureSocketContext, public CInterface SSL_CTX_set_session_id_context(m_ctx, (const unsigned char*)"hpccsystems", 11); } -public: - IMPLEMENT_IINTERFACE; - CSecureSocketContext(SecureSocketType sockettype) + void initContext(SecureSocketType sockettype) { - m_verify = false; - m_address_match = false; - if(sockettype == ClientSocket) m_meth = SSLv23_client_method(); else m_meth = SSLv23_server_method(); - m_ctx = SSL_CTX_new(m_meth); + m_ctx.setown(SSL_CTX_new(m_meth)); if(!m_ctx) - { - throw MakeStringException(-1, "ctx can't be created"); - } + throw makeStringException(-1, "ctx can't be created"); if (sockettype == ServerSocket) setSessionIdContext(); - - SSL_CTX_set_mode(m_ctx, SSL_CTX_get_mode(m_ctx) | SSL_MODE_AUTO_RETRY); } - CSecureSocketContext(const char* certfile, const char* privkeyfile, const char* passphrase, SecureSocketType sockettype) + void setCertificate(const char *certFileOrBuf) { - m_verify = false; - m_address_match = false; + if (isEmptyString(certFileOrBuf)) + return; - if(sockettype == ClientSocket) - m_meth = SSLv23_client_method(); - else - m_meth = SSLv23_server_method(); + if (containsEmbeddedKey(certFileOrBuf)) + { + // can have multiple certs in buffer + if (!useCertificateChainPEMBuffer(m_ctx, certFileOrBuf)) + throw makeEVPException(-1, "error loading certificate chain"); + } + else if (SSL_CTX_use_certificate_chain_file(m_ctx, certFileOrBuf) <= 0) + throw makeEVPExceptionV(-1, "error loading certificate chain file %s", certFileOrBuf); + } - m_ctx = SSL_CTX_new(m_meth); + void setPrivateKey(const char *privKeyFileOrBuf) + { + if (isEmptyString(privKeyFileOrBuf)) + return; - if(!m_ctx) + if (containsEmbeddedKey(privKeyFileOrBuf)) { - throw MakeStringException(-1, "ctx can't be created"); + // single RSA key in buffer + if (!usePrivateKeyPEMBuffer(m_ctx, privKeyFileOrBuf)) + throw makeEVPException(-1, "error loading private key"); } + else if (SSL_CTX_use_PrivateKey_file(m_ctx, privKeyFileOrBuf, SSL_FILETYPE_PEM) <= 0) + throw makeEVPExceptionV(-1, "error loading private key file %s", privKeyFileOrBuf); - if (sockettype == ServerSocket) - setSessionIdContext(); + if (!SSL_CTX_check_private_key(m_ctx)) + throw makeStringException(-1, "Private key does not match the certificate public key"); + } - password.set(passphrase); - SSL_CTX_set_default_passwd_cb_userdata(m_ctx, (void*)password.str()); - SSL_CTX_set_default_passwd_cb(m_ctx, pem_passwd_cb); + void setVerifyLocations(const char *caCertsPathOrBuf) + { + if (isEmptyString(caCertsPathOrBuf)) + return; - if (SSL_CTX_use_certificate_chain_file(m_ctx, certfile)<=0) + if (containsEmbeddedKey(caCertsPathOrBuf)) { - char errbuf[512]; - ERR_error_string_n(ERR_get_error(), errbuf, 512); - throw MakeStringException(-1, "error loading certificate chain file %s - %s", certfile, errbuf); + // can have multiple certs in buffer + if (!loadVerifyLocationsPEMBuffer(m_ctx, caCertsPathOrBuf)) + throw makeStringException(-1, "Error loading CA certificates"); } + else if (SSL_CTX_load_verify_locations(m_ctx, caCertsPathOrBuf, NULL) != 1) + throw makeStringExceptionV(-1, "Error loading CA certificates from %s", caCertsPathOrBuf); + } - if(SSL_CTX_use_PrivateKey_file(m_ctx, privkeyfile, SSL_FILETYPE_PEM) <= 0) - { - char errbuf[512]; - ERR_error_string_n(ERR_get_error(), errbuf, 512); - throw MakeStringException(-1, "error loading private key file %s - %s", privkeyfile, errbuf); - } +public: + CSecureSocketContext(SecureSocketType sockettype) + { + initContext(sockettype); - if(!SSL_CTX_check_private_key(m_ctx)) - { - throw MakeStringException(-1, "Private key does not match the certificate public key"); - } - SSL_CTX_set_mode(m_ctx, SSL_CTX_get_mode(m_ctx) | SSL_MODE_AUTO_RETRY); } - CSecureSocketContext(const IPropertyTree* config, SecureSocketType sockettype) + CSecureSocketContext(const char* certFileOrBuf, const char* privKeyFileOrBuf, const char* passphrase, SecureSocketType sockettype) { - assertex(config); - m_verify = false; - m_address_match = false; + initContext(sockettype); - if(sockettype == ClientSocket) - m_meth = SSLv23_client_method(); - else - m_meth = SSLv23_server_method(); + // MCK TODO: should we set a default cipherList, as is done in other ctor (below) ? - m_ctx = SSL_CTX_new(m_meth); + password.set(passphrase); + SSL_CTX_set_default_passwd_cb_userdata(m_ctx, (void*)password.str()); + SSL_CTX_set_default_passwd_cb(m_ctx, pem_passwd_cb); - if(!m_ctx) - { - throw MakeStringException(-1, "ctx can't be created"); - } + setCertificate(certFileOrBuf); + setPrivateKey(privKeyFileOrBuf); - if (sockettype == ServerSocket) - setSessionIdContext(); + SSL_CTX_set_mode(m_ctx, SSL_CTX_get_mode(m_ctx) | SSL_MODE_AUTO_RETRY); + } + + CSecureSocketContext(const IPropertyTree* config, SecureSocketType sockettype) + { + assertex(config); + + initContext(sockettype); const char *cipherList = config->queryProp("cipherList"); if (!cipherList || !*cipherList) @@ -1275,7 +1384,7 @@ class CSecureSocketContext : implements ISecureSocketContext, public CInterface SSL_CTX_set_cipher_list(m_ctx, cipherList); const char* passphrase = config->queryProp("passphrase"); - if(passphrase && *passphrase) + if (passphrase && *passphrase) { StringBuffer pwd; decrypt(pwd, passphrase); @@ -1284,32 +1393,18 @@ class CSecureSocketContext : implements ISecureSocketContext, public CInterface SSL_CTX_set_default_passwd_cb(m_ctx, pem_passwd_cb); } - const char* certfile = config->queryProp("certificate"); - if(certfile && *certfile) - { - if (SSL_CTX_use_certificate_chain_file(m_ctx, certfile) <= 0) - { - char errbuf[512]; - ERR_error_string_n(ERR_get_error(), errbuf, 512); - throw MakeStringException(-1, "error loading certificate chain file %s - %s", certfile, errbuf); - } - } + const char *certFileOrBuf = config->queryProp("certificatebuf"); + if (!certFileOrBuf) + certFileOrBuf = config->queryProp("certificate"); + if (certFileOrBuf && *certFileOrBuf) + setCertificate(certFileOrBuf); + + const char *privKeyFileOrBuf = config->queryProp("privatekeybuf"); + if (!privKeyFileOrBuf) + privKeyFileOrBuf = config->queryProp("privatekey"); + if (privKeyFileOrBuf && *privKeyFileOrBuf) + setPrivateKey(privKeyFileOrBuf); - const char* privkeyfile = config->queryProp("privatekey"); - if(privkeyfile && *privkeyfile) - { - if(SSL_CTX_use_PrivateKey_file(m_ctx, privkeyfile, SSL_FILETYPE_PEM) <= 0) - { - char errbuf[512]; - ERR_error_string_n(ERR_get_error(), errbuf, 512); - throw MakeStringException(-1, "error loading private key file %s - %s", privkeyfile, errbuf); - } - if(!SSL_CTX_check_private_key(m_ctx)) - { - throw MakeStringException(-1, "Private key does not match the certificate public key"); - } - } - SSL_CTX_set_mode(m_ctx, SSL_CTX_get_mode(m_ctx) | SSL_MODE_AUTO_RETRY); m_verify = config->getPropBool("verify/@enable"); @@ -1317,14 +1412,11 @@ class CSecureSocketContext : implements ISecureSocketContext, public CInterface if(m_verify) { - const char* capath = config->queryProp("verify/ca_certificates/@path"); - if(capath && *capath) - { - if(SSL_CTX_load_verify_locations(m_ctx, capath, NULL) != 1) - { - throw MakeStringException(-1, "Error loading CA certificates from %s", capath); - } - } + const char *caCertPathOrBuf = config->queryProp("verify/ca_certificates/pem"); + if (!caCertPathOrBuf) + caCertPathOrBuf = config->queryProp("verify/ca_certificates/@path"); + if (caCertPathOrBuf && *caCertPathOrBuf) + setVerifyLocations(caCertPathOrBuf); bool acceptSelfSigned = config->getPropBool("verify/@accept_selfsigned"); SSL_CTX_set_verify(m_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, (acceptSelfSigned) ? verify_callback_allow_selfSigned : verify_callback_reject_selfSigned); @@ -1370,11 +1462,6 @@ class CSecureSocketContext : implements ISecureSocketContext, public CInterface } } - ~CSecureSocketContext() - { - SSL_CTX_free(m_ctx); - } - ISecureSocket* createSecureSocket(ISocket* sock, int loglevel, const char *fqdn) { return new CSecureSocket(sock, m_ctx, m_verify, m_address_match, m_peers, loglevel, fqdn); @@ -1873,9 +1960,9 @@ SECURESOCKET_API ISecureSocketContext* createSecureSocketContext(SecureSocketTyp return new securesocket::CSecureSocketContext(sockettype); } -SECURESOCKET_API ISecureSocketContext* createSecureSocketContextEx(const char* certfile, const char* privkeyfile, const char* passphrase, SecureSocketType sockettype) +SECURESOCKET_API ISecureSocketContext* createSecureSocketContextEx(const char* certFileOrBuf, const char* privKeyFileOrBuf, const char* passphrase, SecureSocketType sockettype) { - return new securesocket::CSecureSocketContext(certfile, privkeyfile, passphrase, sockettype); + return new securesocket::CSecureSocketContext(certFileOrBuf, privKeyFileOrBuf, passphrase, sockettype); } SECURESOCKET_API ISecureSocketContext* createSecureSocketContextEx2(const IPropertyTree* config, SecureSocketType sockettype) diff --git a/system/security/securesocket/securesocket.hpp b/system/security/securesocket/securesocket.hpp index b315600c7ab..cd3001b8460 100644 --- a/system/security/securesocket/securesocket.hpp +++ b/system/security/securesocket/securesocket.hpp @@ -81,14 +81,14 @@ interface ICertificate : implements IInterface }; typedef ISecureSocketContext* (*createSecureSocketContext_t)(SecureSocketType); -typedef ISecureSocketContext* (*createSecureSocketContextEx_t)(const char* certfile, const char* privkeyfile, const char* passphrase, SecureSocketType); +typedef ISecureSocketContext* (*createSecureSocketContextEx_t)(const char* certFileOrBuf, const char* privKeyFileOrBuf, const char* passphrase, SecureSocketType); typedef ISecureSocketContext* (*createSecureSocketContextEx2_t)(IPropertyTree* config, SecureSocketType); typedef ISecureSocketContext* (*createSecureSocketContextSecret_t)(const char *mtlsSecretName, SecureSocketType); extern "C" { SECURESOCKET_API ISecureSocketContext* createSecureSocketContext(SecureSocketType); -SECURESOCKET_API ISecureSocketContext* createSecureSocketContextEx(const char* certfile, const char* privkeyfile, const char* passphrase, SecureSocketType); +SECURESOCKET_API ISecureSocketContext* createSecureSocketContextEx(const char* certFileOrBuf, const char* privKeyFileOrBuf, const char* passphrase, SecureSocketType); SECURESOCKET_API ISecureSocketContext* createSecureSocketContextEx2(const IPropertyTree* config, SecureSocketType); SECURESOCKET_API ISecureSocketContext* createSecureSocketContextSSF(ISmartSocketFactory* ssf); SECURESOCKET_API ISecureSocketContext* createSecureSocketContextSecret(const char *mtlsSecretName, SecureSocketType);