]> jfr.im git - irc/evilnet/znc.git/commitdiff
Merge branch '1.6.x'
authorAlexey Sokolov <redacted>
Sun, 20 Nov 2016 18:01:59 +0000 (18:01 +0000)
committerAlexey Sokolov <redacted>
Sun, 20 Nov 2016 18:09:55 +0000 (18:09 +0000)
1  2 
include/znc/Socket.h
src/Socket.cpp

index 34bedf87b36618ab9d06912b15a6d9e5ad6bc810,51abf162733de6a03ed6c40492b1955cddb5930b..e0e0ab7a09458c0529e2cb595214d7be66ff8c6f
  
  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:
  };
  
  /**
diff --cc src/Socket.cpp
index dcf53b98b67c44107aa7b6f914f346b885aa6442,7c7fba5002876937b6698667b25ae0275c7c93c1..3a18f785ddb11909d53bcca95a03500c3e66c0ed
@@@ -387,71 -346,95 +387,96 @@@ CSockManager::CSockManager() 
  #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() {