aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/proxy.py27
-rw-r--r--libmproxy/resources/bogus_template11
-rw-r--r--libmproxy/utils.py171
3 files changed, 175 insertions, 34 deletions
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py
index f3ea2ed2..8200c725 100644
--- a/libmproxy/proxy.py
+++ b/libmproxy/proxy.py
@@ -22,9 +22,11 @@ class ProxyError(Exception):
class Config:
- def __init__(self, pemfile, ciphers = None):
- self.pemfile = pemfile
+ def __init__(self, certfile = None, certpath = None, ciphers = None, cacert = None):
+ self.certfile = certfile
+ self.certpath = certpath
self.ciphers = ciphers
+ self.cacert = cacert
def read_chunked(fp):
@@ -495,6 +497,23 @@ class ProxyHandler(SocketServer.StreamRequestHandler):
if server:
server.terminate()
+ def find_cert(self, host, port=443):
+ #return config.certpath + "/" + host + ":" + port + ".pem"
+ if config.certpath is not None:
+ cert = config.certpath + "/" + host + ".pem"
+ if not os.path.exists(cert) and config.cacert is not None:
+ utils.make_bogus_cert(cert, ca=config.cacert, commonName=host)
+ if os.path.exists(cert):
+ return cert
+ print >> sys.stderr, "WARNING: Certificate missing for %s:%d! (%s)\n" % (host, port, cert)
+ return config.certfile
+
+ def find_key(self, host, port=443):
+ if config.cacert is not None:
+ return config.cacert
+ else:
+ return config.certfile
+
def read_request(self, client_conn):
line = self.rfile.readline()
if line == "\r\n" or line == "\n": # Possible leftover from previous message
@@ -517,8 +536,8 @@ class ProxyHandler(SocketServer.StreamRequestHandler):
self.wfile.flush()
self.connection = ssl.wrap_socket(
self.connection,
- certfile = config.pemfile,
- keyfile = config.pemfile,
+ certfile = self.find_cert(host,port),
+ keyfile = self.find_key(host,port),
server_side = True,
ssl_version = ssl.PROTOCOL_SSLv23,
ciphers = config.ciphers,
diff --git a/libmproxy/resources/bogus_template b/libmproxy/resources/bogus_template
deleted file mode 100644
index afa7281c..00000000
--- a/libmproxy/resources/bogus_template
+++ /dev/null
@@ -1,11 +0,0 @@
-[ req ]
-prompt = no
-distinguished_name = req_distinguished_name
-
-[ req_distinguished_name ]
-C = NZ
-ST = none
-L = none
-O = none
-OU = none
-emailAddress = none
diff --git a/libmproxy/utils.py b/libmproxy/utils.py
index 87fca5ce..39279e04 100644
--- a/libmproxy/utils.py
+++ b/libmproxy/utils.py
@@ -14,7 +14,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re, os, subprocess, datetime, textwrap, errno
-
def format_timestamp(s):
d = datetime.datetime.fromtimestamp(s)
return d.strftime("%Y-%m-%d %H:%M:%S")
@@ -314,32 +313,166 @@ class Data:
data = Data(__name__)
-def make_bogus_cert(path):
+def make_openssl_conf(path, countryName=None, stateOrProvinceName=None, localityName=None, organizationName=None, organizationalUnitName=None, commonName=None, emailAddress=None, ca=False):
+ cnf = open(path, "w")
+ cnf.write("[ req ]\n")
+ cnf.write("prompt = no\n")
+ cnf.write("distinguished_name = req_distinguished_name\n")
+ if ca:
+ cnf.write("x509_extensions = v3_ca # The extentions to add to the self signed cert\n")
+ cnf.write("\n")
+ cnf.write("[ req_distinguished_name ]\n")
+ if countryName is not None:
+ cnf.write("countryName = %s\n" % (countryName) )
+ cnf.write("stateOrProvinceName = %s\n" % (stateOrProvinceName) )
+ cnf.write("localityName = %s\n" % (localityName) )
+ cnf.write("organizationName = %s\n" % (organizationName) )
+ cnf.write("organizationalUnitName = %s\n" % (organizationalUnitName) )
+ cnf.write("commonName = %s\n" % (commonName) )
+ cnf.write("emailAddress = %s\n" % (emailAddress) )
+ cnf.write("\n")
+ cnf.write("[ v3_ca ]\n")
+ cnf.write("subjectKeyIdentifier=hash\n")
+ cnf.write("authorityKeyIdentifier=keyid:always,issuer\n")
+ if ca:
+ cnf.write("basicConstraints = critical,CA:true\n")
+ cnf.write("keyUsage = cRLSign, keyCertSign\n")
+ #cnf.write("nsCertType = sslCA, emailCA\n")
+ #cnf.write("subjectAltName=email:copy\n")
+ #cnf.write("issuerAltName=issuer:copy\n")
+
+def make_bogus_cert(certpath, countryName=None, stateOrProvinceName=None, localityName=None, organizationName="mitmproxy", organizationalUnitName=None, commonName="Dummy Certificate", emailAddress=None, ca=None, newca=False):
# Generates a bogus certificate like so:
# openssl req -config template -x509 -nodes -days 9999 -newkey rsa:1024 \
# -keyout cert.pem -out cert.pem
+ (path, ext) = os.path.splitext(certpath)
d = os.path.dirname(path)
if not os.path.exists(d):
os.makedirs(d)
- cmd = [
- "openssl",
- "req",
- "-config", data.path("resources/bogus_template"),
- "-x509" ,
- "-nodes",
- "-days", "9999",
- "-newkey", "rsa:1024",
- "-keyout", path,
- "-out", path,
- ]
- subprocess.call(
- cmd,
- stderr=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stdin=subprocess.PIPE
- )
+ cnf = open(path+".cnf", "w")
+ cnf.write("[ req ]\n")
+ cnf.write("prompt = no\n")
+ cnf.write("distinguished_name = req_distinguished_name\n")
+ if newca:
+ cnf.write("x509_extensions = v3_ca\n")
+ cnf.write("req_extensions = v3_ca_req\n")
+ else:
+ cnf.write("x509_extensions = v3_cert\n")
+ cnf.write("req_extensions = v3_cert_req\n")
+ cnf.write("\n")
+ cnf.write("[ req_distinguished_name ]\n")
+ if countryName is not None:
+ cnf.write("countryName = %s\n" % (countryName) )
+ if stateOrProvinceName is not None:
+ cnf.write("stateOrProvinceName = %s\n" % (stateOrProvinceName) )
+ if localityName is not None:
+ cnf.write("localityName = %s\n" % (localityName) )
+ if organizationName is not None:
+ cnf.write("organizationName = %s\n" % (organizationName) )
+ if organizationalUnitName is not None:
+ cnf.write("organizationalUnitName = %s\n" % (organizationalUnitName) )
+ if commonName is not None:
+ cnf.write("commonName = %s\n" % (commonName) )
+ if emailAddress is not None:
+ cnf.write("emailAddress = %s\n" % (emailAddress) )
+ cnf.write("\n")
+ cnf.write("[ v3_ca ]\n")
+ cnf.write("subjectKeyIdentifier=hash\n")
+ cnf.write("authorityKeyIdentifier=keyid:always,issuer\n")
+ cnf.write("basicConstraints = critical,CA:true\n")
+ cnf.write("keyUsage = cRLSign, keyCertSign\n")
+ cnf.write("nsCertType = sslCA\n")
+ #cnf.write("subjectAltName=email:copy\n")
+ #cnf.write("issuerAltName=issuer:copy\n")
+ cnf.write("\n")
+ cnf.write("[ v3_ca_req ]\n")
+ cnf.write("basicConstraints = critical,CA:true\n")
+ cnf.write("keyUsage = cRLSign, keyCertSign\n")
+ cnf.write("nsCertType = sslCA\n")
+ #cnf.write("subjectAltName=email:copy\n")
+ cnf.write("\n")
+ cnf.write("[ v3_cert ]\n")
+ cnf.write("basicConstraints = CA:false\n")
+ cnf.write("keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n")
+ cnf.write("nsCertType = server\n")
+ cnf.write("subjectKeyIdentifier=hash\n")
+ cnf.write("authorityKeyIdentifier=keyid:always,issuer\n")
+ cnf.write("\n")
+ cnf.write("[ v3_cert_req ]\n")
+ cnf.write("basicConstraints = CA:false\n")
+ cnf.write("keyUsage = nonRepudiation, digitalSignature, keyEncipherment\n")
+ cnf.write("nsCertType = server\n")
+ cnf.write("\n")
+
+ cnf.close()
+
+ if ca is None:
+ # Create a new selfsigned certificate + key
+ cmd = [
+ "openssl",
+ "req",
+ "-new",
+ "-x509",
+ "-config", path+".cnf",
+ "-nodes",
+ "-days", "9999",
+ "-out", certpath,
+ "-newkey", "rsa:1024",
+ "-keyout", certpath,
+ ]
+ #print " ".join(cmd)
+ subprocess.call(
+ cmd,
+ stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE
+ )
+ else:
+ # Create a dummy signed certificate. Uses same key as the signing CA
+ cmd = [
+ "openssl",
+ "req",
+ "-new",
+ "-config", path+".cnf",
+ "-out", path+".req",
+ "-key", ca,
+ ]
+ #print " ".join(cmd)
+ subprocess.call(
+ cmd,
+ stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE
+ )
+ cmd = [
+ "openssl",
+ "x509",
+ "-req",
+ "-in", path+".req",
+ "-days", "9999",
+ "-out", certpath,
+ "-CA", ca,
+ "-CAcreateserial",
+ "-extfile", path+".cnf"
+ ]
+ if newca:
+ cmd.extend([
+ "-extensions", "v3_ca",
+ ])
+ else:
+ cmd.extend([
+ "-extensions", "v3_cert",
+ ])
+
+ #print " ".join(cmd)
+ subprocess.call(
+ cmd,
+ stderr=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE
+ )
def mkdir_p(path):
try: