diff options
| author | Henrik Nordstrom <henrik@henriknordstrom.net> | 2011-02-08 18:00:59 +0100 | 
|---|---|---|
| committer | Henrik Nordstrom <henrik@henriknordstrom.net> | 2011-02-10 02:59:51 +0100 | 
| commit | 32adee8743526875c894007c89a988a19d12109f (patch) | |
| tree | 33b6233040ef6c388e121de51a03f83b2a91c2b1 | |
| parent | 4ffaadd4355e943d7fa46f3050a1fb780f4d261d (diff) | |
| download | mitmproxy-32adee8743526875c894007c89a988a19d12109f.tar.gz mitmproxy-32adee8743526875c894007c89a988a19d12109f.tar.bz2 mitmproxy-32adee8743526875c894007c89a988a19d12109f.zip | |
Implement a dummy CA
| -rw-r--r-- | libmproxy/proxy.py | 27 | ||||
| -rw-r--r-- | libmproxy/resources/bogus_template | 11 | ||||
| -rw-r--r-- | libmproxy/utils.py | 171 | ||||
| -rwxr-xr-x | mitmdump | 25 | ||||
| -rwxr-xr-x | mitmplayback | 42 | ||||
| -rwxr-xr-x | mitmproxy | 42 | ||||
| -rwxr-xr-x | mitmrecord | 42 | 
7 files changed, 294 insertions, 66 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: @@ -27,11 +27,21 @@ if __name__ == '__main__':                  version="%%prog %s"%VERSION,              )      parser.add_option( -        "-c", "--cert", action="store", -        type = "str", dest="cert", default="~/.mitmproxy/cert.pem", +        "--cert", action="store", +        type = "str", dest="cert", default="~/.mitmproxy/default.pem",          help = "SSL certificate file."      )      parser.add_option( +        "-c", "--cacert", action="store", +        type = "str", dest="cacert", default="~/.mitmproxy/ca.pem", +        help = "SSL CA certificate file." +    ) +    parser.add_option( +        "--certpath", action="store", +        type = "str", dest="certpath", default="~/.mitmproxy/", +        help = "SSL certificate store path." +    ) +    parser.add_option(          "--ciphers", action="store",          type = "str", dest="ciphers", default=None,          help = "SSL ciphers." @@ -52,14 +62,17 @@ if __name__ == '__main__':      if options.quiet:          options.verbose = 0 -    certpath = os.path.expanduser(options.cert) +    options.cert = os.path.expanduser(options.cert) +    options.certpath = os.path.expanduser(options.certpath) -    if not os.path.exists(certpath): +    if not os.path.exists(options.cert):          print >> sys.stderr, "Creating bogus certificate at %s"%options.cert -        utils.make_bogus_cert(certpath) +        utils.make_bogus_cert(options.cert)      proxy.config = proxy.Config( -        certpath, +        certfile = options.cert, +        certpath = options.certpath, +        cacert   = options.cacert,          ciphers = options.ciphers      )      server = proxy.ProxyServer(options.port) diff --git a/mitmplayback b/mitmplayback index eb147cd9..9d4fe11a 100755 --- a/mitmplayback +++ b/mitmplayback @@ -31,12 +31,24 @@ if __name__ == '__main__':              )      parser.add_option( -        "-c", "--cert", action="store", -        type = "str", dest="cert", default="~/.mitmproxy/cert.pem", +        "--cert", action="store", +        type = "str", dest="cert", default="~/.mitmproxy/default.pem",          help = "SSL certificate file."      )      parser.add_option( +        "-c", "--cacert", action="store", +        type = "str", dest="cacert", default="~/.mitmproxy/ca.pem", +        help = "SSL CA certificate file." +    ) + +    parser.add_option( +        "--certpath", action="store", +        type = "str", dest="certpath", default=None, +        help = "SSL certificate store path." +    ) + +    parser.add_option(          "--ciphers", action="store",          type = "str", dest="ciphers", default=None,          help = "SSL ciphers." @@ -66,15 +78,27 @@ if __name__ == '__main__':      if options.quiet:          options.verbose = 0 -    certpath = os.path.expanduser(options.cert) -    options.cache = os.path.expanduser(options.cache) +    if options.cert is not None: +        options.cert = os.path.expanduser(options.cert) +        if not os.path.exists(options.cert): +            print >> sys.stderr, "Creating bogus certificate at %s"%options.cert +            utils.make_bogus_cert(options.cert) +    if options.cacert is not None: +        options.cacert = os.path.expanduser(options.cacert) +        if not os.path.exists(options.cacert): +            print >> sys.stderr, "Creating bogus CA certificate at %s"%options.cacert +            utils.make_bogus_cert(options.cacert, newca=True, commonName="Dummy CA") +    if options.certpath is not None: +        options.certpath = os.path.expanduser(options.certpath) +    elif options.cacert is not None: +        options.certpath = os.path.dirname(options.cacert) +    if options.cache is not None: +        options.cache = os.path.expanduser(options.cache) -    if not os.path.exists(certpath): -        print >> sys.stderr, "Creating bogus certificate at %s"%options.cert -        utils.make_bogus_cert(certpath) -      proxy.config = proxy.Config( -        certpath, +        certfile = options.cert, +        certpath = options.certpath, +        cacert   = options.cacert,          ciphers = options.ciphers      )      server = proxy.ProxyServer(options.port) @@ -34,12 +34,24 @@ if __name__ == '__main__':      )      parser.add_option( -        "-c", "--cert", action="store", -        type = "str", dest="cert", default="~/.mitmproxy/cert.pem", +        "--cert", action="store", +        type = "str", dest="cert", default="~/.mitmproxy/default.pem",          help = "SSL certificate file."      )      parser.add_option( +        "-c", "--cacert", action="store", +        type = "str", dest="cacert", default="~/.mitmproxy/ca.pem", +        help = "SSL CA certificate file." +    ) + +    parser.add_option( +        "--certpath", action="store", +        type = "str", dest="certpath", default="~/.mitmproxy/", +        help = "SSL certificate store path." +    ) + +    parser.add_option(          "--ciphers", action="store",          type = "str", dest="ciphers", default=None,          help = "SSL ciphers." @@ -96,14 +108,28 @@ if __name__ == '__main__':      parser.add_option_group(group)      options, args = parser.parse_args() -    certpath = os.path.expanduser(options.cert) -     -    if not os.path.exists(certpath): -        print >> sys.stderr, "Creating bogus certificate at %s"%options.cert -        utils.make_bogus_cert(certpath) + +    if options.cert is not None: +        options.cert = os.path.expanduser(options.cert) +        if not os.path.exists(options.cert): +            print >> sys.stderr, "Creating bogus certificate at %s"%options.cert +            utils.make_bogus_cert(options.cert) +    if options.cacert is not None: +        options.cacert = os.path.expanduser(options.cacert) +        if not os.path.exists(options.cacert): +            print >> sys.stderr, "Creating bogus CA certificate at %s"%options.cacert +            utils.make_bogus_cert(options.cacert, newca=True, commonName="Dummy CA") +    if options.certpath is not None: +        options.certpath = os.path.expanduser(options.certpath) +    elif options.cacert is not None: +        options.certpath = os.path.dirname(options.cacert) +    if options.cache is not None: +        options.cache = os.path.expanduser(options.cache)      proxy.config = proxy.Config( -        certpath, +        certfile = options.cert, +        certpath = options.certpath, +        cacert   = options.cacert,          ciphers = options.ciphers      )      if options.cache is not None: @@ -30,12 +30,24 @@ if __name__ == '__main__':              )      parser.add_option( -        "-c", "--cert", action="store", -        type = "str", dest="cert", default="~/.mitmproxy/cert.pem", +        "--cert", action="store", +        type = "str", dest="cert", default="~/.mitmproxy/default.pem",          help = "SSL certificate file."      )      parser.add_option( +        "-c", "--cacert", action="store", +        type = "str", dest="cacert", default="~/.mitmproxy/ca.pem", +        help = "SSL CA certificate file." +    ) + +    parser.add_option( +        "--certpath", action="store", +        type = "str", dest="certpath", default=None, +        help = "SSL certificate store path." +    ) + +    parser.add_option(          "--ciphers", action="store",          type = "str", dest="ciphers", default=None,          help = "SSL ciphers." @@ -71,15 +83,27 @@ if __name__ == '__main__':      if options.quiet:          options.verbose = 0 -    certpath = os.path.expanduser(options.cert) -    options.cache = os.path.expanduser(options.cache) -     -    if not os.path.exists(certpath): -        print >> sys.stderr, "Creating bogus certificate at %s"%options.cert -        utils.make_bogus_cert(certpath) +    if options.cert is not None: +        options.cert = os.path.expanduser(options.cert) +        if not os.path.exists(options.cert): +            print >> sys.stderr, "Creating bogus certificate at %s"%options.cert +            utils.make_bogus_cert(options.cert) +    if options.cacert is not None: +        options.cacert = os.path.expanduser(options.cacert) +        if not os.path.exists(options.cacert): +            print >> sys.stderr, "Creating bogus CA certificate at %s"%options.cacert +            utils.make_bogus_cert(options.cacert, newca=True, commonName="Dummy CA") +    if options.certpath is not None: +        options.certpath = os.path.expanduser(options.certpath) +    elif options.cacert is not None: +        options.certpath = os.path.dirname(options.cacert) +    if options.cache is not None: +        options.cache = os.path.expanduser(options.cache)      proxy.config = proxy.Config( -        certpath, +        certfile = options.cert, +        certpath = options.certpath, +        cacert   = options.cacert,          ciphers = options.ciphers      )      server = proxy.ProxyServer(options.port) | 
