mirror of
https://github.com/znc/znc.git
synced 2026-08-12 03:42:48 +02:00
+72
-35
@@ -1641,29 +1641,39 @@ void CClient::UserPortCommand(CString& sLine) {
|
||||
const CString sCommand = sLine.Token(0);
|
||||
|
||||
if (sCommand.Equals("LISTPORTS")) {
|
||||
CTable Table;
|
||||
Table.AddColumn(t_s("Port", "listports"));
|
||||
Table.AddColumn(t_s("BindHost", "listports"));
|
||||
Table.AddColumn(t_s("SSL", "listports"));
|
||||
Table.AddColumn(t_s("Protocol", "listports"));
|
||||
Table.AddColumn(t_s("IRC", "listports"));
|
||||
Table.AddColumn(t_s("Web", "listports"));
|
||||
CTable TableT;
|
||||
TableT.AddColumn(t_s("Port", "listports"));
|
||||
TableT.AddColumn(t_s("BindHost", "listports"));
|
||||
TableT.AddColumn(t_s("Protocol", "listports"));
|
||||
TableT.AddColumn(t_s("SSL", "listports"));
|
||||
TableT.AddColumn(t_s("IRC", "listports"));
|
||||
TableT.AddColumn(t_s("Web", "listports"));
|
||||
|
||||
CTable TableU;
|
||||
TableU.AddColumn(t_s("Path", "listports"));
|
||||
TableU.AddColumn(t_s("Mode", "listports"));
|
||||
TableU.AddColumn(t_s("Group", "listports"));
|
||||
TableU.AddColumn(t_s("SSL", "listports"));
|
||||
TableU.AddColumn(t_s("IRC", "listports"));
|
||||
TableU.AddColumn(t_s("Web", "listports"));
|
||||
|
||||
const vector<CListener*>& vpListeners = CZNC::Get().GetListeners();
|
||||
|
||||
for (const CListener* pListener : vpListeners) {
|
||||
Table.AddRow();
|
||||
CTable* pTable;
|
||||
if (const CTCPListener* pTCPListener =
|
||||
dynamic_cast<const CTCPListener*>(pListener)) {
|
||||
Table.SetCell(t_s("Port", "listports"),
|
||||
CString(pTCPListener->GetPort()));
|
||||
Table.SetCell(t_s("BindHost", "listports"),
|
||||
(pTCPListener->GetBindHost().empty()
|
||||
? CString("*")
|
||||
: pTCPListener->GetBindHost()));
|
||||
TableT.AddRow();
|
||||
pTable = &TableT;
|
||||
TableT.SetCell(t_s("Port", "listports"),
|
||||
CString(pTCPListener->GetPort()));
|
||||
TableT.SetCell(t_s("BindHost", "listports"),
|
||||
(pTCPListener->GetBindHost().empty()
|
||||
? CString("*")
|
||||
: pTCPListener->GetBindHost()));
|
||||
|
||||
EAddrType eAddr = pTCPListener->GetAddrType();
|
||||
Table.SetCell(
|
||||
TableT.SetCell(
|
||||
t_s("Protocol", "listports"),
|
||||
eAddr == ADDR_ALL
|
||||
? t_s("IPv4 and IPv6", "listports")
|
||||
@@ -1671,28 +1681,37 @@ void CClient::UserPortCommand(CString& sLine) {
|
||||
: t_s("IPv6", "listports")));
|
||||
} else if (const CUnixListener* pUnixListener =
|
||||
dynamic_cast<const CUnixListener*>(pListener)) {
|
||||
Table.SetCell(t_s("Port", "listports"),
|
||||
pUnixListener->GetPath());
|
||||
TableU.AddRow();
|
||||
pTable = &TableU;
|
||||
TableU.SetCell(t_s("Path", "listports"),
|
||||
pUnixListener->GetPath());
|
||||
TableU.SetCell(t_s("Mode", "listports"),
|
||||
pUnixListener->GetMode());
|
||||
TableU.SetCell(t_s("Group", "listports"),
|
||||
pUnixListener->GetGroup());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
Table.SetCell(t_s("SSL", "listports"),
|
||||
pListener->IsSSL() ? t_s("yes", "listports|ssl")
|
||||
: t_s("no", "listports|ssl"));
|
||||
pTable->SetCell(t_s("SSL", "listports"),
|
||||
pListener->IsSSL() ? t_s("yes", "listports|ssl")
|
||||
: t_s("no", "listports|ssl"));
|
||||
|
||||
CListener::EAcceptType eAccept = pListener->GetAcceptType();
|
||||
Table.SetCell(t_s("IRC", "listports"),
|
||||
eAccept == CListener::ACCEPT_ALL ||
|
||||
eAccept == CListener::ACCEPT_IRC
|
||||
? t_s("yes", "listports|irc")
|
||||
: t_s("no", "listports|irc"));
|
||||
Table.SetCell(t_s("Web", "listports"),
|
||||
eAccept == CListener::ACCEPT_ALL ||
|
||||
eAccept == CListener::ACCEPT_HTTP
|
||||
? t_f("yes, on {1}", "listports|irc")(
|
||||
pListener->GetURIPrefix() + "/")
|
||||
: t_s("no", "listports|web"));
|
||||
pTable->SetCell(t_s("IRC", "listports"),
|
||||
eAccept == CListener::ACCEPT_ALL ||
|
||||
eAccept == CListener::ACCEPT_IRC
|
||||
? t_s("yes", "listports|irc")
|
||||
: t_s("no", "listports|irc"));
|
||||
pTable->SetCell(t_s("Web", "listports"),
|
||||
eAccept == CListener::ACCEPT_ALL ||
|
||||
eAccept == CListener::ACCEPT_HTTP
|
||||
? t_f("yes, on {1}", "listports|irc")(
|
||||
pListener->GetURIPrefix() + "/")
|
||||
: t_s("no", "listports|web"));
|
||||
}
|
||||
|
||||
PutStatus(Table);
|
||||
PutStatus(TableT);
|
||||
PutStatus(TableU);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1732,12 +1751,30 @@ void CClient::UserPortCommand(CString& sLine) {
|
||||
|
||||
std::unique_ptr<CListener> pListener;
|
||||
if (sPort.TrimPrefix("unix:")) {
|
||||
bool bSSL = sPort.TrimPrefix("ssl:");
|
||||
bool bSSL = false;
|
||||
CString sMode;
|
||||
CString sGroup;
|
||||
if (auto colon = sPort.find_first_of(':'); colon != std::string::npos) {
|
||||
VCString vsOpts;
|
||||
CString(sPort.substr(0, colon)).Split(",", vsOpts, false);
|
||||
for (CString& sOpt : vsOpts) {
|
||||
if (sOpt == "ssl") {
|
||||
bSSL = true;
|
||||
} else if (sOpt.TrimPrefix("mode=")) {
|
||||
sMode = sOpt;
|
||||
} else if (sOpt.TrimPrefix("group=")) {
|
||||
sGroup = sOpt;
|
||||
} else {
|
||||
throw PortCommandUsage{};
|
||||
}
|
||||
}
|
||||
sPort = sPort.substr(colon + 1);
|
||||
}
|
||||
const CString& sPath = sPort;
|
||||
CListener::EAcceptType eAccept = ParseEAccept(sLine.Token(2));
|
||||
CString sURIPrefix = sLine.Token(3);
|
||||
|
||||
pListener.reset(new CUnixListener(sPath, sURIPrefix, bSSL, eAccept));
|
||||
pListener.reset(new CUnixListener(sPath, sURIPrefix, bSSL, eAccept, sGroup, sMode));
|
||||
} else {
|
||||
bool bSSL = sPort.StartsWith("+");
|
||||
EAddrType eAddr = ParseEAddr(sLine.Token(2));
|
||||
@@ -1765,7 +1802,7 @@ void CClient::UserPortCommand(CString& sLine) {
|
||||
"[bindhost [uriprefix]]"));
|
||||
PutStatus(t_s("+ means SSL"));
|
||||
PutStatus(
|
||||
t_s("Or: AddPort unix:[ssl:]/path/to/socket <web|irc|all> "
|
||||
t_s("Or: AddPort unix:[ssl,mode=NNN,group=foo]:/path/to/socket <web|irc|all> "
|
||||
"[uriprefix]"));
|
||||
}
|
||||
} else if (sCommand.Equals("DELPORT")) {
|
||||
|
||||
+88
-3
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <grp.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <znc/Listener.h>
|
||||
#include <znc/Config.h>
|
||||
#include <znc/znc.h>
|
||||
@@ -85,9 +91,21 @@ CConfig CTCPListener::ToConfig() const {
|
||||
return listenerConfig;
|
||||
}
|
||||
|
||||
CUnixListener::~CUnixListener() {
|
||||
CUnixListener::CUnixListener(const CString& sPath, const CString& sURIPrefix,
|
||||
bool bSSL, EAcceptType eAccept,
|
||||
const CString& sGid, const CString& sMode)
|
||||
: CListener(sURIPrefix, bSSL, eAccept),
|
||||
m_sPath(sPath),
|
||||
m_sGid(sGid),
|
||||
m_iMode(-1) {
|
||||
if (!sMode.empty()) {
|
||||
std::istringstream s(sMode);
|
||||
s >> std::oct >> m_iMode;
|
||||
}
|
||||
}
|
||||
|
||||
CUnixListener::~CUnixListener() {}
|
||||
|
||||
bool CUnixListener::Listen() {
|
||||
if (m_pListener) {
|
||||
errno = EINVAL;
|
||||
@@ -97,18 +115,85 @@ bool CUnixListener::Listen() {
|
||||
m_pListener = new CRealListener(*this);
|
||||
SetupSSL();
|
||||
|
||||
return CZNC::Get().GetManager().ListenUnix("UNIX_LISTENER", m_sPath,
|
||||
m_pListener);
|
||||
if (!CZNC::Get().GetManager().ListenUnix("UNIX_LISTENER", m_sPath,
|
||||
m_pListener))
|
||||
return false;
|
||||
|
||||
if (!m_sGid.empty()) {
|
||||
bool bSuccess = [&]() -> bool {
|
||||
std::vector<char> buffer(100);
|
||||
group gr{};
|
||||
group* result;
|
||||
retrysize:
|
||||
int err = getgrnam_r(m_sGid.c_str(), &gr, buffer.data(),
|
||||
buffer.size(), &result);
|
||||
switch (err) {
|
||||
case ERANGE: {
|
||||
if (buffer.size() > 10000) {
|
||||
DEBUG("Can't get gid due to memory size");
|
||||
return false;
|
||||
}
|
||||
buffer.resize(buffer.size() + 100);
|
||||
goto retrysize;
|
||||
}
|
||||
case 0: {
|
||||
if (!result) {
|
||||
DEBUG("Group not found");
|
||||
return false;
|
||||
}
|
||||
if (chown(m_sPath.c_str(), -1, result->gr_gid)) {
|
||||
char* e = strerror(errno);
|
||||
DEBUG("Can't chmod: " << e);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
char* e = strerror(err);
|
||||
DEBUG("Error while getting gid " << e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
if (!bSuccess) {
|
||||
m_pListener->Close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_iMode != -1) {
|
||||
if (chmod(m_sPath.c_str(), m_iMode)) {
|
||||
char* e = strerror(errno);
|
||||
DEBUG("Error while chmod " << e);
|
||||
m_pListener->Close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CConfig CUnixListener::ToConfig() const {
|
||||
CConfig listenerConfig = CListener::ToConfig();
|
||||
|
||||
listenerConfig.AddKeyValuePair("Path", GetPath());
|
||||
if (!m_sGid.empty()) listenerConfig.AddKeyValuePair("Group", m_sGid);
|
||||
if (m_iMode != -1) {
|
||||
listenerConfig.AddKeyValuePair("Mode", GetMode());
|
||||
}
|
||||
|
||||
return listenerConfig;
|
||||
}
|
||||
|
||||
CString CUnixListener::GetMode() const {
|
||||
std::ostringstream s;
|
||||
if (m_iMode != -1) {
|
||||
s << std::oct << m_iMode;
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
|
||||
void CListener::ResetRealListener() { m_pListener = nullptr; }
|
||||
|
||||
CRealListener::~CRealListener() { m_Listener.ResetRealListener(); }
|
||||
|
||||
+12
-4
@@ -1744,13 +1744,16 @@ bool CZNC::AddTCPListener(unsigned short uPort, const CString& sBindHost,
|
||||
|
||||
bool CZNC::AddUnixListener(const CString& sPath, const CString& sURIPrefix,
|
||||
bool bSSL, CListener::EAcceptType eAccept,
|
||||
CString& sError) {
|
||||
CUtils::PrintAction("Binding to path [" + sPath + "]" + (bSSL ? " with SSL" : ""));
|
||||
const CString& sGroup, const CString& sMode, CString& sError) {
|
||||
CUtils::PrintAction("Binding to path [" + sPath + "]" +
|
||||
(bSSL ? " with SSL" : "") +
|
||||
(sGroup.empty() ? CString() : " gid=" + sGroup) +
|
||||
(sMode.empty() ? CString() : " mode=" + sMode));
|
||||
|
||||
if (!CheckSslAndPemFile(bSSL, sError)) return false;
|
||||
|
||||
CListener* pListener =
|
||||
new CUnixListener(sPath, sURIPrefix, bSSL, eAccept);
|
||||
new CUnixListener(sPath, sURIPrefix, bSSL, eAccept, sGroup, sMode);
|
||||
return FinishAddingListener(pListener, sError);
|
||||
}
|
||||
|
||||
@@ -1841,8 +1844,13 @@ bool CZNC::AddListener(CConfig* pConfig, CString& sError) {
|
||||
|
||||
return AddTCPListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr,
|
||||
eAccept, sError);
|
||||
} else {
|
||||
CString sGroup;
|
||||
CString sMode;
|
||||
pConfig->FindStringEntry("group", sGroup);
|
||||
pConfig->FindStringEntry("mode", sMode);
|
||||
return AddUnixListener(sPath, sURIPrefix, bSSL, eAccept, sGroup, sMode, sError);
|
||||
}
|
||||
return AddUnixListener(sPath, sURIPrefix, bSSL, eAccept, sError);
|
||||
}
|
||||
|
||||
bool CZNC::AddListener(CListener* pListener) {
|
||||
|
||||
Reference in New Issue
Block a user