From 640bb5377e24886342bacfc0c73e09ea71dc6956 Mon Sep 17 00:00:00 2001 From: outlaws-bai <80510016+outlaws-bai@users.noreply.github.com> Date: Tue, 31 Oct 2023 20:52:21 +0800 Subject: [PATCH] fix #6426 - Optimize LDAP Proxy Auth (#6428) * fix #6426 https://github.com/mitmproxy/mitmproxy/issues/6426 * Revert "fix #6426" This reverts commit 822b05b522c55a79e2de2809c49b2508f8edfd6c. * fix # 6426 Optimize LDAP Proxy Auth * [autofix.ci] apply automated fixes * update CHANGELOG.md --------- Co-authored-by: jincong.bai Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 ++ mitmproxy/addons/proxyauth.py | 28 +++++++++++++++++++++---- mitmproxy/utils/arg_check.py | 2 +- test/mitmproxy/addons/test_proxyauth.py | 15 +++++++++++++ test/mitmproxy/utils/test_arg_check.py | 2 +- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27cec191b..7ab6ebd48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ ([#6412](https://github.com/mitmproxy/mitmproxy/pull/6412), @tddschn) * Fix root-relative URLs so that mitmweb can run in subdirectories. ([#6411](https://github.com/mitmproxy/mitmproxy/pull/6411), @davet2001) +* Add an optional parameter(ldap search filter key) to ProxyAuth-LDAP. + ([#6428](https://github.com/mitmproxy/mitmproxy/pull/6428), @outlaws-bai) ## 27 September 2023: mitmproxy 10.1.1 diff --git a/mitmproxy/addons/proxyauth.py b/mitmproxy/addons/proxyauth.py index 5ff57feee..3dcd98619 100644 --- a/mitmproxy/addons/proxyauth.py +++ b/mitmproxy/addons/proxyauth.py @@ -40,7 +40,7 @@ class ProxyAuth: "username:pass", "any" to accept any user/pass combination, "@path" to use an Apache htpasswd file, - or "ldap[s]:url_server_ldap[:port]:dn_auth:password:dn_subtree" for LDAP authentication. + or "ldap[s]:url_server_ldap[:port]:dn_auth:password:dn_subtree[?search_filter_key=...]" for LDAP authentication. """, ) @@ -213,6 +213,7 @@ class Ldap(Validator): conn: ldap3.Connection server: ldap3.Server dn_subtree: str + filter_key: str def __init__(self, proxyauth: str): ( @@ -222,6 +223,7 @@ class Ldap(Validator): ldap_user, ldap_pass, self.dn_subtree, + self.filter_key, ) = self.parse_spec(proxyauth) server = ldap3.Server(url, port=port, use_ssl=use_ssl) conn = ldap3.Connection(server, ldap_user, ldap_pass, auto_bind=True) @@ -229,7 +231,7 @@ class Ldap(Validator): self.server = server @staticmethod - def parse_spec(spec: str) -> tuple[bool, str, int | None, str, str, str]: + def parse_spec(spec: str) -> tuple[bool, str, int | None, str, str, str, str]: try: if spec.count(":") > 4: ( @@ -245,6 +247,16 @@ class Ldap(Validator): security, url, ldap_user, ldap_pass, dn_subtree = spec.split(":") port = None + if "?" in dn_subtree: + dn_subtree, search_str = dn_subtree.split("?") + key, value = search_str.split("=") + if key == "search_filter_key": + search_filter_key = value + else: + raise ValueError + else: + search_filter_key = "cn" + if security == "ldaps": use_ssl = True elif security == "ldap": @@ -252,14 +264,22 @@ class Ldap(Validator): else: raise ValueError - return use_ssl, url, port, ldap_user, ldap_pass, dn_subtree + return ( + use_ssl, + url, + port, + ldap_user, + ldap_pass, + dn_subtree, + search_filter_key, + ) except ValueError: raise exceptions.OptionsError(f"Invalid LDAP specification: {spec}") def __call__(self, username: str, password: str) -> bool: if not username or not password: return False - self.conn.search(self.dn_subtree, f"(cn={username})") + self.conn.search(self.dn_subtree, f"({self.filter_key}={username})") if self.conn.response: c = ldap3.Connection( self.server, self.conn.response[0]["dn"], password, auto_bind=True diff --git a/mitmproxy/utils/arg_check.py b/mitmproxy/utils/arg_check.py index 35a5aa23a..1dab73caf 100644 --- a/mitmproxy/utils/arg_check.py +++ b/mitmproxy/utils/arg_check.py @@ -127,7 +127,7 @@ def check(): "Please use `--proxyauth SPEC` instead.\n" 'SPEC Format: "username:pass", "any" to accept any user/pass combination,\n' '"@path" to use an Apache htpasswd file, or\n' - '"ldap[s]:url_server_ldap:dn_auth:password:dn_subtree" ' + '"ldap[s]:url_server_ldap[:port]:dn_auth:password:dn_subtree[?search_filter_key=...]" ' "for LDAP authentication.".format(option) ) diff --git a/test/mitmproxy/addons/test_proxyauth.py b/test/mitmproxy/addons/test_proxyauth.py index 9bdb5b7ce..743bc635b 100644 --- a/test/mitmproxy/addons/test_proxyauth.py +++ b/test/mitmproxy/addons/test_proxyauth.py @@ -165,11 +165,25 @@ class TestProxyAuth: ) assert isinstance(pa.validator, proxyauth.Ldap) + ctx.configure( + pa, + proxyauth="ldap:localhost:1234:cn=default,dc=cdhdt,dc=com:password:dc=cdhdt,dc=com?search_filter_key=SamAccountName", + ) + assert isinstance(pa.validator, proxyauth.Ldap) + with pytest.raises( exceptions.OptionsError, match="Invalid LDAP specification" ): ctx.configure(pa, proxyauth="ldap:test:test:test") + with pytest.raises( + exceptions.OptionsError, match="Invalid LDAP specification" + ): + ctx.configure( + pa, + proxyauth="ldap:localhost:1234:cn=default,dc=cdhdt,dc=com:password:ou=application,dc=cdhdt,dc=com?key=1", + ) + with pytest.raises( exceptions.OptionsError, match="Invalid LDAP specification" ): @@ -231,6 +245,7 @@ class TestProxyAuth: [ "ldaps:localhost:cn=default,dc=cdhdt,dc=com:password:ou=application,dc=cdhdt,dc=com", "ldap:localhost:1234:cn=default,dc=cdhdt,dc=com:password:ou=application,dc=cdhdt,dc=com", + "ldap:localhost:1234:cn=default,dc=cdhdt,dc=com:password:ou=application,dc=cdhdt,dc=com?search_filter_key=cn", ], ) def test_ldap(monkeypatch, spec): diff --git a/test/mitmproxy/utils/test_arg_check.py b/test/mitmproxy/utils/test_arg_check.py index d498d1c43..29018ddad 100644 --- a/test/mitmproxy/utils/test_arg_check.py +++ b/test/mitmproxy/utils/test_arg_check.py @@ -35,7 +35,7 @@ from mitmproxy.utils import arg_check "Please use `--proxyauth SPEC` instead.\n" 'SPEC Format: "username:pass", "any" to accept any user/pass combination,\n' '"@path" to use an Apache htpasswd file, or\n' - '"ldap[s]:url_server_ldap:dn_auth:password:dn_subtree" ' + '"ldap[s]:url_server_ldap[:port]:dn_auth:password:dn_subtree[?search_filter_key=...]" ' "for LDAP authentication.", ), (