37#include "blocxx/BLOCXX_config.h"
38#ifdef BLOCXX_HAVE_OPENSSL
54#include <openssl/rand.h>
55#include <openssl/err.h>
61#include <sys/resource.h>
65#ifdef BLOCXX_HAVE_SYS_TYPES_H
69#ifdef BLOCXX_HAVE_SYS_STAT_H
73#ifdef BLOCXX_HAVE_UNISTD_H
86struct CRYPTO_dynlock_value
219 if (SSLCtxMgr::isClient() || SSLCtxMgr::isServer())
221 Secure::rand_save_state();
253SSL_CTX* SSLCtxMgr::m_ctxClient = 0;
254SSL_CTX* SSLCtxMgr::m_ctxServer = 0;
261SSLCtxMgr::getOpenSSLErrorDescription()
279void SSLCtxMgr::disableSSLInit()
284 BLOCXX_THROW(SSLException,
"SSLCtxMgr::disableSSLInit(): init() cannot be disabled as it has already been called");
291void SSLCtxMgr::disableLocks()
296 BLOCXX_THROW(SSLException,
"SSLCtxMgr::disableSSLLocks(): locks cannot be disabled as they are already in use");
303Bool SSLCtxMgr::getSSLInitDisabled()
311Bool SSLCtxMgr::getSSLLocksDisabled()
335 BLOCXX_THROW(SSLException, Format(
"SSLCtxMgr::initCtx(): Couldn't read certificate from file: %1: %2",
344 BLOCXX_THROW(SSLException, Format(
"SSLCtxMgr::initCtx(): Unable to set private key: %1",
351 BLOCXX_THROW(SSLException, Format(
"SSLCtxMgr::initCtx(): Couldn't read key from file: %1: %2",
417 BLOCXX_THROW(SSLException,
"SSLCtxMgr::initCtx(): no certificate file specified");
426 String
sessID(
"SSL_SESSION_");
427 sessID += String(Secure::rand_range<UInt16>(0, 10000));
441SSLCtxMgr::pem_passwd_cb(
char*
buf,
int size,
int ,
447 buf[size - 1] =
'\0';
585SSLCtxMgr::uninitClient()
595SSLCtxMgr::uninitServer()
641 owctx->peerCertPassedVerify = OWSSLContext::VERIFY_FAIL;
647 if (
owctx->peerCertPassedVerify != OWSSLContext::VERIFY_FAIL)
649 owctx->peerCertPassedVerify = OWSSLContext::VERIFY_PASS;
680 m_ctx = SSLCtxMgr::initCtx(opts.certfile, opts.keyfile, opts.pkey);
682 SSLCtxMgr::generateEphRSAKey(m_ctx);
683 String sessID(
"SSL_SESSION_");
684 sessID += String(Secure::rand_range<UInt16>(0, 10000));
686 (SSL_MAX_SSL_SESSION_ID_LENGTH < (sessID.length())) ?
687 SSL_MAX_SSL_SESSION_ID_LENGTH : (sessID.length());
689 if (SSL_CTX_set_session_id_context(m_ctx,
reinterpret_cast<const unsigned char*
>(sessID.c_str()), sessIDLen) != 1)
692 BLOCXX_THROW(SSLException, Format(
"SSLCtxMgr::initServer(): SSL_CTX_set_session_id_context failed: %1", SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
695 if (opts.verifyMode != SSLOpts::MODE_DISABLED && !opts.trustStore.empty())
697 if (!FileSystem::exists(opts.trustStore))
700 BLOCXX_THROW(SSLException, Format(
"Error loading truststore %1",
701 opts.trustStore).c_str());
703 if (SSL_CTX_load_verify_locations(m_ctx,0,opts.trustStore.c_str()) != 1)
706 BLOCXX_THROW(SSLException, Format(
"Error loading truststore %1: %2", opts.trustStore, SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
715 switch (opts.verifyMode)
717 case SSLOpts::MODE_DISABLED:
718 SSL_CTX_set_verify(m_ctx, SSL_VERIFY_NONE, 0);
720 case SSLOpts::MODE_REQUIRED:
721 SSL_CTX_set_verify(m_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
723 case SSLOpts::MODE_OPTIONAL:
724 case SSLOpts::MODE_AUTOUPDATE:
725 SSL_CTX_set_verify(m_ctx, SSL_VERIFY_PEER, verify_callback);
732 SSL_CTX_set_verify_depth(m_ctx, 4);
737SSLCtxBase::~SSLCtxBase()
749SSLCtxBase::getSSLCtx()
const
755 : verifyMode(MODE_DISABLED)
772SSLServerCtx::SSLServerCtx(
const SSLOpts& opts)
777SSLClientCtx::SSLClientCtx(
const SSLOpts& opts)
785SSLTrustStore::SSLTrustStore(
const String& storeLocation)
786 : m_store(storeLocation)
788 m_mapfile = m_store +
"/map";
789 if (FileSystem::exists(m_mapfile))
791 MutexLock mlock(m_mapGuard);
798SSLTrustStore::getUser(
const String& certhash, String& user, String& uid)
800 MutexLock mlock(m_mapGuard);
801 Map<String, UserInfo>::const_iterator iter = m_map.find(certhash);
802 if (iter == m_map.end())
806 user = iter->second.user;
807 uid = iter->second.uid;
813SSLTrustStore::addCertificate(X509* cert,
const String& user,
const String& uid)
815 static const int numtries = 1000;
818 unsigned long hash = X509_subject_name_hash(cert);
819 ss << std::hex << hash;
820 String filename = m_store +
"/" + ss.toString() +
".";
822 for (
i = 0;
i < numtries; ++
i)
824 String temp = filename + String(
i);
825 if (FileSystem::exists(temp))
834 BLOCXX_THROW(SSLException,
"Unable to find a valid filename to store cert");
836 FILE* fp = fopen(filename.c_str(),
"w");
839 BLOCXX_THROW_ERRNO_MSG(SSLException, Format(
"Unable to open new cert file for writing: %1", filename).c_str());
845 if (PEM_write_X509(fp, cert) != 1)
848 BLOCXX_THROW(SSLException, Format(
"SSL error while writing certificate to %1: %2", filename, SSLCtxMgr::getOpenSSLErrorDescription()).c_str());
852 String digest = getCertMD5Fingerprint(cert);
853 MutexLock mlock(m_mapGuard);
857 m_map[digest] = info;
863SSLTrustStore::getCertMD5Fingerprint(X509* cert)
865 unsigned char digest[16];
866 unsigned int len = 16;
867 X509_digest(cert, EVP_md5(), digest, &len);
868 return MD5::convertBinToHex(digest);
873SSLTrustStore::writeMap()
875 std::ofstream f(m_mapfile.c_str(), std::ios::out);
880 for (Map<String, UserInfo>::const_iterator iter = m_map.begin();
881 iter != m_map.end(); ++iter)
883 f << iter->first <<
" " << iter->second.user
884 <<
" " << iter->second.uid <<
"\n";
891SSLTrustStore::readMap()
893 std::ifstream f(m_mapfile.c_str(), std::ios::in);
901 String line = String::getLine(f);
908 if (toks.size() != 3 && toks.size() != 2)
910 BLOCXX_THROW(SSLException, Format(
"Error processing user map %1 at line %2", m_mapfile, lineno).c_str());
914 if (toks.size() == 3)
918 m_map.insert(std::make_pair(toks[0], info));
921 std::cerr <<
"cert<>user map initizialized with " << m_map.size() <<
" users" << std::endl;
928OWSSLContext::OWSSLContext()
929 : peerCertPassedVerify(VERIFY_NONE)
933OWSSLContext::~OWSSLContext()
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(),...
#define BLOCXX_ASSERTMSG(CON, MSG)
BLOCXX_ASSERTMSG works the same as BLOCXX_ASSERT, but with a second string parameter that will be add...
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
#define BLOCXX_THROW_ERRNO_MSG(exType, msg)
Throw an exception using FILE, LINE, errno and strerror(errno)
#define BLOCXX_GLOBAL_MUTEX_INIT()
#define BLOCXX_LAZY_GLOBAL_INIT(...)
Statically initialize a LazyGlobal instance.
void acquire()
Acquire ownership of this Mutex object.
BLOCXX_COMMON_API String getPass(const String &prompt)
The getpass function displays a prompt to the standard error output, and reads in a password from /de...
BLOCXX_COMMON_API UInt64 thread_t_ToUInt64(Thread_t thr)
Convert a Thread_t to an UInt64.
Array< String > StringArray
bool operator==(const Array< T > &x, const Array< T > &y)
LazyGlobal< Mutex, int, GlobalMutexFactory > GlobalMutex