mirror of
https://github.com/znc/znc.git
synced 2026-07-01 15:31:52 +02:00
X-Forwarded-For: verify the whole chain, from the end
This commit is contained in:
@@ -56,6 +56,7 @@ public:
|
||||
void ParseURI();
|
||||
void GetPage();
|
||||
static CString GetDate(time_t tm = 0);
|
||||
virtual CString GetRemoteIP();
|
||||
|
||||
// Cookies
|
||||
CString GetRequestCookie(const CString& sKey) const;
|
||||
|
||||
@@ -130,7 +130,6 @@ public:
|
||||
|
||||
CSmartPtr<CWebSession> GetSession();
|
||||
|
||||
virtual CString GetRemoteIP();
|
||||
virtual Csock* GetSockObj(const CString& sHost, unsigned short uPort);
|
||||
static CString GetSkinPath(const CString& sSkinName);
|
||||
CModule* GetModule() const { return (CModule*) m_pModule; }
|
||||
|
||||
+5
-5
@@ -66,9 +66,9 @@ public:
|
||||
void ClearBindHosts();
|
||||
bool AddBindHost(const CString& sHost);
|
||||
bool RemBindHost(const CString& sHost);
|
||||
void ClearAllowProxy();
|
||||
bool AddAllowProxy(const CString& sHost);
|
||||
bool RemAllowProxy(const CString& sHost);
|
||||
void ClearTrustedProxies();
|
||||
bool AddTrustedProxy(const CString& sHost);
|
||||
bool RemTrustedProxy(const CString& sHost);
|
||||
void Broadcast(const CString& sMessage, bool bAdminOnly = false,
|
||||
CUser* pSkipUser = NULL, CClient* pSkipClient = NULL);
|
||||
void AddBytesRead(unsigned long long u) { m_uBytesRead += u; }
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
const CString& GetConfigFile() const { return m_sConfigFile; }
|
||||
bool WritePemFile();
|
||||
const VCString& GetBindHosts() const { return m_vsBindHosts; }
|
||||
const VCString& GetAllowProxies() const { return m_vsAllowProxies; }
|
||||
const VCString& GetTrustedProxies() const { return m_vsTrustedProxies; }
|
||||
const std::vector<CListener*>& GetListeners() const { return m_vpListeners; }
|
||||
time_t TimeStarted() const { return m_TimeStarted; }
|
||||
unsigned int GetMaxBufferSize() const { return m_uiMaxBufferSize; }
|
||||
@@ -208,7 +208,7 @@ protected:
|
||||
CString m_sPidFile;
|
||||
CString m_sSSLCertFile;
|
||||
VCString m_vsBindHosts;
|
||||
VCString m_vsAllowProxies;
|
||||
VCString m_vsTrustedProxies;
|
||||
VCString m_vsMotd;
|
||||
CFile* m_pLockFile;
|
||||
unsigned int m_uiConnectDelay;
|
||||
|
||||
+39
-1
@@ -128,7 +128,37 @@ void CHTTPSock::ReadLine(const CString& sData) {
|
||||
if (m_uPostLen > MAX_POST_SIZE)
|
||||
PrintErrorPage(413, "Request Entity Too Large", "The request you sent was too large.");
|
||||
} else if (sName.Equals("X-Forwarded-For:")) {
|
||||
m_sForwardedIP = sLine.Token(1).TrimRight_n(",");
|
||||
// X-Forwarded-For: client, proxy1, proxy2
|
||||
if (m_sForwardedIP.empty()) {
|
||||
const VCString& vsTrustedProxies = CZNC::Get().GetTrustedProxies();
|
||||
CString sIP = GetRemoteIP();
|
||||
|
||||
VCString vsIPs;
|
||||
sLine.Token(1, true).Split(",", vsIPs, false, "", "", false, true);
|
||||
|
||||
while (!vsIPs.empty()) {
|
||||
// sIP told us that it got connection from vsIPs.back()
|
||||
// check if sIP is trusted proxy
|
||||
bool bTrusted = false;
|
||||
for (VCString::const_iterator it = vsTrustedProxies.begin(); it != vsTrustedProxies.end(); ++it) {
|
||||
if (sIP.WildCmp(*it)) {
|
||||
bTrusted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bTrusted) {
|
||||
// sIP is trusted proxy, so use vsIPs.back() as new sIP
|
||||
sIP = vsIPs.back();
|
||||
vsIPs.pop_back();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// either sIP is not trusted proxy, or it's in the beginning of the X-Forwarded-For list
|
||||
// in both cases use it as the endpoind
|
||||
m_sForwardedIP = sIP;
|
||||
}
|
||||
} else if (sName.Equals("If-None-Match:")) {
|
||||
// this is for proper client cache support (HTTP 304) on static files:
|
||||
m_sIfNoneMatch = sLine.Token(1, true);
|
||||
@@ -151,6 +181,14 @@ void CHTTPSock::ReadLine(const CString& sData) {
|
||||
}
|
||||
}
|
||||
|
||||
CString CHTTPSock::GetRemoteIP() {
|
||||
if (!m_sForwardedIP.empty()) {
|
||||
return m_sForwardedIP;
|
||||
}
|
||||
|
||||
return CSocket::GetRemoteIP();
|
||||
}
|
||||
|
||||
CString CHTTPSock::GetDate(time_t stamp) {
|
||||
struct tm tm;
|
||||
std::stringstream stream;
|
||||
|
||||
@@ -866,21 +866,6 @@ bool CWebSock::OnLogin(const CString& sUser, const CString& sPass) {
|
||||
return IsLoggedIn();
|
||||
}
|
||||
|
||||
CString CWebSock::GetRemoteIP()
|
||||
{
|
||||
const VCString& vsProxies = CZNC::Get().GetAllowProxies();
|
||||
CString sIP = CHTTPSock::GetRemoteIP();
|
||||
|
||||
VCString::const_iterator it;
|
||||
for (it = vsProxies.begin(); it != vsProxies.end(); ++it) {
|
||||
if (sIP.WildCmp(*it)) {
|
||||
return m_sForwardedIP;
|
||||
}
|
||||
}
|
||||
|
||||
return sIP;
|
||||
}
|
||||
|
||||
Csock* CWebSock::GetSockObj(const CString& sHost, unsigned short uPort) {
|
||||
// All listening is done by CListener, thus CWebSock should never have
|
||||
// to listen, but since GetSockObj() is pure virtual...
|
||||
|
||||
+14
-14
@@ -484,8 +484,8 @@ bool CZNC::WriteConfig() {
|
||||
config.AddKeyValuePair("BindHost", m_vsBindHosts[v].FirstLine());
|
||||
}
|
||||
|
||||
for (unsigned int v = 0; v < m_vsAllowProxies.size(); v++) {
|
||||
config.AddKeyValuePair("AllowProxy", m_vsAllowProxies[v].FirstLine());
|
||||
for (unsigned int v = 0; v < m_vsTrustedProxies.size(); v++) {
|
||||
config.AddKeyValuePair("TrustedProxy", m_vsTrustedProxies[v].FirstLine());
|
||||
}
|
||||
|
||||
CModules& Mods = GetModules();
|
||||
@@ -1114,7 +1114,7 @@ bool CZNC::DoRehash(CString& sError)
|
||||
}
|
||||
|
||||
m_vsBindHosts.clear();
|
||||
m_vsAllowProxies.clear();
|
||||
m_vsTrustedProxies.clear();
|
||||
m_vsMotd.clear();
|
||||
|
||||
// Delete all listeners
|
||||
@@ -1209,9 +1209,9 @@ bool CZNC::DoRehash(CString& sError)
|
||||
AddBindHost(*vit);
|
||||
}
|
||||
|
||||
config.FindStringVector("allowproxy", vsList);
|
||||
config.FindStringVector("trustedproxy", vsList);
|
||||
for (vit = vsList.begin(); vit != vsList.end(); ++vit) {
|
||||
AddAllowProxy(*vit);
|
||||
AddTrustedProxy(*vit);
|
||||
}
|
||||
|
||||
config.FindStringVector("vhost", vsList);
|
||||
@@ -1437,30 +1437,30 @@ bool CZNC::RemBindHost(const CString& sHost) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CZNC::ClearAllowProxy() {
|
||||
m_vsAllowProxies.clear();
|
||||
void CZNC::ClearTrustedProxies() {
|
||||
m_vsTrustedProxies.clear();
|
||||
}
|
||||
|
||||
bool CZNC::AddAllowProxy(const CString& sHost) {
|
||||
bool CZNC::AddTrustedProxy(const CString& sHost) {
|
||||
if (sHost.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int a = 0; a < m_vsAllowProxies.size(); a++) {
|
||||
if (m_vsAllowProxies[a].Equals(sHost)) {
|
||||
for (unsigned int a = 0; a < m_vsTrustedProxies.size(); a++) {
|
||||
if (m_vsTrustedProxies[a].Equals(sHost)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_vsAllowProxies.push_back(sHost);
|
||||
m_vsTrustedProxies.push_back(sHost);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CZNC::RemAllowProxy(const CString& sHost) {
|
||||
bool CZNC::RemTrustedProxy(const CString& sHost) {
|
||||
VCString::iterator it;
|
||||
for (it = m_vsAllowProxies.begin(); it != m_vsAllowProxies.end(); ++it) {
|
||||
for (it = m_vsTrustedProxies.begin(); it != m_vsTrustedProxies.end(); ++it) {
|
||||
if (sHost.Equals(*it)) {
|
||||
m_vsAllowProxies.erase(it);
|
||||
m_vsTrustedProxies.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user