8000 [WIP] Allow trusted proxies to forward client certificate fingerprints (#1430) by an-empty-string · Pull Request #1478 · znc/znc · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[WIP] Allow trusted proxies to forward client certificate fingerprints (#1430) #1478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/znc/HTTPSock.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class CHTTPSock : public CSocket {
const CString& GetURI() const;
const CString& GetURIPrefix() const;
bool IsPost() const;
long GetPeerFingerprint(CString& sResult) const override;
// !Getters

// Parameter access
Expand Down Expand Up @@ -118,6 +119,7 @@ class CHTTPSock : public CSocket {
void WriteFileGzipped(CFile& File);

protected:
bool IsTrustedProxy(const CString& sIP);
void PrintPage(const CString& sPage);
void Init();

Expand All @@ -135,6 +137,7 @@ class CHTTPSock : public CSocket {
CString m_sContentType;
CString m_sDocRoot;
CString m_sForwardedIP;
CString m_sForwardedCertFP;
std::map<CString, VCString> m_msvsPOSTParams;
std::map<CString, VCString> m_msvsGETParams;
MCString m_msHeaders;
Expand Down
4 changes: 4 additions & 0 deletions include/znc/Socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class CZNCSock : public Csock, public CCoreTranslationMixin {

virtual CString GetRemoteIP() const { return Csock::GetRemoteIP(); }

virtual long GetPeerFingerprint(CS_STRING& sResult) const {
return Csock::GetPeerFingerprint(sResult);
}

protected:
// All existing errno codes seem to be in range 1-300
enum {
Expand Down
13 changes: 12 additions & 1 deletion modules/certauth.cpp
10000
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,18 @@ class CSSLClientCertMod : public CModule {

CString GetKey(Csock* pSock) {
CString sRes;
long int res = pSock->GetPeerFingerprint(sRes);

CZNCSock *pZNCSock;
long int res;
if ((pZNCSock = dynamic_cast<CZNCSock*>(pSock))) {
// This up-cast is needed because GetPeerFingerprint is not declared
// virtual on Csock, but it is on CZNCSock. This _should_ never
// fail, since all the Csocks we care about are also CZNCSocks, but
// better safe than sorry.
res = pZNCSock->GetPeerFingerprint(sRes);
} else {
res = pSock->GetPeerFingerprint(sRes);
}

DEBUG("GetKey() returned status " << res << " with key " << sRes);

Expand Down
38 changes: 30 additions & 8 deletions src/HTTPSock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@ void CHTTPSock::CheckPost() {
}
}

bool CHTTPSock::IsTrustedProxy(const CString& sIP) {
const VCString& vsTrustedProxies = CZNC::Get().GetTrustedProxies();
bool bTrusted = false;

for (const CString& sTrustedProxy : vsTrustedProxies) {
if (CUtils::CheckCIDR(sIP, sTrustedProxy)) {
bTrusted = true;
break;
}
}

return bTrusted;
}

void CHTTPSock::ReadLine(const CString& sData) {
if (m_bGotHeader) {
return;
Expand Down Expand Up @@ -152,7 +166,6 @@ void CHTTPSock::ReadLine(const CString& sData) {
} else if (sName.Equals("X-Forwarded-For:")) {
// X-Forwarded-For: client, proxy1, proxy2
if (m_sForwardedIP.empty()) {
const VCString& vsTrustedProxies = CZNC::Get().GetTrustedProxies();
CString sIP = GetRemoteIP();

VCString vsIPs;
Expand All @@ -161,13 +174,7 @@ void CHTTPSock::ReadLine(const CString& sData) {
while (!vsIPs.empty()) {
// sIP told us that it got connection from vsIPs.back()
// check if sIP is trusted proxy
bool bTrusted = false;
for (const CString& sTrustedProxy : vsTrustedProxies) {
if (CUtils::CheckCIDR(sIP, sTrustedProxy)) {
bTrusted = true;
break;
}
}
bool bTrusted = IsTrustedProxy(sIP);
if (bTrusted) {
// sIP is trusted proxy, so use vsIPs.back() as new sIP
sIP = vsIPs.back();
Expand All @@ -181,6 +188,12 @@ void CHTTPSock::ReadLine(const CString& sData) {
// X-Forwarded-For list in both cases use it as the endpoind
m_sForwardedIP = sIP;
}
} else if (sName.Equals("X-Forwarded-CertFP:")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find anything about this name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's not standardized anywhere. X-Forwarded-For is standardized by convention but as far as I know there isn't anything similar to TLS fingerprints, as this sort of thing isn't as widely done. This would have to go in documentation somewhere.

if (IsTrustedProxy(GetRemoteIP())) {
m_sForwardedCertFP = sLine.Token(1, true);
DEBUG(GetSockName()
<< " Got a forwarded CertFP '" << m_sForwardedCertFP << "'");
}
} 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);
Expand Down Expand Up @@ -540,6 +553,15 @@ const CString& CHTTPSock::GetURI() const { return m_sURI; }

const CString& CHTTPSock::GetURIPrefix() const { return m_sURIPrefix; }

long CHTTPSock::GetPeerFingerprint(CString& sResult) const {
if(m_sForwardedCertFP.empty()) {
return CSocket::GetPeerFingerprint(sResult);
}

sResult = m_sForwardedCertFP;
return X509_V_OK;
}

bool CHTTPSock::HasParam(const CString& sName, bool bPost) const {
if (bPost) return (m_msvsPOSTParams.find(sName) != m_msvsPOSTParams.end());
return (m_msvsGETParams.find(sName) != m_msvsGETParams.end());
Expand Down
0