diff --git a/include/znc/Listener.h b/include/znc/Listener.h index c16ef1c1..002a3098 100644 --- a/include/znc/Listener.h +++ b/include/znc/Listener.h @@ -92,6 +92,28 @@ class CTCPListener : public CListener { CString m_sBindHost; }; +class CUnixListener : public CListener { + public: + CUnixListener(const CString& sPath, const CString& sURIPrefix, bool bSSL, + EAcceptType eAccept) + : CListener(sURIPrefix, bSSL, eAccept), + m_sPath(sPath) {} + ~CUnixListener(); + + CUnixListener(const CUnixListener&) = delete; + CUnixListener& operator=(const CUnixListener&) = delete; + + // Getters + const CString& GetPath() const { return m_sPath; } + // !Getters + + bool Listen() override; + CConfig ToConfig() const override; + + protected: + CString m_sPath; +}; + class CRealListener : public CZNCSock { public: CRealListener(CListener& listener) : CZNCSock(), m_Listener(listener) {} diff --git a/include/znc/znc.h b/include/znc/znc.h index 80720d3d..d81aa392 100644 --- a/include/znc/znc.h +++ b/include/znc/znc.h @@ -204,6 +204,8 @@ class CZNC { bool AddListener(unsigned short uPort, const CString& sBindHost, const CString& sURIPrefix, bool bSSL, EAddrType eAddr, CListener::EAcceptType eAccept, CString& sError); + bool AddListener(const CString& sPath, const CString& sURIPrefix, bool bSSL, + CListener::EAcceptType eAccept, CString& sError); bool DelListener(CListener*); // Message of the Day diff --git a/src/Listener.cpp b/src/Listener.cpp index 40b8e388..d5513982 100644 --- a/src/Listener.cpp +++ b/src/Listener.cpp @@ -83,6 +83,35 @@ CConfig CTCPListener::ToConfig() const { return listenerConfig; } +CUnixListener::~CUnixListener() { +} + +bool CUnixListener::Listen() { + CString sName = "unix:" + m_sPath; + + m_pListener = new CRealListener(*this); + +#ifdef HAVE_LIBSSL + if (IsSSL()) { + m_pListener->SetSSL(true); + m_pListener->SetPemLocation(CZNC::Get().GetPemLocation()); + m_pListener->SetKeyLocation(CZNC::Get().GetKeyLocation()); + m_pListener->SetDHParamLocation(CZNC::Get().GetDHParamLocation()); + } +#endif + + CZNC::Get().GetManager().AddSock(m_pListener, sName); + return m_pListener->ListenUnix(m_sPath); +} + +CConfig CUnixListener::ToConfig() const { + CConfig listenerConfig = CListener::ToConfig(); + + listenerConfig.AddKeyValuePair("Path", GetPath()); + + return listenerConfig; +} + void CListener::ResetRealListener() { m_pListener = nullptr; } CRealListener::~CRealListener() { m_Listener.ResetRealListener(); } diff --git a/src/znc.cpp b/src/znc.cpp index 1f6de301..9db0fef4 100644 --- a/src/znc.cpp +++ b/src/znc.cpp @@ -1717,9 +1717,70 @@ bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost, return true; } +bool CZNC::AddListener(const CString& sPath, const CString& sURIPrefixRaw, + bool bSSL, CListener::EAcceptType eAccept, + CString& sError) { + CUtils::PrintAction("Binding to path [" + sPath + "]"); + +#ifndef HAVE_LIBSSL + if (bSSL) { + sError = "SSL is not enabled"; + CUtils::PrintStatus(false, sError); + return false; + } +#else + CString sPemFile = GetPemLocation(); + + if (bSSL && !CFile::Exists(sPemFile)) { + sError = "Unable to locate pem file: [" + sPemFile + "]"; + CUtils::PrintStatus(false, sError); + + // If stdin is e.g. /dev/null and we call GetBoolInput(), + // we are stuck in an endless loop! + if (isatty(0) && + CUtils::GetBoolInput("Would you like to create a new pem file?", + true)) { + sError.clear(); + WritePemFile(); + } else { + return false; + } + + CUtils::PrintAction("Binding to path [" + sPath + "]"); + } +#endif + + // URIPrefix must start with a slash and end without one. + CString sURIPrefix = CString(sURIPrefixRaw); + if (!sURIPrefix.empty()) { + if (!sURIPrefix.StartsWith("/")) { + sURIPrefix = "/" + sURIPrefix; + } + if (sURIPrefix.EndsWith("/")) { + sURIPrefix.TrimRight("/"); + } + } + + CListener* pListener = + new CUnixListener(sPath, sURIPrefix, bSSL, eAccept); + + if (!pListener->Listen()) { + sError = FormatBindError(); + CUtils::PrintStatus(false, sError); + delete pListener; + return false; + } + + m_vpListeners.push_back(pListener); + CUtils::PrintStatus(true); + + return true; +} + bool CZNC::AddListener(CConfig* pConfig, CString& sError) { CString sBindHost; CString sURIPrefix; + CString sPath; bool bSSL; bool b4; #ifdef HAVE_IPV6 @@ -1730,32 +1791,22 @@ bool CZNC::AddListener(CConfig* pConfig, CString& sError) { bool bIRC; bool bWeb; unsigned short uPort; + bool bTcpListener = true; + if (!pConfig->FindUShortEntry("port", uPort)) { - sError = "No port given"; - CUtils::PrintError(sError); - return false; + bTcpListener = false; + if (!pConfig->FindStringEntry("path", sPath)) { + sError = "No port and no path given"; + CUtils::PrintError(sError); + return false; + } } - pConfig->FindStringEntry("host", sBindHost); + pConfig->FindBoolEntry("ssl", bSSL, false); - pConfig->FindBoolEntry("ipv4", b4, true); - pConfig->FindBoolEntry("ipv6", b6, b6); pConfig->FindBoolEntry("allowirc", bIRC, true); pConfig->FindBoolEntry("allowweb", bWeb, true); pConfig->FindStringEntry("uriprefix", sURIPrefix); - EAddrType eAddr; - if (b4 && b6) { - eAddr = ADDR_ALL; - } else if (b4 && !b6) { - eAddr = ADDR_IPV4ONLY; - } else if (!b4 && b6) { - eAddr = ADDR_IPV6ONLY; - } else { - sError = "No address family given"; - CUtils::PrintError(sError); - return false; - } - CListener::EAcceptType eAccept; if (bIRC && bWeb) { eAccept = CListener::ACCEPT_ALL; @@ -1769,8 +1820,28 @@ bool CZNC::AddListener(CConfig* pConfig, CString& sError) { return false; } - return AddListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept, - sError); + if (bTcpListener) { + pConfig->FindStringEntry("host", sBindHost); + pConfig->FindBoolEntry("ipv4", b4, true); + pConfig->FindBoolEntry("ipv6", b6, b6); + + EAddrType eAddr; + if (b4 && b6) { + eAddr = ADDR_ALL; + } else if (b4 && !b6) { + eAddr = ADDR_IPV4ONLY; + } else if (!b4 && b6) { + eAddr = ADDR_IPV6ONLY; + } else { + sError = "No address family given"; + CUtils::PrintError(sError); + return false; + } + + return AddListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept, + sError); + } + return AddListener(sPath, sURIPrefix, bSSL, eAccept, sError); } bool CZNC::AddListener(CListener* pListener) {