class CModule;
-class CZNCSock : public Csock {
-public:
- CZNCSock(int timeout = 60);
- CZNCSock(const CString& sHost, u_short port, int timeout = 60);
- ~CZNCSock() {}
+class CZNCSock : public Csock, public CCoreTranslationMixin {
+ public:
+ CZNCSock(int timeout = 60);
+ CZNCSock(const CString& sHost, u_short port, int timeout = 60);
+ ~CZNCSock() {}
- int ConvertAddress(const struct sockaddr_storage * pAddr, socklen_t iAddrLen, CS_STRING & sIP, u_short * piPort) const override;
+ int ConvertAddress(const struct sockaddr_storage* pAddr, socklen_t iAddrLen,
+ CString& sIP, u_short* piPort) const override;
#ifdef HAVE_LIBSSL
- int VerifyPeerCertificate(int iPreVerify, X509_STORE_CTX * pStoreCTX) override;
- void SSLHandShakeFinished() override;
+ int VerifyPeerCertificate(int iPreVerify,
+ X509_STORE_CTX* pStoreCTX) override;
+ void SSLHandShakeFinished() override;
+ bool SNIConfigureClient(CString& sHostname) override;
#endif
- void SetHostToVerifySSL(const CString& sHost) { m_HostToVerifySSL = sHost; }
- CString GetSSLPeerFingerprint() const;
- void SetSSLTrustedPeerFingerprints(const SCString& ssFPs) { m_ssTrustedFingerprints = ssFPs; }
-
-#ifndef HAVE_ICU
- // Don't fail to compile when ICU is not enabled
- void SetEncoding(const CString&) {}
-#endif
- virtual CString GetRemoteIP() const { return Csock::GetRemoteIP(); }
-
-protected:
- // All existing errno codes seem to be in range 1-300
- enum {
- errnoBadSSLCert = 12569,
- };
-
-private:
- CString m_HostToVerifySSL;
- SCString m_ssTrustedFingerprints;
- SCString m_ssCertVerificationErrors;
+ void SetHostToVerifySSL(const CString& sHost) {
+ m_sHostToVerifySSL = sHost;
+ }
+ CString GetSSLPeerFingerprint() const;
+ void SetSSLTrustedPeerFingerprints(const SCString& ssFPs) {
+ m_ssTrustedFingerprints = ssFPs;
+ }
+
+ void SetTrustAllCerts(const bool bTrustAll = false) { m_bTrustAllCerts = bTrustAll; }
+ bool GetTrustAllCerts() const { return m_bTrustAllCerts; }
+
+ void SetTrustPKI(const bool bTrustPKI = true) { m_bTrustPKI = bTrustPKI; }
+ bool GetTrustPKI() const { return m_bTrustPKI; }
+
+ void SetEncoding(const CString&);
+
+ virtual CString GetRemoteIP() const { return Csock::GetRemoteIP(); }
+
+ protected:
+ // All existing errno codes seem to be in range 1-300
+ enum {
+ errnoBadSSLCert = 12569,
+ };
+
+ private:
+ CString m_sHostToVerifySSL;
+ SCString m_ssTrustedFingerprints;
+ SCString m_ssCertVerificationErrors;
+ bool m_bTrustAllCerts;
+ bool m_bTrustPKI;
};
-enum EAddrType {
- ADDR_IPV4ONLY,
- ADDR_IPV6ONLY,
- ADDR_ALL
-};
+enum EAddrType { ADDR_IPV4ONLY, ADDR_IPV6ONLY, ADDR_ALL };
class CSockManager : public TSocketManager<CZNCSock> {
-public:
- CSockManager();
- virtual ~CSockManager();
+ public:
+ CSockManager();
+ virtual ~CSockManager();
- bool ListenHost(u_short iPort, const CString& sSockName, const CString& sBindHost, bool bSSL = false, int iMaxConns = SOMAXCONN, CZNCSock *pcSock = NULL, u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) {
- CSListener L(iPort, sBindHost);
+ bool ListenHost(u_short iPort, const CString& sSockName,
+ const CString& sBindHost, bool bSSL = false,
+ int iMaxConns = SOMAXCONN, CZNCSock* pcSock = nullptr,
+ u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) {
+ CSListener L(iPort, sBindHost);
- L.SetSockName(sSockName);
- L.SetIsSSL(bSSL);
- L.SetTimeout(iTimeout);
- L.SetMaxConns(iMaxConns);
+ L.SetSockName(sSockName);
+ L.SetIsSSL(bSSL);
+ L.SetTimeout(iTimeout);
+ L.SetMaxConns(iMaxConns);
#ifdef HAVE_IPV6
- switch (eAddr) {
- case ADDR_IPV4ONLY:
- L.SetAFRequire(CSSockAddr::RAF_INET);
- break;
- case ADDR_IPV6ONLY:
- L.SetAFRequire(CSSockAddr::RAF_INET6);
- break;
- case ADDR_ALL:
- L.SetAFRequire(CSSockAddr::RAF_ANY);
- break;
- }
+ switch (eAddr) {
+ case ADDR_IPV4ONLY:
+ L.SetAFRequire(CSSockAddr::RAF_INET);
+ break;
+ case ADDR_IPV6ONLY:
+ L.SetAFRequire(CSSockAddr::RAF_INET6);
+ break;
+ case ADDR_ALL:
+ L.SetAFRequire(CSSockAddr::RAF_ANY);
+ break;
+ }
#endif
- return Listen(L, pcSock);
- }
+ return Listen(L, pcSock);
+ }
- bool ListenAll(u_short iPort, const CString& sSockName, bool bSSL = false, int iMaxConns = SOMAXCONN, CZNCSock *pcSock = NULL, u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) {
- return ListenHost(iPort, sSockName, "", bSSL, iMaxConns, pcSock, iTimeout, eAddr);
- }
+ bool ListenAll(u_short iPort, const CString& sSockName, bool bSSL = false,
+ int iMaxConns = SOMAXCONN, CZNCSock* pcSock = nullptr,
+ u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) {
+ return ListenHost(iPort, sSockName, "", bSSL, iMaxConns, pcSock,
+ iTimeout, eAddr);
+ }
- u_short ListenRand(const CString& sSockName, const CString& sBindHost, bool bSSL = false, int iMaxConns = SOMAXCONN, CZNCSock *pcSock = NULL, u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) {
- unsigned short uPort = 0;
- CSListener L(0, sBindHost);
+ u_short ListenRand(const CString& sSockName, const CString& sBindHost,
+ bool bSSL = false, int iMaxConns = SOMAXCONN,
+ CZNCSock* pcSock = nullptr, u_int iTimeout = 0,
+ EAddrType eAddr = ADDR_ALL) {
+ unsigned short uPort = 0;
+ CSListener L(0, sBindHost);
- L.SetSockName(sSockName);
- L.SetIsSSL(bSSL);
- L.SetTimeout(iTimeout);
- L.SetMaxConns(iMaxConns);
+ L.SetSockName(sSockName);
+ L.SetIsSSL(bSSL);
+ L.SetTimeout(iTimeout);
+ L.SetMaxConns(iMaxConns);
#ifdef HAVE_IPV6
- switch (eAddr) {
- case ADDR_IPV4ONLY:
- L.SetAFRequire(CSSockAddr::RAF_INET);
- break;
- case ADDR_IPV6ONLY:
- L.SetAFRequire(CSSockAddr::RAF_INET6);
- break;
- case ADDR_ALL:
- L.SetAFRequire(CSSockAddr::RAF_ANY);
- break;
- }
+ switch (eAddr) {
+ case ADDR_IPV4ONLY:
+ L.SetAFRequire(CSSockAddr::RAF_INET);
+ break;
+ case ADDR_IPV6ONLY:
+ L.SetAFRequire(CSSockAddr::RAF_INET6);
+ break;
+ case ADDR_ALL:
+ L.SetAFRequire(CSSockAddr::RAF_ANY);
+ break;
+ }
#endif
- Listen(L, pcSock, &uPort);
+ Listen(L, pcSock, &uPort);
+
+ return uPort;
+ }
- return uPort;
- }
+ u_short ListenAllRand(const CString& sSockName, bool bSSL = false,
+ int iMaxConns = SOMAXCONN, CZNCSock* pcSock = nullptr,
+ u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) {
+ return (ListenRand(sSockName, "", bSSL, iMaxConns, pcSock, iTimeout,
+ eAddr));
+ }
- u_short ListenAllRand(const CString& sSockName, bool bSSL = false, int iMaxConns = SOMAXCONN, CZNCSock *pcSock = NULL, u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) {
- return(ListenRand(sSockName, "", bSSL, iMaxConns, pcSock, iTimeout, eAddr));
- }
+ void Connect(const CString& sHostname, u_short iPort,
+ const CString& sSockName, int iTimeout = 60, bool bSSL = false,
+ const CString& sBindHost = "", CZNCSock* pcSock = nullptr);
- void Connect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout = 60, bool bSSL = false, const CString& sBindHost = "", CZNCSock *pcSock = NULL);
+ unsigned int GetAnonConnectionCount(const CString& sIP) const;
++ void DelSockByAddr(Csock* pcSock) override;
- unsigned int GetAnonConnectionCount(const CString &sIP) const;
- void DelSockByAddr(Csock* pcSock) override;
-private:
- void FinishConnect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout, bool bSSL, const CString& sBindHost, CZNCSock *pcSock);
+ private:
+ void FinishConnect(const CString& sHostname, u_short iPort,
+ const CString& sSockName, int iTimeout, bool bSSL,
+ const CString& sBindHost, CZNCSock* pcSock);
- class CTDNSMonitorFD;
- friend class CTDNSMonitorFD;
++ std::map<Csock*, bool /* deleted */> m_InFlightDnsSockets;
++
+#ifdef HAVE_PTHREAD
+ class CThreadMonitorFD;
+ friend class CThreadMonitorFD;
+#endif
#ifdef HAVE_THREADED_DNS
- struct TDNSTask {
- CString sHostname;
- u_short iPort;
- CString sSockName;
- int iTimeout;
- bool bSSL;
- CString sBindhost;
- CZNCSock* pcSock;
-
- bool bDoneTarget;
- bool bDoneBind;
- addrinfo* aiTarget;
- addrinfo* aiBind;
- };
- class CDNSJob : public CJob {
- public:
- CString sHostname;
- TDNSTask* task;
- CSockManager* pManager;
- bool bBind;
-
- int iRes;
- addrinfo* aiResult;
-
- void runThread();
- void runMain();
- };
- void StartTDNSThread(TDNSTask* task, bool bBind);
- void SetTDNSThreadFinished(TDNSTask* task, bool bBind, addrinfo* aiResult);
- static void* TDNSThread(void* argument);
+ struct TDNSTask {
+ TDNSTask()
+ : sHostname(""),
+ iPort(0),
+ sSockName(""),
+ iTimeout(0),
+ bSSL(false),
+ sBindhost(""),
+ pcSock(nullptr),
+ bDoneTarget(false),
+ bDoneBind(false),
+ aiTarget(nullptr),
+ aiBind(nullptr) {}
+
+ TDNSTask(const TDNSTask&) = delete;
+ TDNSTask& operator=(const TDNSTask&) = delete;
+
+ CString sHostname;
+ u_short iPort;
+ CString sSockName;
+ int iTimeout;
+ bool bSSL;
+ CString sBindhost;
+ CZNCSock* pcSock;
+
+ bool bDoneTarget;
+ bool bDoneBind;
+ addrinfo* aiTarget;
+ addrinfo* aiBind;
+ };
+ class CDNSJob : public CJob {
+ public:
+ CDNSJob()
+ : sHostname(""),
+ task(nullptr),
+ pManager(nullptr),
+ bBind(false),
+ iRes(0),
+ aiResult(nullptr) {}
+
+ CDNSJob(const CDNSJob&) = delete;
+ CDNSJob& operator=(const CDNSJob&) = delete;
+
+ CString sHostname;
+ TDNSTask* task;
+ CSockManager* pManager;
+ bool bBind;
+
+ int iRes;
+ addrinfo* aiResult;
+
+ void runThread() override;
+ void runMain() override;
+ };
+ void StartTDNSThread(TDNSTask* task, bool bBind);
+ void SetTDNSThreadFinished(TDNSTask* task, bool bBind, addrinfo* aiResult);
+ static void* TDNSThread(void* argument);
#endif
-protected:
+ protected:
};
/**
#endif
}
-CSockManager::~CSockManager() {
-}
-
-// It's here to not break ABI of 1.6; in 1.7 this should be a data member of CSockManager.
-static std::map<Csock*, bool /* deleted */> g_InFlightDnsSockets;
+CSockManager::~CSockManager() {}
-void CSockManager::Connect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout, bool bSSL, const CString& sBindHost, CZNCSock *pcSock) {
- g_InFlightDnsSockets[pcSock] = false;
- if (pcSock) {
- pcSock->SetHostToVerifySSL(sHostname);
- }
+void CSockManager::Connect(const CString& sHostname, u_short iPort,
+ const CString& sSockName, int iTimeout, bool bSSL,
+ const CString& sBindHost, CZNCSock* pcSock) {
++ m_InFlightDnsSockets[pcSock] = false;
+ if (pcSock) {
+ pcSock->SetHostToVerifySSL(sHostname);
+ }
#ifdef HAVE_THREADED_DNS
- DEBUG("TDNS: initiating resolving of [" << sHostname << "] and bindhost [" << sBindHost << "] for [" << sSockName << "]");
- TDNSTask* task = new TDNSTask;
- task->sHostname = sHostname;
- task->iPort = iPort;
- task->sSockName = sSockName;
- task->iTimeout = iTimeout;
- task->bSSL = bSSL;
- task->sBindhost = sBindHost;
- task->pcSock = pcSock;
- task->aiTarget = NULL;
- task->aiBind = NULL;
- task->bDoneTarget = false;
- if (sBindHost.empty()) {
- task->bDoneBind = true;
- } else {
- task->bDoneBind = false;
- StartTDNSThread(task, true);
- }
- StartTDNSThread(task, false);
+ DEBUG("TDNS: initiating resolving of [" << sHostname << "] and bindhost ["
+ << sBindHost << "]");
+ TDNSTask* task = new TDNSTask;
+ task->sHostname = sHostname;
+ task->iPort = iPort;
+ task->sSockName = sSockName;
+ task->iTimeout = iTimeout;
+ task->bSSL = bSSL;
+ task->sBindhost = sBindHost;
+ task->pcSock = pcSock;
+ if (sBindHost.empty()) {
+ task->bDoneBind = true;
+ } else {
+ StartTDNSThread(task, true);
+ }
+ StartTDNSThread(task, false);
#else /* HAVE_THREADED_DNS */
- // Just let Csocket handle DNS itself
- FinishConnect(sHostname, iPort, sSockName, iTimeout, bSSL, sBindHost, pcSock);
+ // Just let Csocket handle DNS itself
+ FinishConnect(sHostname, iPort, sSockName, iTimeout, bSSL, sBindHost,
+ pcSock);
#endif
}
-void CSockManager::FinishConnect(const CString& sHostname, u_short iPort, const CString& sSockName, int iTimeout, bool bSSL, const CString& sBindHost, CZNCSock *pcSock) {
- auto it = g_InFlightDnsSockets.find(pcSock);
- if (it != g_InFlightDnsSockets.end()) {
- bool bSocketDeletedAlready = it->second;
- g_InFlightDnsSockets.erase(it);
- if (bSocketDeletedAlready) {
- DEBUG("TDNS: Socket [" << sSockName << "] is deleted already, not proceeding with connection");
- return;
- }
- } else {
- // impossible
- }
-
- CSConnection C(sHostname, iPort, iTimeout);
-
- C.SetSockName(sSockName);
- C.SetIsSSL(bSSL);
- C.SetBindHost(sBindHost);
+void CSockManager::FinishConnect(const CString& sHostname, u_short iPort,
+ const CString& sSockName, int iTimeout,
+ bool bSSL, const CString& sBindHost,
+ CZNCSock* pcSock) {
++ auto it = m_InFlightDnsSockets.find(pcSock);
++ if (it != m_InFlightDnsSockets.end()) {
++ bool bSocketDeletedAlready = it->second;
++ m_InFlightDnsSockets.erase(it);
++ if (bSocketDeletedAlready) {
++ DEBUG("TDNS: Socket ["
++ << sSockName
++ << "] is deleted already, not proceeding with connection");
++ return;
++ }
++ } else {
++ // impossible
++ }
++
+ CSConnection C(sHostname, iPort, iTimeout);
+
+ C.SetSockName(sSockName);
+ C.SetIsSSL(bSSL);
+ C.SetBindHost(sBindHost);
#ifdef HAVE_LIBSSL
- CString sCipher = CZNC::Get().GetSSLCiphers();
- if (sCipher.empty()) {
- sCipher = ZNC_DefaultCipher();
- }
- C.SetCipher(sCipher);
+ CString sCipher = CZNC::Get().GetSSLCiphers();
+ if (sCipher.empty()) {
+ sCipher = ZNC_DefaultCipher();
+ }
+ C.SetCipher(sCipher);
#endif
- TSocketManager<CZNCSock>::Connect(C, pcSock);
+ TSocketManager<CZNCSock>::Connect(C, pcSock);
}
- auto it = g_InFlightDnsSockets.find(pcSock);
- if (it != g_InFlightDnsSockets.end()) {
- // Then socket is resolving its DNS. When that finishes, let it silently die without crash.
- it->second = true;
- }
- TSocketManager<CZNCSock>::DelSockByAddr(pcSock);
+ void CSockManager::DelSockByAddr(Csock* pcSock) {
-
++ auto it = m_InFlightDnsSockets.find(pcSock);
++ if (it != m_InFlightDnsSockets.end()) {
++ // The socket is resolving its DNS. When that finishes, let it silently
++ // die without crash.
++ it->second = true;
++ }
++ TSocketManager<CZNCSock>::DelSockByAddr(pcSock);
+ }
+
/////////////////// CSocket ///////////////////
-CSocket::CSocket(CModule* pModule) : CZNCSock() {
- m_pModule = pModule;
- if (m_pModule) m_pModule->AddSocket(this);
- EnableReadLine();
- SetMaxBufferThreshold(10240);
+CSocket::CSocket(CModule* pModule) : CZNCSock(), m_pModule(pModule) {
+ if (m_pModule) m_pModule->AddSocket(this);
+ EnableReadLine();
+ SetMaxBufferThreshold(10240);
}
-CSocket::CSocket(CModule* pModule, const CString& sHostname, unsigned short uPort, int iTimeout) : CZNCSock(sHostname, uPort, iTimeout) {
- m_pModule = pModule;
- if (m_pModule) m_pModule->AddSocket(this);
- EnableReadLine();
- SetMaxBufferThreshold(10240);
+CSocket::CSocket(CModule* pModule, const CString& sHostname,
+ unsigned short uPort, int iTimeout)
+ : CZNCSock(sHostname, uPort, iTimeout), m_pModule(pModule) {
+ if (m_pModule) m_pModule->AddSocket(this);
+ EnableReadLine();
+ SetMaxBufferThreshold(10240);
}
CSocket::~CSocket() {