mirror of
https://github.com/znc/znc.git
synced 2026-08-09 10:23:14 +02:00
Add support to connect to server via unix socket
The syntax for AddServer command and config is chosen to be unix:/path or unix:ssl:/path For security reasons, only admins can add such servers, to prevent users from poking around the file system.
This commit is contained in:
+23
-10
@@ -817,7 +817,7 @@ void CClient::UserCommand(CString& sLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
CString sServer = sLine.Token(1);
|
||||
CString sServer = sLine.Token(1, true);
|
||||
|
||||
if (!m_pNetwork) {
|
||||
PutStatus(t_s(
|
||||
@@ -827,10 +827,20 @@ void CClient::UserCommand(CString& sLine) {
|
||||
|
||||
if (sServer.empty()) {
|
||||
PutStatus(t_s("Usage: AddServer <host> [[+]port] [pass]"));
|
||||
if (m_pUser->IsAdmin()) {
|
||||
PutStatus(t_s("Or: AddServer unix:[ssl:]/path/to/socket"));
|
||||
}
|
||||
PutStatus(t_s("+ means SSL"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pNetwork->AddServer(sLine.Token(1, true))) {
|
||||
CServer Server = CServer::Parse(sServer);
|
||||
if (Server.IsUnixSocket() && !m_pUser->IsAdmin()) {
|
||||
PutStatus(t_s("Access denied!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pNetwork->AddServer(std::move(Server))) {
|
||||
PutStatus(t_s("Server added"));
|
||||
} else {
|
||||
PutStatus(
|
||||
@@ -849,11 +859,9 @@ void CClient::UserCommand(CString& sLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
CString sServer = sLine.Token(1);
|
||||
unsigned short uPort = sLine.Token(2).ToUShort();
|
||||
CString sPass = sLine.Token(3);
|
||||
CServer Server = CServer::Parse(sLine.Token(1, true));
|
||||
|
||||
if (sServer.empty()) {
|
||||
if (Server.GetName().empty()) {
|
||||
PutStatus(t_s("Usage: DelServer <host> [port] [pass]"));
|
||||
return;
|
||||
}
|
||||
@@ -863,7 +871,9 @@ void CClient::UserCommand(CString& sLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pNetwork->DelServer(sServer, uPort, sPass)) {
|
||||
// Unix sockets can be removed with "unix:" prefix and without, both
|
||||
// work.
|
||||
if (m_pNetwork->DelServer(Server)) {
|
||||
PutStatus(t_s("Server removed"));
|
||||
} else {
|
||||
PutStatus(t_s("No such server"));
|
||||
@@ -888,9 +898,12 @@ void CClient::UserCommand(CString& sLine) {
|
||||
Table.AddRow();
|
||||
Table.SetCell(
|
||||
t_s("Host", "listservers"),
|
||||
pServer->GetName() + (pServer == pCurServ ? "*" : ""));
|
||||
Table.SetCell(t_s("Port", "listservers"),
|
||||
CString(pServer->GetPort()));
|
||||
(pServer->IsUnixSocket() ? pServer->GetString(false)
|
||||
: pServer->GetName()) +
|
||||
(pServer == pCurServ ? "*" : ""));
|
||||
if (!pServer->IsUnixSocket())
|
||||
Table.SetCell(t_s("Port", "listservers"),
|
||||
CString(pServer->GetPort()));
|
||||
Table.SetCell(
|
||||
t_s("SSL", "listservers"),
|
||||
(pServer->IsSSL()) ? t_s("SSL", "listservers|cell") : "");
|
||||
|
||||
+38
-43
@@ -215,8 +215,7 @@ void CIRCNetwork::Clone(const CIRCNetwork& Network, bool bCloneName) {
|
||||
DelServers();
|
||||
|
||||
for (CServer* pServer : vServers) {
|
||||
AddServer(pServer->GetName(), pServer->GetPort(), pServer->GetPass(),
|
||||
pServer->IsSSL());
|
||||
AddServer(*pServer);
|
||||
}
|
||||
|
||||
m_uServerIdx = 0;
|
||||
@@ -1155,6 +1154,11 @@ bool CIRCNetwork::DelServer(const CString& sName, unsigned short uPort,
|
||||
return false;
|
||||
}
|
||||
|
||||
CServer Server(sName, uPort, sPass);
|
||||
return DelServer(Server);
|
||||
}
|
||||
|
||||
bool CIRCNetwork::DelServer(const CServer& Server) {
|
||||
unsigned int a = 0;
|
||||
bool bSawCurrentServer = false;
|
||||
CServer* pCurServer = GetCurrentServer();
|
||||
@@ -1165,11 +1169,16 @@ bool CIRCNetwork::DelServer(const CString& sName, unsigned short uPort,
|
||||
|
||||
if (pServer == pCurServer) bSawCurrentServer = true;
|
||||
|
||||
if (!pServer->GetName().Equals(sName)) continue;
|
||||
// Unix sockets can be removed with "unix:" prefix and without, both
|
||||
// work - that's not part of GetName()
|
||||
if (!pServer->GetName().Equals(Server.GetName())) continue;
|
||||
|
||||
if (uPort != 0 && pServer->GetPort() != uPort) continue;
|
||||
// But it makes no sense to remove TCP server via "unix:hostname.com"
|
||||
if (!pServer->IsUnixSocket() && Server.IsUnixSocket()) continue;
|
||||
|
||||
if (!sPass.empty() && pServer->GetPass() != sPass) continue;
|
||||
if (Server.GetPort() != 6667 && pServer->GetPort() != Server.GetPort()) continue;
|
||||
|
||||
if (!Server.GetPass().empty() && pServer->GetPass() != Server.GetPass()) continue;
|
||||
|
||||
m_vServers.erase(it);
|
||||
|
||||
@@ -1205,21 +1214,23 @@ bool CIRCNetwork::AddServer(const CString& sName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bSSL = false;
|
||||
CString sLine = sName;
|
||||
sLine.Trim();
|
||||
return AddServer(CServer::Parse(sName));
|
||||
}
|
||||
|
||||
CString sHost = sLine.Token(0);
|
||||
CString sPort = sLine.Token(1);
|
||||
bool CIRCNetwork::AddServer(CServer Server) {
|
||||
if (Server.GetName().empty()) return false;
|
||||
#ifndef HAVE_LIBSSL
|
||||
if (Server.IsSSL()) return false;
|
||||
#endif
|
||||
|
||||
if (sPort.TrimPrefix("+")) {
|
||||
bSSL = true;
|
||||
// Check if server is already added
|
||||
for (CServer* pServer : m_vServers) {
|
||||
if (*pServer == Server) return false;
|
||||
}
|
||||
|
||||
unsigned short uPort = sPort.ToUShort();
|
||||
CString sPass = sLine.Token(2, true);
|
||||
|
||||
return AddServer(sHost, uPort, sPass, bSSL);
|
||||
m_vServers.push_back(new CServer(std::move(Server)));
|
||||
CheckIRCConnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CIRCNetwork::AddServer(const CString& sName, unsigned short uPort,
|
||||
@@ -1234,30 +1245,7 @@ bool CIRCNetwork::AddServer(const CString& sName, unsigned short uPort,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!uPort) {
|
||||
uPort = 6667;
|
||||
}
|
||||
|
||||
// Check if server is already added
|
||||
for (CServer* pServer : m_vServers) {
|
||||
if (!sName.Equals(pServer->GetName())) continue;
|
||||
|
||||
if (uPort != pServer->GetPort()) continue;
|
||||
|
||||
if (sPass != pServer->GetPass()) continue;
|
||||
|
||||
if (bSSL != pServer->IsSSL()) continue;
|
||||
|
||||
// Server is already added
|
||||
return false;
|
||||
}
|
||||
|
||||
CServer* pServer = new CServer(sName, uPort, sPass, bSSL);
|
||||
m_vServers.push_back(pServer);
|
||||
|
||||
CheckIRCConnect();
|
||||
|
||||
return true;
|
||||
return AddServer(CServer(sName, uPort, sPass, bSSL));
|
||||
}
|
||||
|
||||
CServer* CIRCNetwork::GetNextServer(bool bAdvance) {
|
||||
@@ -1374,9 +1362,16 @@ bool CIRCNetwork::Connect() {
|
||||
}
|
||||
|
||||
CString sSockName = "IRC::" + m_pUser->GetUsername() + "::" + m_sName;
|
||||
CZNC::Get().GetManager().Connect(pServer->GetName(), pServer->GetPort(),
|
||||
sSockName, 120, bSSL, GetBindHost(),
|
||||
pIRCSock);
|
||||
|
||||
if (pServer->IsUnixSocket()) {
|
||||
pIRCSock->SetSSL(bSSL);
|
||||
CZNC::Get().GetManager().ConnectUnix(sSockName, pServer->GetName(),
|
||||
pIRCSock);
|
||||
} else {
|
||||
CZNC::Get().GetManager().Connect(pServer->GetName(), pServer->GetPort(),
|
||||
sSockName, 120, bSSL, GetBindHost(),
|
||||
pIRCSock);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+63
-5
@@ -17,11 +17,12 @@
|
||||
#include <znc/Server.h>
|
||||
|
||||
CServer::CServer(const CString& sName, unsigned short uPort,
|
||||
const CString& sPass, bool bSSL)
|
||||
const CString& sPass, bool bSSL, bool bUnixSocket)
|
||||
: m_sName(sName),
|
||||
m_uPort((uPort) ? uPort : (unsigned short)6667),
|
||||
m_sPass(sPass),
|
||||
m_bSSL(bSSL) {}
|
||||
m_bSSL(bSSL),
|
||||
m_bUnixSocket(bUnixSocket) {}
|
||||
|
||||
CServer::~CServer() {}
|
||||
|
||||
@@ -33,9 +34,66 @@ const CString& CServer::GetName() const { return m_sName; }
|
||||
unsigned short CServer::GetPort() const { return m_uPort; }
|
||||
const CString& CServer::GetPass() const { return m_sPass; }
|
||||
bool CServer::IsSSL() const { return m_bSSL; }
|
||||
bool CServer::IsUnixSocket() const { return m_bUnixSocket; }
|
||||
|
||||
CString CServer::GetString(bool bIncludePassword) const {
|
||||
return m_sName + " " + CString(m_bSSL ? "+" : "") + CString(m_uPort) +
|
||||
CString(bIncludePassword ? (m_sPass.empty() ? "" : " " + m_sPass)
|
||||
: "");
|
||||
CString sResult;
|
||||
if (m_bUnixSocket) {
|
||||
sResult = "unix:" + CString(m_bSSL ? "ssl:" : "") + m_sName;
|
||||
} else {
|
||||
sResult = m_sName + " " + CString(m_bSSL ? "+" : "") + CString(m_uPort);
|
||||
}
|
||||
sResult +=
|
||||
CString(bIncludePassword ? (m_sPass.empty() ? "" : " " + m_sPass) : "");
|
||||
return sResult;
|
||||
}
|
||||
|
||||
CServer CServer::Parse(CString sLine) {
|
||||
bool bSSL = false;
|
||||
sLine.Trim();
|
||||
|
||||
if (sLine.TrimPrefix("unix:")) {
|
||||
if (sLine.TrimPrefix("ssl:")) {
|
||||
bSSL = true;
|
||||
}
|
||||
|
||||
CString sPath = sLine.Token(0);
|
||||
CString sPass = sLine.Token(1, true);
|
||||
return CServer(sPath, 0, sPass, bSSL, true);
|
||||
}
|
||||
|
||||
CString sHost = sLine.Token(0);
|
||||
CString sPort = sLine.Token(1);
|
||||
|
||||
if (sPort.TrimPrefix("+")) {
|
||||
bSSL = true;
|
||||
}
|
||||
|
||||
unsigned short uPort = sPort.ToUShort();
|
||||
CString sPass = sLine.Token(2, true);
|
||||
|
||||
return CServer(sHost, uPort, sPass, bSSL, false);
|
||||
}
|
||||
|
||||
bool CServer::operator==(const CServer& o) const {
|
||||
if (m_sName != o.m_sName) return false;
|
||||
if (m_uPort != o.m_uPort) return false;
|
||||
if (m_sPass != o.m_sPass) return false;
|
||||
if (m_bSSL != o.m_bSSL) return false;
|
||||
if (m_bUnixSocket != o.m_bUnixSocket) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CServer::operator<(const CServer& o) const {
|
||||
if (m_sName < o.m_sName) return true;
|
||||
if (m_sName > o.m_sName) return false;
|
||||
if (m_uPort < o.m_uPort) return true;
|
||||
if (m_uPort > o.m_uPort) return false;
|
||||
if (m_sPass < o.m_sPass) return true;
|
||||
if (m_sPass > o.m_sPass) return false;
|
||||
if (m_bSSL < o.m_bSSL) return true;
|
||||
if (m_bSSL > o.m_bSSL) return false;
|
||||
if (m_bUnixSocket < o.m_bUnixSocket) return true;
|
||||
if (m_bUnixSocket > o.m_bUnixSocket) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user