aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy/filt.py
diff options
context:
space:
mode:
Diffstat (limited to 'mitmproxy/filt.py')
-rw-r--r--mitmproxy/filt.py118
1 files changed, 92 insertions, 26 deletions
diff --git a/mitmproxy/filt.py b/mitmproxy/filt.py
index a42988f1..8b647b22 100644
--- a/mitmproxy/filt.py
+++ b/mitmproxy/filt.py
@@ -35,11 +35,26 @@ from __future__ import absolute_import, print_function, division
import re
import sys
+import functools
+
+from mitmproxy.models.http import HTTPFlow
+from mitmproxy.models.tcp import TCPFlow
from netlib import strutils
import pyparsing as pp
+def only(*types):
+ def decorator(fn):
+ @functools.wraps(fn)
+ def filter_types(self, flow):
+ if isinstance(flow, types):
+ return fn(self, flow)
+ return False
+ return filter_types
+ return decorator
+
+
class _Token(object):
def dump(self, indent=0, fp=sys.stdout):
@@ -65,10 +80,29 @@ class FErr(_Action):
return True if f.error else False
+class FHTTP(_Action):
+ code = "http"
+ help = "Match HTTP flows"
+
+ @only(HTTPFlow)
+ def __call__(self, f):
+ return True
+
+
+class FTCP(_Action):
+ code = "tcp"
+ help = "Match TCP flows"
+
+ @only(TCPFlow)
+ def __call__(self, f):
+ return True
+
+
class FReq(_Action):
code = "q"
help = "Match request with no response"
+ @only(HTTPFlow)
def __call__(self, f):
if not f.response:
return True
@@ -78,6 +112,7 @@ class FResp(_Action):
code = "s"
help = "Match response"
+ @only(HTTPFlow)
def __call__(self, f):
return bool(f.response)
@@ -117,6 +152,7 @@ class FAsset(_Action):
]
ASSET_TYPES = [re.compile(x) for x in ASSET_TYPES]
+ @only(HTTPFlow)
def __call__(self, f):
if f.response:
for i in self.ASSET_TYPES:
@@ -129,6 +165,7 @@ class FContentType(_Rex):
code = "t"
help = "Content-type header"
+ @only(HTTPFlow)
def __call__(self, f):
if _check_content_type(self.re, f.request):
return True
@@ -137,18 +174,20 @@ class FContentType(_Rex):
return False
-class FRequestContentType(_Rex):
+class FContentTypeRequest(_Rex):
code = "tq"
help = "Request Content-Type header"
+ @only(HTTPFlow)
def __call__(self, f):
return _check_content_type(self.re, f.request)
-class FResponseContentType(_Rex):
+class FContentTypeResponse(_Rex):
code = "ts"
help = "Response Content-Type header"
+ @only(HTTPFlow)
def __call__(self, f):
if f.response:
return _check_content_type(self.re, f.response)
@@ -160,6 +199,7 @@ class FHead(_Rex):
help = "Header"
flags = re.MULTILINE
+ @only(HTTPFlow)
def __call__(self, f):
if f.request and self.re.search(bytes(f.request.headers)):
return True
@@ -173,6 +213,7 @@ class FHeadRequest(_Rex):
help = "Request header"
flags = re.MULTILINE
+ @only(HTTPFlow)
def __call__(self, f):
if f.request and self.re.search(bytes(f.request.headers)):
return True
@@ -183,6 +224,7 @@ class FHeadResponse(_Rex):
help = "Response header"
flags = re.MULTILINE
+ @only(HTTPFlow)
def __call__(self, f):
if f.response and self.re.search(bytes(f.response.headers)):
return True
@@ -192,13 +234,19 @@ class FBod(_Rex):
code = "b"
help = "Body"
+ @only(HTTPFlow, TCPFlow)
def __call__(self, f):
- if f.request and f.request.raw_content:
- if self.re.search(f.request.get_content(strict=False)):
- return True
- if f.response and f.response.raw_content:
- if self.re.search(f.response.get_content(strict=False)):
- return True
+ if isinstance(f, HTTPFlow):
+ if f.request and f.request.raw_content:
+ if self.re.search(f.request.get_content(strict=False)):
+ return True
+ if f.response and f.response.raw_content:
+ if self.re.search(f.response.get_content(strict=False)):
+ return True
+ elif isinstance(f, TCPFlow):
+ for msg in f.messages:
+ if self.re.search(msg.content):
+ return True
return False
@@ -206,20 +254,32 @@ class FBodRequest(_Rex):
code = "bq"
help = "Request body"
+ @only(HTTPFlow, TCPFlow)
def __call__(self, f):
- if f.request and f.request.raw_content:
- if self.re.search(f.request.get_content(strict=False)):
- return True
+ if isinstance(f, HTTPFlow):
+ if f.request and f.request.raw_content:
+ if self.re.search(f.request.get_content(strict=False)):
+ return True
+ elif isinstance(f, TCPFlow):
+ for msg in f.messages:
+ if msg.from_client and self.re.search(msg.content):
+ return True
class FBodResponse(_Rex):
code = "bs"
help = "Response body"
+ @only(HTTPFlow, TCPFlow)
def __call__(self, f):
- if f.response and f.response.raw_content:
- if self.re.search(f.response.get_content(strict=False)):
- return True
+ if isinstance(f, HTTPFlow):
+ if f.response and f.response.raw_content:
+ if self.re.search(f.response.get_content(strict=False)):
+ return True
+ elif isinstance(f, TCPFlow):
+ for msg in f.messages:
+ if not msg.from_client and self.re.search(msg.content):
+ return True
class FMethod(_Rex):
@@ -227,6 +287,7 @@ class FMethod(_Rex):
help = "Method"
flags = re.IGNORECASE
+ @only(HTTPFlow)
def __call__(self, f):
return bool(self.re.search(f.request.data.method))
@@ -236,6 +297,7 @@ class FDomain(_Rex):
help = "Domain"
flags = re.IGNORECASE
+ @only(HTTPFlow)
def __call__(self, f):
return bool(self.re.search(f.request.data.host))
@@ -252,6 +314,7 @@ class FUrl(_Rex):
toks = toks[1:]
return klass(*toks)
+ @only(HTTPFlow)
def __call__(self, f):
return self.re.search(f.request.url)
@@ -284,6 +347,7 @@ class FCode(_Int):
code = "c"
help = "HTTP response code"
+ @only(HTTPFlow)
def __call__(self, f):
if f.response and f.response.status_code == self.num:
return True
@@ -331,26 +395,28 @@ class FNot(_Token):
filt_unary = [
+ FAsset,
+ FErr,
+ FHTTP,
FReq,
FResp,
- FAsset,
- FErr
+ FTCP,
]
filt_rex = [
- FHeadRequest,
- FHeadResponse,
- FHead,
+ FBod,
FBodRequest,
FBodResponse,
- FBod,
- FMethod,
- FDomain,
- FUrl,
- FRequestContentType,
- FResponseContentType,
FContentType,
- FSrc,
+ FContentTypeRequest,
+ FContentTypeResponse,
+ FDomain,
FDst,
+ FHead,
+ FHeadRequest,
+ FHeadResponse,
+ FMethod,
+ FSrc,
+ FUrl,
]
filt_int = [
FCode