aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc-src/certinstall/android.html4
-rw-r--r--doc-src/index.py2
-rw-r--r--doc-src/ssl.html17
-rw-r--r--libmproxy/flow.py14
-rw-r--r--libmproxy/proxy.py9
-rw-r--r--libmproxy/version.py2
-rw-r--r--test/data/no_common_name.pem20
-rw-r--r--test/test_server.py25
8 files changed, 83 insertions, 10 deletions
diff --git a/doc-src/certinstall/android.html b/doc-src/certinstall/android.html
index f215d91d..9b0c5d71 100644
--- a/doc-src/certinstall/android.html
+++ b/doc-src/certinstall/android.html
@@ -14,7 +14,7 @@ below - your device may differ, but the broad process should be similar.
## Getting the certificate onto the device
First we need to get the __mitmproxy-ca-cert.cer__ file into the
-__/sdcard/Download__ folder on the device. There are a number of ways to do
+__/sdcard__ folder on the device (/sdcard/Download on older devices). There are a number of ways to do
this. If you have the Android Developer Tools installed, you can use [__adb
push__](http://developer.android.com/tools/help/adb.html) to accomplish this.
Depending on your device, you could also transfer the file using external media
@@ -32,7 +32,7 @@ and select "Install from storage":
<img src="android-settingssecuritymenu.png"/>
-The certificate in /sdcard/Download is automatically located and offered for
+The certificate in /sdcard is automatically located and offered for
installation. Installing the cert will delete the download file from the local
disk:
diff --git a/doc-src/index.py b/doc-src/index.py
index 6880bcae..3333a1b9 100644
--- a/doc-src/index.py
+++ b/doc-src/index.py
@@ -16,7 +16,7 @@ else:
ns.title = countershape.template.Template(None, "<h1>@!this.title!@</h1>")
-this.titlePrefix = "mitmproxy 0.9 - "
+this.titlePrefix = "mitmproxy 0.10 - "
this.markup = markup.Markdown(extras=["footnotes"])
ns.docMaintainer = "Aldo Cortesi"
diff --git a/doc-src/ssl.html b/doc-src/ssl.html
index 68e9a57c..c904cf61 100644
--- a/doc-src/ssl.html
+++ b/doc-src/ssl.html
@@ -34,6 +34,23 @@ testing system or browser to trust the __mitmproxy__ CA as a signing root
authority.
+Using a custom certificate
+--------------------------
+
+You can use your own certificate by passing the __--cert__ option to mitmproxy.
+
+The certificate file is expected to be in the PEM format. You can generate
+a certificate in this format using these instructions:
+
+<pre class="terminal">
+> openssl genrsa -out cert.key 8192
+> openssl req -new -x509 -key cert.key -out cert.crt
+ (Specify the mitm domain as Common Name, e.g. *.google.com)
+> cat cert.key cert.crt > cert.pem
+> mitmproxy --cert=cert.pem
+</pre>
+
+
Installing the mitmproxy CA
---------------------------
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index 96103ddb..44dc57ae 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -288,7 +288,9 @@ class Request(HTTPMsg):
(or None, if request didn't results SSL setup)
"""
- def __init__(self, client_conn, httpversion, host, port, scheme, method, path, headers, content, timestamp_start=None, timestamp_end=None, tcp_setup_timestamp=None, ssl_setup_timestamp=None):
+ def __init__(
+ self, client_conn, httpversion, host, port, scheme, method, path, headers, content, timestamp_start=None,
+ timestamp_end=None, tcp_setup_timestamp=None, ssl_setup_timestamp=None, ip=None):
assert isinstance(headers, ODictCaseless)
self.client_conn = client_conn
self.httpversion = httpversion
@@ -299,6 +301,7 @@ class Request(HTTPMsg):
self.close = False
self.tcp_setup_timestamp = tcp_setup_timestamp
self.ssl_setup_timestamp = ssl_setup_timestamp
+ self.ip = ip
# Have this request's cookies been modified by sticky cookies or auth?
self.stickycookie = False
@@ -364,6 +367,7 @@ class Request(HTTPMsg):
self.timestamp_end = state["timestamp_end"]
self.tcp_setup_timestamp = state["tcp_setup_timestamp"]
self.ssl_setup_timestamp = state["ssl_setup_timestamp"]
+ self.ip = state["ip"]
def _get_state(self):
return dict(
@@ -379,7 +383,8 @@ class Request(HTTPMsg):
timestamp_start = self.timestamp_start,
timestamp_end = self.timestamp_end,
tcp_setup_timestamp = self.tcp_setup_timestamp,
- ssl_setup_timestamp = self.ssl_setup_timestamp
+ ssl_setup_timestamp = self.ssl_setup_timestamp,
+ ip = self.ip
)
@classmethod
@@ -397,7 +402,8 @@ class Request(HTTPMsg):
state["timestamp_start"],
state["timestamp_end"],
state["tcp_setup_timestamp"],
- state["ssl_setup_timestamp"]
+ state["ssl_setup_timestamp"],
+ state["ip"]
)
def __hash__(self):
@@ -729,6 +735,8 @@ class Response(HTTPMsg):
)
if self.content:
headers["Content-Length"] = [str(len(self.content))]
+ elif 'Transfer-Encoding' in self.headers:
+ headers["Content-Length"] = ["0"]
proto = "HTTP/%s.%s %s %s"%(self.httpversion[0], self.httpversion[1], self.code, str(self.msg))
data = (proto, str(headers))
return FMT%data
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py
index 6114922e..3098aff4 100644
--- a/libmproxy/proxy.py
+++ b/libmproxy/proxy.py
@@ -231,6 +231,9 @@ class ProxyHandler(tcp.BaseHandler):
sc.rfile.reset_timestamps()
try:
tsstart = utils.timestamp()
+ peername = sc.connection.getpeername()
+ if peername:
+ request.ip = peername[0]
httpversion, code, msg, headers, content = http.read_response(
sc.rfile,
request.method,
@@ -302,13 +305,15 @@ class ProxyHandler(tcp.BaseHandler):
def find_cert(self, cc, host, port, sni):
if self.config.certfile:
- return certutils.SSLCert.from_pem(file(self.config.certfile, "r").read())
+ with open(self.config.certfile, "rb") as f:
+ return certutils.SSLCert.from_pem(f.read())
else:
sans = []
if not self.config.no_upstream_cert:
conn = self.get_server_connection(cc, "https", host, port, sni)
sans = conn.cert.altnames
- host = conn.cert.cn.decode("utf8").encode("idna")
+ if conn.cert.cn:
+ host = conn.cert.cn.decode("utf8").encode("idna")
ret = self.config.certstore.get_cert(host, sans, self.config.cacert)
if not ret:
raise ProxyError(502, "Unable to generate dummy cert.")
diff --git a/libmproxy/version.py b/libmproxy/version.py
index 02d68411..3140e03a 100644
--- a/libmproxy/version.py
+++ b/libmproxy/version.py
@@ -1,4 +1,4 @@
-IVERSION = (0, 9, 2)
+IVERSION = (0, 10)
VERSION = ".".join(str(i) for i in IVERSION)
NAME = "mitmproxy"
NAMEVERSION = NAME + " " + VERSION
diff --git a/test/data/no_common_name.pem b/test/data/no_common_name.pem
new file mode 100644
index 00000000..fc271a0e
--- /dev/null
+++ b/test/data/no_common_name.pem
@@ -0,0 +1,20 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOQIBAAJBAKVJ43C+8SjOvN9/pP/8HwzmHGQmRvdK/R6KlWdr7He6iiXDQNfH
+RAp+gqX0hBRT80eRjGhSmTTBLCWiXVny4UUCAwEAAQJAUQ8nZ0d85VJd9g2XUaLH
+Z4ACNGtBKk2wTKYSFyIqWZxsF5qhh7HGshJIAP6tYiX8ZW+mMSfme+zsJzWe8ChL
+gQIhAM8QpAgUHnNteZvkv0XqceX1GILEWifMt+hO9yTp4dY5AiEAzFnKr77CKCri
+/DPig4R/5q4KMpMx9EqJufHdGNmIA20CICMARxnufK86RCIr6oEg/hvG8Fu6YRr1
+Kekk3/XnavtRAiBVLVQ7vwKE5aNpRmMzOKZrS736aLpYvjz8IaFr+zgjXQIgdad5
+QZoTD49NTyMEgyZp70gTXcXQLrX2PgQKL4uNmoU=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIBgTCCASugAwIBAgIJAKlcXsPLQAQuMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV
+BAYTAkFVMB4XDTEzMTIxMjAxMzA1NVoXDTE0MDExMTAxMzA1NVowDTELMAkGA1UE
+BhMCQVUwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApUnjcL7xKM6833+k//wfDOYc
+ZCZG90r9HoqVZ2vsd7qKJcNA18dECn6CpfSEFFPzR5GMaFKZNMEsJaJdWfLhRQID
+AQABo24wbDAdBgNVHQ4EFgQUJm8BXcVRsROy0PVt5stkB3eVnEgwPQYDVR0jBDYw
+NIAUJm8BXcVRsROy0PVt5stkB3eVnEihEaQPMA0xCzAJBgNVBAYTAkFVggkAqVxe
+w8tABC4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAHHxcBEpWrIqtLVH
+m6Yn1hgqrAbfMj9IK6zY9C5Cbad/DfUj3AZMb5u758WJK0x9brmckgqdrQsuf9He
+Ef51/SU=
+-----END CERTIFICATE-----
diff --git a/test/test_server.py b/test/test_server.py
index d832ff18..2c94b9df 100644
--- a/test/test_server.py
+++ b/test/test_server.py
@@ -143,7 +143,18 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin):
req = p.request("get:'http://foo':h':foo'='bar'")
assert req.status_code == 400
-
+ def test_empty_chunked_content(self):
+ """
+ https://github.com/mitmproxy/mitmproxy/issues/186
+ """
+ connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ connection.connect(("127.0.0.1", self.proxy.port))
+ spec = '301:h"Transfer-Encoding"="chunked":r:b"0\\r\\n\\r\\n"'
+ connection.send("GET http://localhost:%d/p/%s HTTP/1.1\r\n"%(self.server.port, spec))
+ connection.send("\r\n");
+ resp = connection.recv(50000)
+ connection.close()
+ assert "content-length" in resp.lower()
class TestHTTPAuth(tservers.HTTPProxTest):
authenticator = http_auth.BasicProxyAuth(http_auth.PassManSingleUser("test", "test"), "realm")
@@ -197,6 +208,13 @@ class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin):
def test_certfile(self):
assert self.pathod("304")
+class TestHTTPSNoCommonName(tservers.HTTPProxTest, CommonMixin):
+ """
+ Test what happens if we get a cert without common name back.
+ """
+ ssl = True
+ ssloptions=pathod.SSLOptions(certfile=tutils.test_data.path("data/no_common_name.pem"),
+ keyfile=tutils.test_data.path("data/no_common_name.pem"))
class TestReverse(tservers.ReverseProxTest, CommonMixin):
reverse = True
@@ -289,6 +307,11 @@ class TestProxy(tservers.HTTPProxTest):
assert second_request.tcp_setup_timestamp == None
assert second_request.ssl_setup_timestamp == None
+ def test_request_ip(self):
+ f = self.pathod("200:b@100")
+ assert f.status_code == 200
+ request = self.master.state.view[0].request
+ assert request.ip == "127.0.0.1"
class TestProxySSL(tservers.HTTPProxTest):
ssl=True