Ejemplo n.º 1
0
    def test_ignore(self):
        n = self.pathod("304")
        self._ignore_on()
        i = self.pathod("305")
        i2 = self.pathod("306")
        self._ignore_off()

        self.master.event_queue.join()

        assert n.status_code == 304
        assert i.status_code == 305
        assert i2.status_code == 306
        assert any(f.response.status_code == 304 for f in self.master.state.flows)
        assert not any(f.response.status_code == 305 for f in self.master.state.flows)
        assert not any(f.response.status_code == 306 for f in self.master.state.flows)

        # Test that we get the original SSL cert
        if self.ssl:
            i_cert = certs.SSLCert(i.sslinfo.certchain[0])
            i2_cert = certs.SSLCert(i2.sslinfo.certchain[0])
            n_cert = certs.SSLCert(n.sslinfo.certchain[0])

            assert i_cert == i2_cert
            assert i_cert != n_cert

        # Test Non-HTTP traffic
        spec = "200:i0,@100:d0"  # this results in just 100 random bytes
        # mitmproxy responds with bad gateway
        assert self.pathod(spec).status_code == 502
        self._ignore_on()
        with tutils.raises(exceptions.HttpException):
            self.pathod(spec)  # pathoc tries to parse answer as HTTP

        self._ignore_off()
Ejemplo n.º 2
0
    def test_tcp(self):
        n = self.pathod("304")
        self._tcpproxy_on()
        i = self.pathod("305")
        i2 = self.pathod("306")
        self._tcpproxy_off()

        self.master.event_queue.join()

        assert n.status_code == 304
        assert i.status_code == 305
        assert i2.status_code == 306
        assert any(f.response.status_code == 304
                   for f in self.master.state.flows
                   if isinstance(f, http.HTTPFlow))
        assert not any(f.response.status_code == 305
                       for f in self.master.state.flows
                       if isinstance(f, http.HTTPFlow))
        assert not any(f.response.status_code == 306
                       for f in self.master.state.flows
                       if isinstance(f, http.HTTPFlow))

        # Test that we get the original SSL cert
        if self.ssl:
            i_cert = certs.SSLCert(i.sslinfo.certchain[0])
            i2_cert = certs.SSLCert(i2.sslinfo.certchain[0])
            n_cert = certs.SSLCert(n.sslinfo.certchain[0])

            assert i_cert == i2_cert == n_cert
Ejemplo n.º 3
0
    def convert_to_ssl(self, sni=None, alpn_protos=None, **sslctx_kwargs):
        context = tls.create_client_context(alpn_protos=alpn_protos,
                                            sni=sni,
                                            **sslctx_kwargs)
        self.connection = SSL.Connection(context, self.connection)
        if sni:
            self.sni = sni
            self.connection.set_tlsext_host_name(sni.encode("idna"))
        self.connection.set_connect_state()
        try:
            self.connection.do_handshake()
        except SSL.Error as v:
            if self.ssl_verification_error:
                raise self.ssl_verification_error
            else:
                raise exceptions.TlsException("SSL handshake error: %s" %
                                              repr(v))

        self.cert = certs.SSLCert(self.connection.get_peer_certificate())

        # Keep all server certificates in a list
        for i in self.connection.get_peer_cert_chain():
            self.server_certs.append(certs.SSLCert(i))

        self.ssl_established = True
        self.rfile.set_descriptor(self.connection)
        self.wfile.set_descriptor(self.connection)
Ejemplo n.º 4
0
    def test_state(self):
        with open(tutils.test_data.path("mitmproxy/net/data/text_cert"), "rb") as f:
            d = f.read()
        c = certs.SSLCert.from_pem(d)

        c.get_state()
        c2 = c.copy()
        a = c.get_state()
        b = c2.get_state()
        assert a == b
        assert c == c2
        assert c is not c2

        x = certs.SSLCert('')
        x.set_state(a)
        assert x == c
    def verify_callback(conn: SSL.Connection, x509: SSL.X509, errno: int,
                        depth: int, is_cert_verified: bool) -> bool:
        if is_cert_verified and depth == 0:
            # Verify hostname of leaf certificate.
            cert = certs.SSLCert(x509)
            try:
                crt = dict(subjectAltName=[
                    ("DNS", x.decode("ascii", "strict")) for x in cert.altnames
                ])  # type: typing.Dict[str, typing.Any]
                if cert.cn:
                    crt["subject"] = [[[
                        "commonName",
                        cert.cn.decode("ascii", "strict")
                    ]]]
                if sni:
                    # SNI hostnames allow support of IDN by using ASCII-Compatible Encoding
                    # Conversion algorithm is in RFC 3490 which is implemented by idna codec
                    # https://docs.python.org/3/library/codecs.html#text-encodings
                    # https://tools.ietf.org/html/rfc6066#section-3
                    # https://tools.ietf.org/html/rfc4985#section-3
                    hostname = sni.encode("idna").decode("ascii")
                else:
                    hostname = "no-hostname"
                match_hostname(crt, hostname)
            except (ValueError, CertificateError) as e:
                conn.cert_error = exceptions.InvalidCertificateException(
                    "Certificate verification error for {}: {}".format(
                        sni or repr(address), str(e)))
                is_cert_verified = False
        elif is_cert_verified:
            pass
        else:
            conn.cert_error = exceptions.InvalidCertificateException(
                "Certificate verification error for {}: {} (errno: {}, depth: {})"
                .format(
                    sni,
                    SSL._ffi.string(
                        SSL._lib.X509_verify_cert_error_string(
                            errno)).decode(), errno, depth))

        # SSL_VERIFY_NONE: The handshake will be continued regardless of the verification result.
        return is_cert_verified
Ejemplo n.º 6
0
 def __str__(self):
     parts = [
         "Application Layer Protocol: %s" % strutils.always_str(self.alp, "utf8"),
         "Cipher: %s, %s bit, %s" % self.cipher,
         "SSL certificate chain:"
     ]
     for n, i in enumerate(self.certchain):
         parts.append("  Certificate [%s]" % n)
         parts.append("\tSubject: ")
         for cn in i.get_subject().get_components():
             parts.append("\t\t%s=%s" % (
                 strutils.always_str(cn[0], "utf8"),
                 strutils.always_str(cn[1], "utf8"))
             )
         parts.append("\tIssuer: ")
         for cn in i.get_issuer().get_components():
             parts.append("\t\t%s=%s" % (
                 strutils.always_str(cn[0], "utf8"),
                 strutils.always_str(cn[1], "utf8"))
             )
         parts.extend(
             [
                 "\tVersion: %s" % i.get_version(),
                 "\tValidity: %s - %s" % (
                     strutils.always_str(i.get_notBefore(), "utf8"),
                     strutils.always_str(i.get_notAfter(), "utf8")
                 ),
                 "\tSerial: %s" % i.get_serial_number(),
                 "\tAlgorithm: %s" % strutils.always_str(i.get_signature_algorithm(), "utf8")
             ]
         )
         pk = i.get_pubkey()
         types = {
             OpenSSL.crypto.TYPE_RSA: "RSA",
             OpenSSL.crypto.TYPE_DSA: "DSA"
         }
         t = types.get(pk.type(), "Uknown")
         parts.append("\tPubkey: %s bit %s" % (pk.bits(), t))
         s = certs.SSLCert(i)
         if s.altnames:
             parts.append("\tSANs: %s" % " ".join(strutils.always_str(n, "utf8") for n in s.altnames))
     return "\n".join(parts)
Ejemplo n.º 7
0
    def convert_to_ssl(self, cert, key, **sslctx_kwargs):
        """
        Convert connection to SSL.
        For a list of parameters, see tls.create_server_context(...)
        """

        context = tls.create_server_context(cert=cert,
                                            key=key,
                                            **sslctx_kwargs)
        self.connection = SSL.Connection(context, self.connection)
        self.connection.set_accept_state()
        try:
            self.connection.do_handshake()
        except SSL.Error as v:
            raise exceptions.TlsException("SSL handshake error: %s" % repr(v))
        self.ssl_established = True
        cert = self.connection.get_peer_certificate()
        if cert:
            self.clientcert = certs.SSLCert(cert)
        self.rfile.set_descriptor(self.connection)
        self.wfile.set_descriptor(self.connection)
Ejemplo n.º 8
0
 def save_cert(conn_, cert, errno_, depth_, preverify_ok_):
     self.clientcert = certs.SSLCert(cert)
     # Return true to prevent cert verification error
     return True
Ejemplo n.º 9
0
    def convert_to_ssl(self, sni=None, alpn_protos=None, **sslctx_kwargs):
        """
            cert: Path to a file containing both client cert and private key.

            options: A bit field consisting of OpenSSL.SSL.OP_* values
            verify_options: A bit field consisting of OpenSSL.SSL.VERIFY_* values
            ca_path: Path to a directory of trusted CA certificates prepared using the c_rehash tool
            ca_pemfile: Path to a PEM formatted trusted CA certificate
        """
        verification_mode = sslctx_kwargs.get('verify_options', None)
        if verification_mode == SSL.VERIFY_PEER and not sni:
            raise exceptions.TlsException(
                "Cannot validate certificate hostname without SNI")

        context = self.create_ssl_context(alpn_protos=alpn_protos,
                                          sni=sni,
                                          **sslctx_kwargs)
        self.connection = SSL.Connection(context, self.connection)
        if sni:
            self.sni = sni
            self.connection.set_tlsext_host_name(sni.encode("idna"))
        self.connection.set_connect_state()
        try:
            self.connection.do_handshake()
        except SSL.Error as v:
            if self.ssl_verification_error:
                raise self.ssl_verification_error
            else:
                raise exceptions.TlsException("SSL handshake error: %s" %
                                              repr(v))

        self.cert = certs.SSLCert(self.connection.get_peer_certificate())

        # Keep all server certificates in a list
        for i in self.connection.get_peer_cert_chain():
            self.server_certs.append(certs.SSLCert(i))

        # Validate TLS Hostname
        try:
            crt = dict(subjectAltName=[("DNS", x.decode("ascii", "strict"))
                                       for x in self.cert.altnames])
            if self.cert.cn:
                crt["subject"] = [[[
                    "commonName",
                    self.cert.cn.decode("ascii", "strict")
                ]]]
            if sni:
                # SNI hostnames allow support of IDN by using ASCII-Compatible Encoding
                # Conversion algorithm is in RFC 3490 which is implemented by idna codec
                # https://docs.python.org/3/library/codecs.html#text-encodings
                # https://tools.ietf.org/html/rfc6066#section-3
                # https://tools.ietf.org/html/rfc4985#section-3
                hostname = sni.encode("idna").decode("ascii")
            else:
                hostname = "no-hostname"
            match_hostname(crt, hostname)
        except (ValueError, CertificateError) as e:
            self.ssl_verification_error = exceptions.InvalidCertificateException(
                "Certificate Verification Error for {}: {}".format(
                    sni or repr(self.address), str(e)))
            if verification_mode == SSL.VERIFY_PEER:
                raise self.ssl_verification_error

        self.ssl_established = True
        self.rfile.set_descriptor(self.connection)
        self.wfile.set_descriptor(self.connection)
Ejemplo n.º 10
0
    def convert_to_ssl(self, sni=None, alpn_protos=None, **sslctx_kwargs):
        """
            cert: Path to a file containing both client cert and private key.

            options: A bit field consisting of OpenSSL.SSL.OP_* values
            verify_options: A bit field consisting of OpenSSL.SSL.VERIFY_* values
            ca_path: Path to a directory of trusted CA certificates prepared using the c_rehash tool
            ca_pemfile: Path to a PEM formatted trusted CA certificate
        """
        verification_mode = sslctx_kwargs.get('verify_options', None)
        if verification_mode == SSL.VERIFY_PEER and not sni:
            raise exceptions.TlsException(
                "Cannot validate certificate hostname without SNI")

        context = self.create_ssl_context(alpn_protos=alpn_protos,
                                          sni=sni,
                                          **sslctx_kwargs)
        self.connection = SSL.Connection(context, self.connection)
        if sni:
            self.sni = sni
            self.connection.set_tlsext_host_name(sni.encode("idna"))
        self.connection.set_connect_state()
        try:
            self.connection.do_handshake()
        except SSL.Error as v:
            if self.ssl_verification_error:
                raise self.ssl_verification_error
            else:
                raise exceptions.TlsException("SSL handshake error: %s" %
                                              repr(v))
        else:
            # Fix for pre v1.0 OpenSSL, which doesn't throw an exception on
            # certificate validation failure
            if verification_mode == SSL.VERIFY_PEER and self.ssl_verification_error:
                raise self.ssl_verification_error

        self.cert = certs.SSLCert(self.connection.get_peer_certificate())

        # Keep all server certificates in a list
        for i in self.connection.get_peer_cert_chain():
            self.server_certs.append(certs.SSLCert(i))

        # Validate TLS Hostname
        try:
            crt = dict(subjectAltName=[("DNS", x.decode("ascii", "strict"))
                                       for x in self.cert.altnames])
            if self.cert.cn:
                crt["subject"] = [[[
                    "commonName",
                    self.cert.cn.decode("ascii", "strict")
                ]]]
            if sni:
                hostname = sni
            else:
                hostname = "no-hostname"
            match_hostname(crt, hostname)
        except (ValueError, CertificateError) as e:
            self.ssl_verification_error = exceptions.InvalidCertificateException(
                "Certificate Verification Error for {}: {}".format(
                    sni or repr(self.address), str(e)))
            if verification_mode == SSL.VERIFY_PEER:
                raise self.ssl_verification_error

        self.ssl_established = True
        self.rfile.set_descriptor(self.connection)
        self.wfile.set_descriptor(self.connection)