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