map addons: fix tests

This commit is contained in:
Martin Plattner 2020-07-17 18:32:27 +02:00
parent 0c8a46253b
commit c98f12c4f3
6 changed files with 117 additions and 29 deletions

View File

@ -133,11 +133,15 @@ class MapLocal:
if mimetype: if mimetype:
headers = {"Content-Type": mimetype} headers = {"Content-Type": mimetype}
if local_file: if local_file:
flow.response = http.HTTPResponse.make( try:
200, flow.response = http.HTTPResponse.make(
local_file.read_bytes(), 200,
headers local_file.read_bytes(),
) headers
)
except IOError as e:
ctx.log.warn(f"Could not read file: {e}")
continue
# only set flow.response once, for the first matching rule # only set flow.response once, for the first matching rule
return return
if any_spec_matches: if any_spec_matches:

View File

@ -24,8 +24,18 @@ from mitmproxy.test import tflow
("https://example.com/foo/bar.jpg", ":/foo/bar.jpg:/tmp", ["/tmp/index.html"]), ("https://example.com/foo/bar.jpg", ":/foo/bar.jpg:/tmp", ["/tmp/index.html"]),
] + [ ] + [
# URL decode and special characters # URL decode and special characters
("http://example.com/foo%20bar.jpg", ":example.com:/tmp", ["/tmp/foo bar.jpg", "/tmp/foo bar.jpg/index.html", "/tmp/foo_bar.jpg", "/tmp/foo_bar.jpg/index.html"]), ("http://example.com/foo%20bar.jpg", ":example.com:/tmp", [
("http://example.com/fóobår.jpg", ":example.com:/tmp", ["/tmp/fóobår.jpg", "/tmp/fóobår.jpg/index.html", "/tmp/f_ob_r.jpg", "/tmp/f_ob_r.jpg/index.html"]), "/tmp/foo bar.jpg",
"/tmp/foo bar.jpg/index.html",
"/tmp/foo_bar.jpg",
"/tmp/foo_bar.jpg/index.html"
]),
("http://example.com/fóobår.jpg", ":example.com:/tmp", [
"/tmp/fóobår.jpg",
"/tmp/fóobår.jpg/index.html",
"/tmp/f_ob_r.jpg",
"/tmp/f_ob_r.jpg/index.html"
]),
] + [ ] + [
# index.html # index.html
("https://example.com/foo", ":example.com/foo:/tmp", ["/tmp/index.html"]), ("https://example.com/foo", ":example.com/foo:/tmp", ["/tmp/index.html"]),
@ -41,13 +51,23 @@ from mitmproxy.test import tflow
), ( ), (
"https://example/results?id=1&foo=2", "https://example/results?id=1&foo=2",
":example/(results\\?id=.+):/tmp", ":example/(results\\?id=.+):/tmp",
["/tmp/results?id=1&foo=2", "/tmp/results?id=1&foo=2/index.html", "/tmp/results_id=1_foo=2", "/tmp/results_id=1_foo=2/index.html"] [
"/tmp/results?id=1&foo=2",
"/tmp/results?id=1&foo=2/index.html",
"/tmp/results_id=1_foo=2",
"/tmp/results_id=1_foo=2/index.html"
]
), ),
] + [ ] + [
# test directory traversal detection # test directory traversal detection
("https://example.com/../../../../../../etc/passwd", ":example.com:/tmp", []), ("https://example.com/../../../../../../etc/passwd", ":example.com:/tmp", []),
# those get already sanitized to benign versions before they reach our detection: # those get already sanitized to benign versions before they reach our detection:
("https://example.com/C:\\foo.txt", ":example.com:/tmp", ["/tmp/C:/foo.txt", "/tmp/C:/foo.txt/index.html", "/tmp/C_/foo.txt", "/tmp/C_/foo.txt/index.html"]), ("https://example.com/C:\\foo.txt", ":example.com:/tmp", [
"/tmp/C:/foo.txt",
"/tmp/C:/foo.txt/index.html",
"/tmp/C_/foo.txt",
"/tmp/C_/foo.txt/index.html"
]),
("https://example.com//etc/passwd", ":example.com:/tmp", ["/tmp/etc/passwd", "/tmp/etc/passwd/index.html"]), ("https://example.com//etc/passwd", ":example.com:/tmp", ["/tmp/etc/passwd", "/tmp/etc/passwd/index.html"]),
] ]
) )
@ -61,7 +81,17 @@ def test_file_candidates(url, spec, expected_candidates):
class TestMapLocal: class TestMapLocal:
def test_map_local(self, tmpdir):
def test_configure(self, tmpdir):
ml = MapLocal()
with taddons.context(ml) as tctx:
tctx.configure(ml, map_local=["/foo/bar/" + str(tmpdir)])
with pytest.raises(Exception, match="Invalid regular expression"):
tctx.configure(ml, map_local=["/foo/+/" + str(tmpdir)])
with pytest.raises(Exception, match="Invalid file path"):
tctx.configure(ml, map_local=["/foo/.+/three"])
def test_simple(self, tmpdir):
ml = MapLocal() ml = MapLocal()
with taddons.context(ml) as tctx: with taddons.context(ml) as tctx:
@ -70,7 +100,7 @@ class TestMapLocal:
tctx.configure( tctx.configure(
ml, ml,
map_local=[ map_local=[
"://example.org/images:" + str(tmpdir) "|//example.org/images|" + str(tmpdir)
] ]
) )
f = tflow.tflow() f = tflow.tflow()
@ -83,7 +113,7 @@ class TestMapLocal:
tctx.configure( tctx.configure(
ml, ml,
map_local=[ map_local=[
"://example.org:" + str(tmpdir) "|//example.org|" + str(tmpdir)
] ]
) )
f = tflow.tflow() f = tflow.tflow()
@ -96,10 +126,59 @@ class TestMapLocal:
tctx.configure( tctx.configure(
ml, ml,
map_local=[ map_local=[
":example.org/foo/foo/bar.jpg:" + str(tmpfile) "|example.org/foo/foo/bar.jpg|" + str(tmpfile)
] ]
) )
f = tflow.tflow() f = tflow.tflow()
f.request.url = b"https://example.org/foo/foo/bar.jpg" f.request.url = b"https://example.org/foo/foo/bar.jpg"
ml.request(f) ml.request(f)
assert f.response.content == b"foofoobar" assert f.response.content == b"foofoobar"
@pytest.mark.asyncio
async def test_nonexistent_files(self, tmpdir, monkeypatch):
ml = MapLocal()
with taddons.context(ml) as tctx:
tctx.configure(
ml,
map_local=[
"|example.org/css|" + str(tmpdir)
]
)
f = tflow.tflow()
f.request.url = b"https://example.org/css/nonexistent"
ml.request(f)
assert f.response.status_code == 404
assert await tctx.master.await_log("None of the local file candidates exist")
tmpfile = tmpdir.join("foo.jpg")
tmpfile.write("foo")
tctx.configure(
ml,
map_local=[
"|//example.org/images|" + str(tmpfile)
]
)
tmpfile.remove()
monkeypatch.setattr(Path, "is_file", lambda x: True)
f = tflow.tflow()
f.request.url = b"https://example.org/images/foo.jpg"
ml.request(f)
assert await tctx.master.await_log("could not read file")
def test_has_reply(self, tmpdir):
ml = MapLocal()
with taddons.context(ml) as tctx:
tmpfile = tmpdir.join("foo.jpg")
tmpfile.write("foo")
tctx.configure(
ml,
map_local=[
"|//example.org/images|" + str(tmpfile)
]
)
f = tflow.tflow()
f.request.url = b"https://example.org/images/foo.jpg"
f.kill()
ml.request(f)
assert not f.response

View File

@ -11,13 +11,8 @@ class TestMapRemote:
mr = mapremote.MapRemote() mr = mapremote.MapRemote()
with taddons.context(mr) as tctx: with taddons.context(mr) as tctx:
tctx.configure(mr, map_remote=["one/two/three"]) tctx.configure(mr, map_remote=["one/two/three"])
with pytest.raises(Exception, match="Cannot parse map_remote .* Invalid number"): with pytest.raises(Exception, match="Invalid regular expression"):
tctx.configure(mr, map_remote=["/"])
with pytest.raises(Exception, match="Cannot parse map_remote .* Invalid filter"):
tctx.configure(mr, map_remote=["/~b/two/three"])
with pytest.raises(Exception, match="Cannot parse map_remote .* Invalid regular expression"):
tctx.configure(mr, map_remote=["/foo/+/three"]) tctx.configure(mr, map_remote=["/foo/+/three"])
tctx.configure(mr, map_remote=["/a/b/c/"])
def test_simple(self): def test_simple(self):
mr = mapremote.MapRemote() mr = mapremote.MapRemote()

View File

@ -12,7 +12,6 @@ class TestModifyBody:
tctx.configure(mb, modify_body=["one/two/three"]) tctx.configure(mb, modify_body=["one/two/three"])
with pytest.raises(Exception, match="Cannot parse modify_body"): with pytest.raises(Exception, match="Cannot parse modify_body"):
tctx.configure(mb, modify_body=["/"]) tctx.configure(mb, modify_body=["/"])
tctx.configure(mb, modify_body=["/a/b/c/"])
def test_simple(self): def test_simple(self):
mb = modifybody.ModifyBody() mb = modifybody.ModifyBody()

View File

@ -22,15 +22,6 @@ def test_parse_modify_spec():
assert spec.subject == b"bar" assert spec.subject == b"bar"
assert spec.read_replacement() == b"voing" assert spec.read_replacement() == b"voing"
with pytest.raises(ValueError, match="Invalid number of parameters"):
parse_modify_spec("/", False)
with pytest.raises(ValueError, match="Invalid filter pattern"):
parse_modify_spec("/~b/one/two", False)
with pytest.raises(ValueError, match="Invalid filter pattern"):
parse_modify_spec("/~b/one/two", False)
with pytest.raises(ValueError, match="Invalid regular expression"): with pytest.raises(ValueError, match="Invalid regular expression"):
parse_modify_spec("/[/two", True) parse_modify_spec("/[/two", True)

View File

@ -0,0 +1,20 @@
import pytest
from mitmproxy.utils.spec import parse_spec
def test_parse_spec():
flow_filter, subject, replacement = parse_spec("/foo/bar/voing")
assert flow_filter.pattern == "foo"
assert subject == "bar"
assert replacement == "voing"
flow_filter, subject, replacement = parse_spec("/bar/voing")
assert flow_filter(1) is True
assert subject == "bar"
assert replacement == "voing"
with pytest.raises(ValueError, match="Invalid number of parameters"):
parse_spec("/")
with pytest.raises(ValueError, match="Invalid filter pattern"):
parse_spec("/~b/one/two")