1 /* 2 * Copyright (C) 2004-2020 ZNC, see the NOTICE file for details. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ZNC_SOCKET_H 18 #define ZNC_SOCKET_H 19 20 #include <znc/zncconfig.h> 21 #include <znc/Csocket.h> 22 #include <znc/Threads.h> 23 #include <znc/Translation.h> 24 25 class CModule; 26 27 class CZNCSock : public Csock, protected CCoreTranslationMixin { 28 public: 29 CZNCSock(int timeout = 60); 30 CZNCSock(const CString& sHost, u_short port, int timeout = 60); ~CZNCSock()31 ~CZNCSock() {} 32 33 int ConvertAddress(const struct sockaddr_storage* pAddr, socklen_t iAddrLen, 34 CString& sIP, u_short* piPort) const override; 35 #ifdef HAVE_LIBSSL 36 int VerifyPeerCertificate(int iPreVerify, 37 X509_STORE_CTX* pStoreCTX) override; 38 void SSLHandShakeFinished() override; 39 bool CheckSSLCert(X509* pCert); SSLCertError(X509 * pCert)40 virtual void SSLCertError(X509* pCert) {} 41 bool SNIConfigureClient(CString& sHostname) override; 42 CString GetSSLPeerFingerprint(X509* pCert = nullptr) const; 43 #else GetSSLPeerFingerprint()44 CString GetSSLPeerFingerprint() const { return ""; } 45 #endif SetHostToVerifySSL(const CString & sHost)46 void SetHostToVerifySSL(const CString& sHost) { 47 m_sHostToVerifySSL = sHost; 48 } SetSSLTrustedPeerFingerprints(const SCString & ssFPs)49 void SetSSLTrustedPeerFingerprints(const SCString& ssFPs) { 50 m_ssTrustedFingerprints = ssFPs; 51 } 52 SetTrustAllCerts(bool bTrustAll)53 void SetTrustAllCerts(bool bTrustAll) { m_bTrustAllCerts = bTrustAll; } GetTrustAllCerts()54 bool GetTrustAllCerts() const { return m_bTrustAllCerts; } 55 SetTrustPKI(bool bTrustPKI)56 void SetTrustPKI(bool bTrustPKI) { m_bTrustPKI = bTrustPKI; } GetTrustPKI()57 bool GetTrustPKI() const { return m_bTrustPKI; } 58 59 void SetEncoding(const CString&); 60 GetRemoteIP()61 virtual CString GetRemoteIP() const { return Csock::GetRemoteIP(); } 62 63 protected: 64 // All existing errno codes seem to be in range 1-300 65 enum { 66 errnoBadSSLCert = 12569, 67 }; 68 69 private: 70 CString m_sHostToVerifySSL; 71 SCString m_ssTrustedFingerprints; 72 SCString m_ssCertVerificationErrors; 73 bool m_bTrustAllCerts = false; 74 bool m_bTrustPKI = true; 75 }; 76 77 enum EAddrType { ADDR_IPV4ONLY, ADDR_IPV6ONLY, ADDR_ALL }; 78 79 class CSockManager : public TSocketManager<CZNCSock>, 80 private CCoreTranslationMixin { 81 public: 82 CSockManager(); 83 virtual ~CSockManager(); 84 85 bool ListenHost(u_short iPort, const CString& sSockName, 86 const CString& sBindHost, bool bSSL = false, 87 int iMaxConns = SOMAXCONN, CZNCSock* pcSock = nullptr, 88 u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) { 89 CSListener L(iPort, sBindHost); 90 91 L.SetSockName(sSockName); 92 L.SetIsSSL(bSSL); 93 L.SetTimeout(iTimeout); 94 L.SetMaxConns(iMaxConns); 95 96 #ifdef HAVE_IPV6 97 switch (eAddr) { 98 case ADDR_IPV4ONLY: 99 L.SetAFRequire(CSSockAddr::RAF_INET); 100 break; 101 case ADDR_IPV6ONLY: 102 L.SetAFRequire(CSSockAddr::RAF_INET6); 103 break; 104 case ADDR_ALL: 105 L.SetAFRequire(CSSockAddr::RAF_ANY); 106 break; 107 } 108 #endif 109 110 return Listen(L, pcSock); 111 } 112 113 bool ListenAll(u_short iPort, const CString& sSockName, bool bSSL = false, 114 int iMaxConns = SOMAXCONN, CZNCSock* pcSock = nullptr, 115 u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) { 116 return ListenHost(iPort, sSockName, "", bSSL, iMaxConns, pcSock, 117 iTimeout, eAddr); 118 } 119 120 u_short ListenRand(const CString& sSockName, const CString& sBindHost, 121 bool bSSL = false, int iMaxConns = SOMAXCONN, 122 CZNCSock* pcSock = nullptr, u_int iTimeout = 0, 123 EAddrType eAddr = ADDR_ALL) { 124 unsigned short uPort = 0; 125 CSListener L(0, sBindHost); 126 127 L.SetSockName(sSockName); 128 L.SetIsSSL(bSSL); 129 L.SetTimeout(iTimeout); 130 L.SetMaxConns(iMaxConns); 131 132 #ifdef HAVE_IPV6 133 switch (eAddr) { 134 case ADDR_IPV4ONLY: 135 L.SetAFRequire(CSSockAddr::RAF_INET); 136 break; 137 case ADDR_IPV6ONLY: 138 L.SetAFRequire(CSSockAddr::RAF_INET6); 139 break; 140 case ADDR_ALL: 141 L.SetAFRequire(CSSockAddr::RAF_ANY); 142 break; 143 } 144 #endif 145 146 Listen(L, pcSock, &uPort); 147 148 return uPort; 149 } 150 151 u_short ListenAllRand(const CString& sSockName, bool bSSL = false, 152 int iMaxConns = SOMAXCONN, CZNCSock* pcSock = nullptr, 153 u_int iTimeout = 0, EAddrType eAddr = ADDR_ALL) { 154 return (ListenRand(sSockName, "", bSSL, iMaxConns, pcSock, iTimeout, 155 eAddr)); 156 } 157 158 void Connect(const CString& sHostname, u_short iPort, 159 const CString& sSockName, int iTimeout = 60, bool bSSL = false, 160 const CString& sBindHost = "", CZNCSock* pcSock = nullptr); 161 162 unsigned int GetAnonConnectionCount(const CString& sIP) const; 163 void DelSockByAddr(Csock* pcSock) override; 164 165 private: 166 void FinishConnect(const CString& sHostname, u_short iPort, 167 const CString& sSockName, int iTimeout, bool bSSL, 168 const CString& sBindHost, CZNCSock* pcSock); 169 170 std::map<Csock*, bool /* deleted */> m_InFlightDnsSockets; 171 172 #ifdef HAVE_PTHREAD 173 class CThreadMonitorFD; 174 friend class CThreadMonitorFD; 175 #endif 176 #ifdef HAVE_THREADED_DNS 177 struct TDNSTask { TDNSTaskTDNSTask178 TDNSTask() 179 : sHostname(""), 180 iPort(0), 181 sSockName(""), 182 iTimeout(0), 183 bSSL(false), 184 sBindhost(""), 185 pcSock(nullptr), 186 bDoneTarget(false), 187 bDoneBind(false), 188 aiTarget(nullptr), 189 aiBind(nullptr) {} 190 191 TDNSTask(const TDNSTask&) = delete; 192 TDNSTask& operator=(const TDNSTask&) = delete; 193 194 CString sHostname; 195 u_short iPort; 196 CString sSockName; 197 int iTimeout; 198 bool bSSL; 199 CString sBindhost; 200 CZNCSock* pcSock; 201 202 bool bDoneTarget; 203 bool bDoneBind; 204 addrinfo* aiTarget; 205 addrinfo* aiBind; 206 }; 207 class CDNSJob : public CJob { 208 public: CDNSJob()209 CDNSJob() 210 : sHostname(""), 211 task(nullptr), 212 pManager(nullptr), 213 bBind(false), 214 iRes(0), 215 aiResult(nullptr) {} 216 217 CDNSJob(const CDNSJob&) = delete; 218 CDNSJob& operator=(const CDNSJob&) = delete; 219 220 CString sHostname; 221 TDNSTask* task; 222 CSockManager* pManager; 223 bool bBind; 224 225 int iRes; 226 addrinfo* aiResult; 227 228 void runThread() override; 229 void runMain() override; 230 }; 231 void StartTDNSThread(TDNSTask* task, bool bBind); 232 void SetTDNSThreadFinished(TDNSTask* task, bool bBind, addrinfo* aiResult); 233 static void* TDNSThread(void* argument); 234 #endif 235 protected: 236 }; 237 238 /** 239 * @class CSocket 240 * @brief Base Csock implementation to be used by modules 241 * 242 * By all means, this class should be used as a base for sockets originating from modules. It handles removing instances of itself 243 * from the module as it unloads, and simplifies use in general. 244 * - EnableReadLine is default to true in this class 245 * - MaxBuffer for readline is set to 10240, in the event this is reached the socket is closed (@see ReachedMaxBuffer) 246 */ 247 class CSocket : public CZNCSock { 248 public: 249 /** 250 * @brief ctor 251 * @param pModule the module this sock instance is associated to 252 */ 253 CSocket(CModule* pModule); 254 /** 255 * @brief ctor 256 * @param pModule the module this sock instance is associated to 257 * @param sHostname the hostname being connected to 258 * @param uPort the port being connected to 259 * @param iTimeout the timeout period for this specific sock 260 */ 261 CSocket(CModule* pModule, const CString& sHostname, unsigned short uPort, 262 int iTimeout = 60); 263 virtual ~CSocket(); 264 265 CSocket(const CSocket&) = delete; 266 CSocket& operator=(const CSocket&) = delete; 267 268 using Csock::Connect; 269 using Csock::Listen; 270 271 //! This defaults to closing the socket, feel free to override 272 void ReachedMaxBuffer() override; 273 void SockError(int iErrno, const CString& sDescription) override; 274 275 //! This limits the global connections from this IP to defeat DoS attacks, feel free to override. The ACL used is provided by the main interface @see CZNC::AllowConnectionFrom 276 bool ConnectionFrom(const CString& sHost, unsigned short uPort) override; 277 278 //! Ease of use Connect, assigns to the manager and is subsequently tracked 279 bool Connect(const CString& sHostname, unsigned short uPort, 280 bool bSSL = false, unsigned int uTimeout = 60); 281 //! Ease of use Listen, assigned to the manager and is subsequently tracked 282 bool Listen(unsigned short uPort, bool bSSL, unsigned int uTimeout = 0); 283 284 // Getters 285 CModule* GetModule() const; 286 // !Getters 287 288 #ifndef SWIG 289 // Translation. As opposed to CCoreTranslationMixin, this one uses module.mo 290 CString t_s(const CString& sEnglish, const CString& sContext = "") const; 291 CInlineFormatMessage t_f(const CString& sEnglish, 292 const CString& sContext = "") const; 293 CInlineFormatMessage t_p(const CString& sEnglish, const CString& sEnglishes, 294 int iNum, const CString& sContext) const; 295 CDelayedTranslation t_d(const CString& sEnglish, 296 const CString& sContext = "") const; 297 #endif 298 299 private: 300 protected: 301 CModule* 302 m_pModule; //!< pointer to the module that this sock instance belongs to 303 }; 304 305 /** 306 * @class CIRCSocket 307 * @brief Base IRC socket for client<->ZNC, and ZNC<->server 308 */ 309 class CIRCSocket : public CZNCSock { 310 public: 311 #ifdef HAVE_ICU 312 /** 313 * @brief Allow IRC control characters to appear even if protocol encoding explicitly disallows them. 314 * 315 * E.g. ISO-2022-JP disallows 0x0F, which in IRC means "reset format", 316 * so by default it gets replaced with U+FFFD ("replacement character"). 317 * https://code.google.com/p/chromium/issues/detail?id=277062#c3 318 * 319 * In case if protocol encoding uses these code points for something else, the encoding takes preference, 320 * and they are not IRC control characters anymore. 321 */ 322 void IcuExtToUCallback(UConverterToUnicodeArgs* toArgs, 323 const char* codeUnits, int32_t length, 324 UConverterCallbackReason reason, 325 UErrorCode* err) override; 326 void IcuExtFromUCallback(UConverterFromUnicodeArgs* fromArgs, 327 const UChar* codeUnits, int32_t length, 328 UChar32 codePoint, UConverterCallbackReason reason, 329 UErrorCode* err) override; 330 #endif 331 }; 332 333 #endif /* ZNC_SOCKET_H */ 334