ISSUE_5068 (#5161)

* changes for custom port number

* indent correction

* test coverage

* coverage correction

* simplify LDAP auth

* make mypy hapy

Co-authored-by: Maximilian Hils <git@maximilianhils.com>
This commit is contained in:
Vinayak Khandelwal 2022-03-16 02:09:38 +05:30 committed by GitHub
parent a0cf273484
commit 3d5f6da048
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 16 deletions

View File

@ -30,6 +30,7 @@
* Allow addon hooks to be async (@nneonneo, #4207) * Allow addon hooks to be async (@nneonneo, #4207)
* Reintroduce `Flow.live`, which signals if a flow belongs to a currently active connection. (@mhils, #4207) * Reintroduce `Flow.live`, which signals if a flow belongs to a currently active connection. (@mhils, #4207)
* Speculative fix for some rare HTTP/2 connection stalls (#5158, @EndUser509) * Speculative fix for some rare HTTP/2 connection stalls (#5158, @EndUser509)
* Add ability to specify custom ports with LDAP authentication (#5068, @demonoidvk)
* Console Improvements on Windows (@mhils) * Console Improvements on Windows (@mhils)
## 28 September 2021: mitmproxy 7.0.4 ## 28 September 2021: mitmproxy 7.0.4

View File

@ -34,7 +34,7 @@ class ProxyAuth:
"username:pass", "username:pass",
"any" to accept any user/pass combination, "any" to accept any user/pass combination,
"@path" to use an Apache htpasswd file, "@path" to use an Apache htpasswd file,
or "ldap[s]:url_server_ldap:dn_auth:password:dn_subtree" for LDAP authentication. or "ldap[s]:url_server_ldap[:port]:dn_auth:password:dn_subtree" for LDAP authentication.
""" """
) )
@ -207,16 +207,15 @@ class Ldap(Validator):
dn_subtree: str dn_subtree: str
def __init__(self, proxyauth: str): def __init__(self, proxyauth: str):
try: (
security, url, ldap_user, ldap_pass, self.dn_subtree = proxyauth.split(":") use_ssl,
except ValueError: url,
raise exceptions.OptionsError("Invalid ldap specification") port,
if security == "ldaps": ldap_user,
server = ldap3.Server(url, use_ssl=True) ldap_pass,
elif security == "ldap": self.dn_subtree,
server = ldap3.Server(url) ) = self.parse_spec(proxyauth)
else: server = ldap3.Server(url, port=port, use_ssl=use_ssl)
raise exceptions.OptionsError("Invalid ldap specification on the first part")
conn = ldap3.Connection( conn = ldap3.Connection(
server, server,
ldap_user, ldap_user,
@ -226,6 +225,34 @@ class Ldap(Validator):
self.conn = conn self.conn = conn
self.server = server self.server = server
@staticmethod
def parse_spec(spec: str) -> Tuple[bool, str, Optional[int], str, str, str]:
try:
if spec.count(":") > 4:
(
security,
url,
port_str,
ldap_user,
ldap_pass,
dn_subtree,
) = spec.split(":")
port = int(port_str)
else:
security, url, ldap_user, ldap_pass, dn_subtree = spec.split(":")
port = None
if security == "ldaps":
use_ssl = True
elif security == "ldap":
use_ssl = False
else:
raise ValueError
return use_ssl, url, port, ldap_user, ldap_pass, dn_subtree
except ValueError:
raise exceptions.OptionsError(f"Invalid LDAP specification: {spec}")
def __call__(self, username: str, password: str) -> bool: def __call__(self, username: str, password: str) -> bool:
if not username or not password: if not username or not password:
return False return False

View File

@ -147,13 +147,19 @@ class TestProxyAuth:
) )
assert isinstance(pa.validator, proxyauth.Ldap) assert isinstance(pa.validator, proxyauth.Ldap)
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"
)
assert isinstance(pa.validator, proxyauth.Ldap)
with pytest.raises(exceptions.OptionsError, match="Invalid LDAP specification"):
ctx.configure(pa, proxyauth="ldap:test:test:test") ctx.configure(pa, proxyauth="ldap:test:test:test")
with pytest.raises(exceptions.OptionsError, match="Invalid ldap specification"): with pytest.raises(exceptions.OptionsError, match="Invalid LDAP specification"):
ctx.configure(pa, proxyauth="ldap:fake_serveruid=?dc=example,dc=com:person") ctx.configure(pa, proxyauth="ldap:fake_serveruid=?dc=example,dc=com:person")
with pytest.raises(exceptions.OptionsError, match="Invalid ldap specification"): with pytest.raises(exceptions.OptionsError, match="Invalid LDAP specification"):
ctx.configure(pa, proxyauth="ldapssssssss:fake_server:dn:password:tree") ctx.configure(pa, proxyauth="ldapssssssss:fake_server:dn:password:tree")
with pytest.raises(exceptions.OptionsError, match="Could not open htpasswd file"): with pytest.raises(exceptions.OptionsError, match="Could not open htpasswd file"):
@ -200,11 +206,15 @@ class TestProxyAuth:
assert f2.metadata["proxyauth"] == ('test', 'test') assert f2.metadata["proxyauth"] == ('test', 'test')
def test_ldap(monkeypatch): @pytest.mark.parametrize("spec", [
"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"
])
def test_ldap(monkeypatch, spec):
monkeypatch.setattr(ldap3, "Server", mock.MagicMock()) monkeypatch.setattr(ldap3, "Server", mock.MagicMock())
monkeypatch.setattr(ldap3, "Connection", mock.MagicMock()) monkeypatch.setattr(ldap3, "Connection", mock.MagicMock())
validator = proxyauth.Ldap("ldaps:localhost:cn=default,dc=cdhdt,dc=com:password:ou=application,dc=cdhdt,dc=com") validator = proxyauth.Ldap(spec)
assert not validator("", "") assert not validator("", "")
assert validator("foo", "bar") assert validator("foo", "bar")
validator.conn.response = False validator.conn.response = False