diff options
Diffstat (limited to 'libmproxy')
-rw-r--r-- | libmproxy/proxy.py | 27 | ||||
-rw-r--r-- | libmproxy/resources/bogus_template | 11 | ||||
-rw-r--r-- | libmproxy/utils.py | 171 |
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: |