Skip to content

Commit

Permalink
Allow server contexted to be updated on subsequent accepts
Browse files Browse the repository at this point in the history
Signed-off-by: Gavin Halliday <[email protected]>
  • Loading branch information
ghalliday committed Oct 25, 2023
1 parent 5db015c commit eb41e66
Showing 1 changed file with 51 additions and 37 deletions.
88 changes: 51 additions & 37 deletions system/security/securesocket/securesocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ static void readBio(BIO* bio, StringBuffer& buf)
}
}


interface ISecureSocketContextCallback : implements IInterface
{
virtual unsigned getVersion() = 0; // Check the version of the context to see if the SSL context needs to be recreated
virtual SSL * createActiveSSL() = 0; // Must be called after getVersion()
};

//Use a namespace to prevent clashes with a class of the same name in jhtree
namespace securesocket
{
Expand Down Expand Up @@ -137,6 +144,7 @@ class CSecureSocket : implements ISecureSocket, public CInterface
{
private:
SSL* m_ssl;
Linked<ISecureSocketContextCallback> contextCallback;
Owned<ISocket> m_socket;
bool m_verify;
bool m_address_match;
Expand All @@ -147,6 +155,7 @@ class CSecureSocket : implements ISecureSocket, public CInterface
size32_t nextblocksize = 0;
unsigned blockflags = BF_ASYNC_TRANSFER;
unsigned blocktimeoutms = WAIT_FOREVER;
unsigned contextVersion;
#ifdef USERECVSEM
static Semaphore receiveblocksem;
bool receiveblocksemowned; // owned by this socket
Expand All @@ -158,8 +167,7 @@ class CSecureSocket : implements ISecureSocket, public CInterface
public:
IMPLEMENT_IINTERFACE;

CSecureSocket(ISocket* sock, SSL_CTX* ctx, bool verify = false, bool addres_match = false, CStringSet* m_peers = NULL, int loglevel=SSLogNormal, const char *fqdn = nullptr);
CSecureSocket(int sockfd, SSL_CTX* ctx, bool verify = false, bool addres_match = false, CStringSet* m_peers = NULL, int loglevel=SSLogNormal, const char *fqdn = nullptr);
CSecureSocket(ISocket* sock, int sockfd, ISecureSocketContextCallback * callback, bool verify = false, bool addres_match = false, CStringSet* m_peers = NULL, int loglevel=SSLogNormal, const char *fqdn = nullptr);
~CSecureSocket();

virtual int secure_accept(int logLevel);
Expand All @@ -173,6 +181,21 @@ class CSecureSocket : implements ISecureSocket, public CInterface
virtual size32_t writetms(void const* buf, size32_t size, unsigned timeoutms=WAIT_FOREVER);

void readTimeout(void* buf, size32_t min_size, size32_t max_size, size32_t &size_read, unsigned timeout, bool useSeconds);
void checkForUpdatedContext()
{
//Check if a new ssl context should be created.
//No need for a critical section because the socket functions are never accessed by multiple threads at the same time
//It is possible that createActiveSSL() may be for a later version - but that will only mean that the same context
//is recreated when the version number is seen to have chanegd.
unsigned activeVersion = contextCallback->getVersion();
if (activeVersion != contextVersion)
{
contextVersion = activeVersion;
SSL_free(m_ssl);
m_ssl = contextCallback->createActiveSSL();
}
}


virtual StringBuffer& get_ssl_version(StringBuffer& ver)
{
Expand Down Expand Up @@ -467,38 +490,14 @@ Semaphore CSecureSocket::receiveblocksem(2);
/**************************************************************************
* CSecureSocket -- secure socket layer implementation using openssl *
**************************************************************************/
CSecureSocket::CSecureSocket(ISocket* sock, SSL_CTX* ctx, bool verify, bool address_match, CStringSet* peers, int loglevel, const char *fqdn)
CSecureSocket::CSecureSocket(ISocket* sock, int sockfd, ISecureSocketContextCallback * callback, bool verify, bool address_match, CStringSet* peers, int loglevel, const char *fqdn)
: contextCallback(callback)
{
if (sock)
sockfd = sock->OShandle();
m_socket.setown(sock);
m_ssl = SSL_new(ctx);

m_verify = verify;
m_address_match = address_match;
m_peers = peers;;
m_loglevel = loglevel;
m_isSecure = false;

if(m_ssl == NULL)
{
throw MakeStringException(-1, "Can't create ssl");
}

// there is no MSG_NOSIGNAL or SO_NOSIGPIPE for SSL_write() ...
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif

SSL_set_fd(m_ssl, sock->OShandle());

if (fqdn)
m_fqdn.set(fqdn);
}

CSecureSocket::CSecureSocket(int sockfd, SSL_CTX* ctx, bool verify, bool address_match, CStringSet* peers, int loglevel, const char *fqdn)
{
//m_socket.setown(sock);
//m_socket.setown(ISocket::attach(sockfd));
m_ssl = SSL_new(ctx);
contextVersion = callback->getVersion();
m_ssl = callback->createActiveSSL();

m_verify = verify;
m_address_match = address_match;
Expand Down Expand Up @@ -652,6 +651,7 @@ bool CSecureSocket::verify_cert(X509* cert)

int CSecureSocket::secure_accept(int logLevel)
{
checkForUpdatedContext();
int err;
err = SSL_accept(m_ssl);
if(err == 0)
Expand Down Expand Up @@ -1268,7 +1268,7 @@ static bool setVerifyCertsPEMBuffer(SSL_CTX *ctx, const char *caCertBuf, int caC
return true;
}

class CSecureSocketContext : public CInterfaceOf<ISecureSocketContext>
class CSecureSocketContext : implements ISecureSocketContext, implements ISecureSocketContextCallback, public CInterface
{
private:
SecureSocketType sockettype;
Expand Down Expand Up @@ -1463,6 +1463,8 @@ class CSecureSocketContext : public CInterfaceOf<ISecureSocketContext>
}

public:
IMPLEMENT_IINTERFACE

CSecureSocketContext(const IPropertyTree* config, SecureSocketType _sockettype) : sockettype(_sockettype)
{
createNewContext(config);
Expand All @@ -1479,19 +1481,31 @@ class CSecureSocketContext : public CInterfaceOf<ISecureSocketContext>
createNewContext(config);
}

//interface ISecureSocketContext
ISecureSocket* createSecureSocket(ISocket* sock, int loglevel, const char *fqdn)
{
CriticalBlock block(cs);
checkForUpdatedContext();
return new CSecureSocket(sock, m_ctx, m_verify, m_address_match, m_peers, loglevel, fqdn);
return new CSecureSocket(sock, 0, this, m_verify, m_address_match, m_peers, loglevel, fqdn);
}

ISecureSocket* createSecureSocket(int sockfd, int loglevel, const char *fqdn)
{
return new CSecureSocket(nullptr, sockfd, this, m_verify, m_address_match, m_peers, loglevel, fqdn);
}

//interface ISecureSocketContextCallback
virtual unsigned getVersion()
{
CriticalBlock block(cs);
checkForUpdatedContext();
return new CSecureSocket(sockfd, m_ctx, m_verify, m_address_match, m_peers, loglevel, fqdn);
return configVersion;
}
virtual SSL * createActiveSSL()
{
//If this function is called it is either a new socket or getVersion() has been called to check it is up to date
CriticalBlock block(cs);
return SSL_new(m_ctx);
}

};

class CRsaCertificate : implements ICertificate, public CInterface
Expand Down

0 comments on commit eb41e66

Please sign in to comment.