aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/console/__init__.py4
-rw-r--r--libmproxy/dump.py7
-rw-r--r--libmproxy/flow.py16
-rw-r--r--libmproxy/proxy.py78
4 files changed, 75 insertions, 30 deletions
diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py
index 2fef5beb..054cc66e 100644
--- a/libmproxy/console/__init__.py
+++ b/libmproxy/console/__init__.py
@@ -949,6 +949,10 @@ class ConsoleMaster(flow.FlowMaster):
self.eventlist.set_focus(len(self.eventlist))
# Handlers
+ def handle_log(self, l):
+ self.add_event(l.msg)
+ l._ack()
+
def handle_error(self, r):
f = flow.FlowMaster.handle_error(self, r)
if f:
diff --git a/libmproxy/dump.py b/libmproxy/dump.py
index 36f54608..a58405ed 100644
--- a/libmproxy/dump.py
+++ b/libmproxy/dump.py
@@ -143,6 +143,11 @@ class DumpMaster(flow.FlowMaster):
def add_event(self, e, level="info"):
if self.eventlog:
print >> self.outfile, e
+ self.outfile.flush()
+
+ def handle_log(self, l):
+ self.add_event(l.msg)
+ l._ack()
def handle_request(self, r):
f = flow.FlowMaster.handle_request(self, r)
@@ -196,6 +201,8 @@ class DumpMaster(flow.FlowMaster):
print >> self.outfile
print >> self.outfile, result
print >> self.outfile, "\n"
+ if self.o.verbosity:
+ self.outfile.flush()
self.state.delete_flow(f)
if self.o.wfile:
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index 4de8bc96..edd10f49 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -637,7 +637,7 @@ class ClientConnect(controller.Msg):
address: (address, port) tuple, or None if the connection is replayed.
requestcount: Number of requests created by this client connection.
close: Is the client connection closed?
- connection_error: Error string or None.
+ error: Error string or None.
"""
def __init__(self, address):
"""
@@ -647,7 +647,7 @@ class ClientConnect(controller.Msg):
self.address = address
self.close = False
self.requestcount = 0
- self.connection_error = None
+ self.error = None
controller.Msg.__init__(self)
def __eq__(self, other):
@@ -655,12 +655,14 @@ class ClientConnect(controller.Msg):
def _load_state(self, state):
self.close = True
+ self.error = state["error"]
self.requestcount = state["requestcount"]
def _get_state(self):
return dict(
address = list(self.address),
requestcount = self.requestcount,
+ error = self.error,
)
@classmethod
@@ -1388,20 +1390,10 @@ class FlowMaster(controller.Master):
def handle_clientconnect(self, cc):
self.run_script_hook("clientconnect", cc)
- self.add_event("Connect from: %s:%s"%cc.address)
cc._ack()
def handle_clientdisconnect(self, r):
self.run_script_hook("clientdisconnect", r)
- s = "Disconnect from: %s:%s"%r.client_conn.address
- self.add_event(s)
- if r.client_conn.requestcount:
- s = " -> handled %s requests"%r.client_conn.requestcount
- self.add_event(s)
- if r.client_conn.connection_error:
- self.add_event(
- " -> error: %s"%r.client_conn.connection_error, "error"
- )
r._ack()
def handle_error(self, r):
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py
index 3ec22fb4..8f7210ca 100644
--- a/libmproxy/proxy.py
+++ b/libmproxy/proxy.py
@@ -16,8 +16,8 @@ import sys, os, string, socket, time
import shutil, tempfile, threading
import optparse, SocketServer
from OpenSSL import SSL
-from netlib import odict, tcp, http, wsgi, certutils
-import utils, flow, version, platform
+from netlib import odict, tcp, http, wsgi, certutils, http_status
+import utils, flow, version, platform, controller
class ProxyError(Exception):
@@ -28,6 +28,13 @@ class ProxyError(Exception):
return "ProxyError(%s, %s)"%(self.code, self.msg)
+class Log(controller.Msg):
+ def __init__(self, msg):
+ controller.Msg.__init__(self)
+ self.msg = msg
+
+
+
class ProxyConfig:
def __init__(self, certfile = None, cacert = None, clientcerts = None, cert_wait_time=0, upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None):
assert not (reverse_proxy and transparent_proxy)
@@ -81,7 +88,10 @@ class ServerConnection(tcp.TCPClient):
path = os.path.join(self.config.clientcerts, self.host) + ".pem"
if os.path.exists(clientcert):
clientcert = path
- self.convert_to_ssl(clientcert=clientcert)
+ try:
+ self.convert_to_ssl(clientcert=clientcert, sni=self.host)
+ except tcp.NetLibError, v:
+ raise ProxyError(400, str(v))
def send(self, request):
self.requestcount += 1
@@ -114,11 +124,18 @@ class ProxyHandler(tcp.BaseHandler):
def handle(self):
cc = flow.ClientConnect(self.client_address)
+ self.log(cc, "connect")
cc._send(self.mqueue)
while self.handle_request(cc) and not cc.close:
pass
cc.close = True
cd = flow.ClientDisconnect(cc)
+
+ self.log(
+ cc, "disconnect",
+ [
+ "handled %s requests"%cc.requestcount]
+ )
cd._send(self.mqueue)
def server_connect(self, scheme, host, port):
@@ -182,17 +199,37 @@ class ProxyHandler(tcp.BaseHandler):
# disconnect.
if http.response_connection_close(response.httpversion, response.headers):
return
- except IOError, v:
- cc.connection_error = v
- except (ProxyError, http.HttpError), e:
- cc.connection_error = "%s: %s"%(e.code, e.msg)
+ except (IOError, ProxyError, http.HttpError), e:
+ if isinstance(e, IOError):
+ cc.error = str(e)
+ else:
+ cc.error = "%s: %s"%(e.code, e.msg)
+
if request:
- err = flow.Error(request, e.msg)
+ err = flow.Error(request, cc.error)
err._send(self.mqueue)
- self.send_error(e.code, e.msg)
+ self.log(
+ cc, cc.error,
+ ["url: %s"%request.get_url()]
+ )
+ else:
+ self.log(cc, cc.error)
+
+ if isinstance(e, ProxyError):
+ self.send_error(e.code, e.msg)
else:
return True
+ def log(self, cc, msg, subs=()):
+ msg = [
+ "%s:%s: "%cc.address + msg
+ ]
+ for i in subs:
+ msg.append(" -> "+i)
+ msg = "\n".join(msg)
+ l = Log(msg)
+ l._send(self.mqueue)
+
def find_cert(self, host, port, sni):
if self.config.certfile:
return self.config.certfile
@@ -226,7 +263,10 @@ class ProxyHandler(tcp.BaseHandler):
if not self.ssl_established and (port in self.config.transparent_proxy["sslports"]):
scheme = "https"
certfile = self.find_cert(host, port, None)
- self.convert_to_ssl(certfile, self.config.certfile or self.config.cacert)
+ try:
+ self.convert_to_ssl(certfile, self.config.certfile or self.config.cacert)
+ except tcp.NetLibError, v:
+ raise ProxyError(400, str(v))
else:
scheme = "http"
host = self.sni or host
@@ -235,7 +275,7 @@ class ProxyHandler(tcp.BaseHandler):
return None
r = http.parse_init_http(line)
if not r:
- raise ProxyError(400, "Bad HTTP request line: %s"%line)
+ raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
method, path, httpversion = r
headers = http.read_headers(self.rfile)
content = http.read_http_body_request(
@@ -249,7 +289,7 @@ class ProxyHandler(tcp.BaseHandler):
scheme, host, port = self.config.reverse_proxy
r = http.parse_init_http(line)
if not r:
- raise ProxyError(400, "Bad HTTP request line: %s"%line)
+ raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
method, path, httpversion = r
headers = http.read_headers(self.rfile)
content = http.read_http_body_request(
@@ -263,7 +303,7 @@ class ProxyHandler(tcp.BaseHandler):
if line.startswith("CONNECT"):
r = http.parse_init_connect(line)
if not r:
- raise ProxyError(400, "Bad HTTP request line: %s"%line)
+ raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
host, port, httpversion = r
# FIXME: Discard additional headers sent to the proxy. Should I expose
# these to users?
@@ -278,14 +318,17 @@ class ProxyHandler(tcp.BaseHandler):
)
self.wfile.flush()
certfile = self.find_cert(host, port, None)
- self.convert_to_ssl(certfile, self.config.certfile or self.config.cacert)
+ try:
+ self.convert_to_ssl(certfile, self.config.certfile or self.config.cacert)
+ except tcp.NetLibError, v:
+ raise ProxyError(400, str(v))
self.proxy_connect_state = (host, port, httpversion)
line = self.rfile.readline(line)
if self.proxy_connect_state:
host, port, httpversion = self.proxy_connect_state
r = http.parse_init_http(line)
if not r:
- raise ProxyError(400, "Bad HTTP request line: %s"%line)
+ raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
method, path, httpversion = r
headers = http.read_headers(self.rfile)
content = http.read_http_body_request(
@@ -295,7 +338,7 @@ class ProxyHandler(tcp.BaseHandler):
else:
r = http.parse_init_proxy(line)
if not r:
- raise ProxyError(400, "Bad HTTP request line: %s"%line)
+ raise ProxyError(400, "Bad HTTP request line: %s"%repr(line))
method, scheme, host, port, path, httpversion = http.parse_init_proxy(line)
headers = http.read_headers(self.rfile)
content = http.read_http_body_request(
@@ -312,8 +355,7 @@ class ProxyHandler(tcp.BaseHandler):
def send_error(self, code, body):
try:
- import BaseHTTPServer
- response = BaseHTTPServer.BaseHTTPRequestHandler.responses[code][0]
+ response = http_status.RESPONSES.get(code, "Unknown")
self.wfile.write("HTTP/1.1 %s %s\r\n" % (code, response))
self.wfile.write("Server: %s\r\n"%version.NAMEVERSION)
self.wfile.write("Connection: close\r\n")