예제 #1
0
async def test_abort_on_socket_failed(hass):
    """Test we abort of we have errors during socket creation."""
    flow = init_config_flow(hass)

    with patch("socket.create_connection", side_effect=socket.gaierror()):
        result = await flow.async_step_user({CONF_HOST: HOST})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["errors"] == {CONF_HOST: "resolve_failed"}

    with patch("socket.create_connection", side_effect=socket.timeout()):
        result = await flow.async_step_user({CONF_HOST: HOST})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["errors"] == {CONF_HOST: "connection_timeout"}

    with patch(
            "socket.create_connection",
            side_effect=ssl.CertificateError(
                f"{HOST} doesn't match somethingelse.com"),
    ):
        result = await flow.async_step_user({CONF_HOST: HOST})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["errors"] == {CONF_HOST: "wrong_host"}

    with patch("socket.create_connection",
               side_effect=ssl.CertificateError("different error")):
        result = await flow.async_step_user({CONF_HOST: HOST})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["errors"] == {CONF_HOST: "certificate_error"}

    with patch("socket.create_connection", side_effect=ssl.SSLError()):
        result = await flow.async_step_user({CONF_HOST: HOST})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["errors"] == {CONF_HOST: "certificate_error"}
예제 #2
0
파일: customssl.py 프로젝트: stelcheck/Dawn
def match_hostname(cert, hostname):
    """Verify that *cert* (in decoded format as returned by
    SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 and RFC 6125
    rules are followed, but IP addresses are not accepted for *hostname*.

    CertificateError is raised on failure. On success, the function
    returns nothing.
    """
    if not cert:
        raise ValueError("empty or no certificate, match_hostname needs a "
                         "SSL socket or SSL context with either "
                         "CERT_OPTIONAL or CERT_REQUIRED")
    try:
        host_ip = ipaddress.ip_address(hostname)
    except ValueError:
        # Not an IP address (common case)
        host_ip = None
    dnsnames = []
    san = cert.get('subjectAltName', ())
    for key, value in san:
        if key == 'DNS':
            if host_ip is None and ssl._dnsname_match(value, hostname):
                return
            dnsnames.append(value)
        elif key == 'IP Address':
            if host_ip is not None and _ipaddress_match(value, host_ip):
                return
            dnsnames.append(value)
    if not dnsnames:
        # The subject is only checked when there is no dNSName entry
        # in subjectAltName
        for sub in cert.get('subject', ()):
            for key, value in sub:
                # XXX according to RFC 2818, the most specific Common Name
                # must be used.
                if key == 'commonName':
                    if ssl._dnsname_match(value, hostname):
                        return
                    dnsnames.append(value)
    if len(dnsnames) > 1:
        raise ssl.CertificateError("hostname %r "
                                   "doesn't match either of %s"
                                   % (hostname, ', '.join(map(repr, dnsnames)))
                                   )
    elif len(dnsnames) == 1:
        raise ssl.CertificateError("hostname %r "
                                   "doesn't match %r"
                                   % (hostname, dnsnames[0]))
    else:
        raise ssl.CertificateError("no appropriate commonName or "
                                   "subjectAltName fields were found")
예제 #3
0
 def _validate_certificate(self, opened_socket):
     cert = opened_socket.getpeercert()
     ssl.match_hostname(cert, self._host)
     before = datetime.strptime(cert["notBefore"], "%b %d %H:%M:%S %Y %Z")
     after = datetime.strptime(cert["notAfter"], "%b %d %H:%M:%S %Y %Z")
     if not before < datetime.utcnow() < after:
         raise ssl.CertificateError("certificate expired")
예제 #4
0
 def wrap_socket(self, *args, **kwargs):
     sock = super().wrap_socket(*args, **kwargs)
     cert = sock.getpeercert(True)
     if not self.cert is None:
         if self.cert != cert:
             raise ssl.CertificateError(
                 'Certificate is not equal to expected')
     return sock
예제 #5
0
파일: net.py 프로젝트: NeoMahler/Limnoria
def check_certificate_fingerprint(conn, trusted_fingerprints):
    cert = conn.getpeercert(binary_form=True)
    for algorithm in FINGERPRINT_ALGORITHMS:
        h = hashlib.new(algorithm)
        h.update(cert)
        if h.hexdigest() in trusted_fingerprints:
            return
    raise ssl.CertificateError('No matching fingerprint.')
예제 #6
0
    def test_cert_error_ssl_module_absent(self, mocker):
        class Dummy(Exception):
            pass

        open_url = mocker.patch.object(http, "open_url")
        open_url.side_effect = ssl.CertificateError("Invalid")
        mocker.patch.object(http, "CertificateError", Dummy)

        with pytest.raises(ssl.CertificateError):
            http.request("GET", "example.com/bad")
예제 #7
0
 def notify_certificate(self, commonname: str, certdata: bytes) -> None:
     cert = x509.load_der_x509_certificate(certdata)
     pem = ssl.DER_cert_to_PEM_cert(certdata)
     certnames = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)
     for name in certnames:
         if name.value.lower() == commonname:
             self.certs[commonname] = pem
             break
     else:
         raise ssl.CertificateError(
             "Certificate has no matching common name"
         )
예제 #8
0
def tls_cert_tofu(wrapped, accept_certs, sname):
    global KNOWN_TLS_HOSTS
    cert = tls_sock_cert_sha256(wrapped)
    if accept_certs and cert not in accept_certs:
        raise ssl.CertificateError('Unrecognized certificate: %s' % cert)

    skey = md5_hex(sname)
    if skey not in KNOWN_TLS_HOSTS:
        KNOWN_TLS_HOSTS[skey] = {'server': sname}
        KNOWN_TLS_HOSTS[skey].use_web_ca = (accept_certs is None)
    if cert not in KNOWN_TLS_HOSTS[skey].accept_certs:
        KNOWN_TLS_HOSTS[skey].accept_certs.append(cert)
예제 #9
0
def main():
    """
    Exercise 3 Client
    """
    # Create a standard TCP Socket
    sock = socket.socket(socket.AF_INET)

    # Create SSL context which holds the parameters for any sessions
    context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
    context.check_hostname = False
    context.load_verify_locations(CA_CERT)

    # We can wrap in an SSL context first, then connect
    conn = context.wrap_socket(sock, server_hostname=LOCAL_HOST)
    try:
        # Handshake - conn is an SSLSocket
        conn.connect((LOCAL_HOST, LOCAL_PORT))

        # Verify against pinned hash
        dat = conn.getpeercert(binary_form=True)
        hashalg = hashlib.sha256()
        hashalg.update(dat)
        cert_hash = hashalg.digest()

        with open(PINNED_FILE, 'rb') as pinned:
            pinned_hash = pinned.read()

        if cert_hash != pinned_hash:
            raise ssl.CertificateError("Non-pinned certificate!")

        # What parameters were established?
        print("Negotiated session using cipher suite: {0}\n".format(
            conn.cipher()[0]))

        # We are sending a 4 byte int, convert into bytes
        conn.send((100124796).to_bytes(4, 'big'))

        # Receive a number back from the server
        server_response = conn.recv(1024)

        # Unpickle the bytes from the server into a datatypes.BankCustomer
        customer_returned = pickle.loads(server_response)
        print(customer_returned)

    except ssl.CertificateError:
        print("The host's certificate has not been pinned by this application")
    finally:
        conn.close()
예제 #10
0
    def error(self, error):
        raw_error_str = str(error)
        if "SSL23_GET_SERVER_HELLO" in str(
                error) or "SSL3_GET_RECORD" in raw_error_str:
            error = T("This server does not allow SSL on this port")

        # Catch certificate errors
        if type(
                error
        ) == ssl.CertificateError or "CERTIFICATE_VERIFY_FAILED" in raw_error_str:
            # Log the raw message for debug purposes
            logging.info("Certificate error for host %s: %s",
                         self.nw.server.host, raw_error_str)

            # Try to see if we should catch this message and provide better text
            if "hostname" in raw_error_str:
                raw_error_str = T(
                    "Certificate hostname mismatch: the server hostname is not listed in the certificate. This is a server issue."
                )
            elif "certificate verify failed" in raw_error_str:
                raw_error_str = T(
                    "Certificate not valid. This is most probably a server issue."
                )

            # Reformat error
            error = T("Server %s uses an untrusted certificate [%s]") % (
                self.nw.server.host, raw_error_str)
            error = "%s - %s: %s" % (error, T("Wiki"),
                                     "https://sabnzbd.org/certificate-errors")

            # Prevent throwing a lot of errors or when testing server
            if error not in self.nw.server.warning and not self.blocking:
                logging.error(error)
            # Pass to server-test
            if self.blocking:
                raise ssl.CertificateError(error)

        # Blocking = server-test, pass directly to display code
        if self.blocking:
            raise socket.error(errno.ECONNREFUSED, str(error))
        else:
            msg = "Failed to connect: %s" % (str(error))
            msg = "%s %s@%s:%s" % (msg, self.nw.thrdnum, self.host, self.port)
            self.error_msg = msg
            logging.info(msg)
            self.nw.server.warning = msg
예제 #11
0
 def starttls(self):
     assert 'ssl' in globals()
     network_config = getattr(conf.supybot.networks, self.irc.network)
     certfile = network_config.certfile()
     if not certfile:
         certfile = conf.supybot.protocols.irc.certfile()
     if not certfile:
         certfile = None
     elif not os.path.isfile(certfile):
         drivers.log.warning('Could not find cert file %s.' % certfile)
         certfile = None
     if self.currentServer.force_tls_verification \
             and not self.anyCertValidationEnabled():
         verifyCertificates = True
     else:
         verifyCertificates = conf.supybot.protocols.ssl.verifyCertificates(
         )
         if not self.currentServer.force_tls_verification \
                 and not self.anyCertValidationEnabled():
             drivers.log.warning(
                 'Not checking SSL certificates, connections '
                 'are vulnerable to man-in-the-middle attacks. Set '
                 'supybot.protocols.ssl.verifyCertificates to "true" '
                 'to enable validity checks.')
     try:
         self.conn = utils.net.ssl_wrap_socket(
             self.conn,
             logger=drivers.log,
             hostname=self.currentServer.hostname,
             certfile=certfile,
             verify=verifyCertificates,
             trusted_fingerprints=network_config.ssl.serverFingerprints(),
             ca_file=network_config.ssl.authorityCertificate(),
         )
     except ssl.CertificateError as e:
         drivers.log.error(
             ('Certificate validation failed when '
              'connecting to %s: %s\n'
              'This means either someone is doing a man-in-the-middle '
              'attack on your connection, or the server\'s certificate is '
              'not in your trusted fingerprints list.') %
             (self.irc.network, e.args[0]))
         raise ssl.CertificateError(
             'Aborting because of failed certificate '
             'verification.')
예제 #12
0
 def _validate_ssl_cert(self):
     if self.ca_certs is not None:
         cert = self._socket.getpeercert()  # get cert as dictionary
         ssl.match_hostname(cert, self.host)
     else:
         cert = self._socket.getpeercert(True)  # get binary cert
         sha512_hash = hashlib.sha512(cert).hexdigest()
         if self.host in self.known_hosts:
             hash_ = self.known_hosts[self.host]
             if sha512_hash != hash_:
                 self.disconnect()
                 e = ('SSL certificate does not match the one from the '
                      'known_hosts file. Most likely the server has changed'
                      ' its certificate and you have to delete the old line'
                      ' from the known_hosts file. Be careful, this could '
                      'also mean that you are being attacked!\nOld hash: '
                      '%s\nNew hash: %s' % (hash_, sha512_hash))
                 raise ssl.CertificateError(e)
         else:
             self.disconnect()
             raise UnknownCertError(self.host, sha512_hash,
                                    hashlib.sha1(cert).hexdigest())
예제 #13
0
파일: client.py 프로젝트: svdermant/lykos
    def connect(self):
        """ initiates the connection to the server set in self.host:self.port
        and returns a generator object.

        >>> cli = IRCClient(my_handler, host="irc.freenode.net", port=6667)
        >>> g = cli.connect()
        >>> while 1:
        ...     next(g)

        """
        try:
            retries = 0
            while True:
                try:
                    self.socket = socket.create_connection(
                        ("{0}".format(self.host), self.port),
                        source_address=("{0}".format(self.bindhost), 0))
                    break
                except socket.error as e:
                    retries += 1
                    self.stream_handler('Error: {0}'.format(e),
                                        level="warning")
                    if retries > 3:
                        sys.exit(1)

            if self.use_ssl:
                ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)

                if self.cipher_list:
                    try:
                        ctx.set_ciphers(self.cipher_list)
                    except Exception:
                        self.stream_handler(
                            "No ciphers could be selected from the cipher list. TLS is not available.",
                            level="warning")
                        self.stream_handler(
                            "Use `openssl ciphers' to see which ciphers are available on this system.",
                            level="warning")
                        raise

                # explicitly disable old protocols
                ctx.options |= ssl.OP_NO_SSLv2
                ctx.options |= ssl.OP_NO_SSLv3
                ctx.options |= ssl.OP_NO_TLSv1

                # explicitly disable compression (CRIME attack)
                ctx.options |= ssl.OP_NO_COMPRESSION

                # TLS session tickets harm forward secrecy
                ctx.options |= ssl.OP_NO_TICKET

                if self.cert_verify and not self.cert_fp:
                    ctx.verify_mode = ssl.CERT_REQUIRED

                    if not self.cert_fp:
                        ctx.check_hostname = True

                    ctx.load_default_certs()
                elif not self.cert_verify and not self.cert_fp:
                    self.stream_handler(
                        "**NOT** validating the server's TLS certificate! Set SSL_VERIFY or SSL_CERTFP in botconfig.py.",
                        level="warning")

                if self.client_certfile:
                    # if client_keyfile is not specified, the ssl module will look to the client_certfile for it.
                    try:
                        # specify blank password to ensure that encrypted certs will outright fail rather than prompting for password on stdin
                        # in a scenario where a user does !update or !restart, they will be unable to type in such a password and effectively kill the bot
                        # until someone can SSH in to restart it via CLI.
                        ctx.load_cert_chain(self.client_certfile,
                                            self.client_keyfile,
                                            password="")
                        self.stream_handler(
                            "Connecting with a TLS client certificate",
                            level="info")
                    except Exception as error:
                        self.stream_handler(
                            "Unable to load client cert/key pair: {0}".format(
                                error),
                            level="error")
                        raise

                try:
                    self.socket = ctx.wrap_socket(self.socket,
                                                  server_hostname=self.host)
                except Exception as error:
                    self.stream_handler(
                        "Could not connect with TLS: {0}".format(error),
                        level="error")
                    raise

                if self.cert_fp:
                    valid_fps = set(
                        fp.replace(":", "").lower() for fp in self.cert_fp)
                    peercert = self.socket.getpeercert(True)
                    h = hashlib.new("sha256")
                    h.update(peercert)
                    peercertfp = h.hexdigest()

                    if peercertfp not in valid_fps:
                        self.stream_handler(
                            "Certificate fingerprint {0} did not match any expected fingerprints"
                            .format(peercertfp),
                            level="error")
                        raise ssl.CertificateError(
                            "Certificate fingerprint {0} did not match any expected fingerprints"
                            .format(peercertfp))
                    self.stream_handler(
                        "Server certificate fingerprint matched {0}".format(
                            peercertfp),
                        level="info")

                self.stream_handler("Connected with cipher {0}".format(
                    self.socket.cipher()[0]),
                                    level="info")

            if not self.blocking:
                self.socket.setblocking(0)

            self.send("CAP LS 302")

            if self.server_pass and "{password}" in self.server_pass and self.password and not self.sasl_auth:
                # If not using SASL, try to send the NickServ password during connect via PASS
                message = "PASS :{0}".format(self.server_pass).format(
                    account=self.authname if self.authname else self.nickname,
                    password=self.password)
                self.send(message, log="PASS :[redacted]")
            elif self.server_pass and "{password}" not in self.server_pass:
                # If {password} isn't present, then we likely have a connect password, so send that regardless of SASL
                message = "PASS :{0}".format(self.server_pass)
                self.send(message, log="PASS :[redacted]")

            self.send("NICK", self.nickname)
            self.user(self.ident, self.real_name)

            if self.connect_cb:
                try:
                    self.connect_cb(self)
                except Exception as e:
                    sys.stderr.write(traceback.format_exc())
                    raise e

            buffer = bytes()
            while not self._end:
                try:
                    buffer += self.socket.recv(1024)
                except socket.error as e:
                    if False and not self.blocking and e.errno == 11:
                        pass
                    else:
                        sys.stderr.write(traceback.format_exc())
                        raise e
                else:
                    data = buffer.split(bytes("\n", "utf_8"))
                    buffer = data.pop()

                    for el in data:
                        prefix, command, args = parse_raw_irc_command(el)

                        try:
                            enc = "utf8"
                            fargs = [
                                arg.decode(enc) for arg in args
                                if isinstance(arg, bytes)
                            ]
                        except UnicodeDecodeError:
                            enc = "latin1"
                            fargs = [
                                arg.decode(enc) for arg in args
                                if isinstance(arg, bytes)
                            ]

                        try:
                            largs = list(args)
                            if prefix is not None:
                                prefix = prefix.decode(enc)
                            self.stream_handler(
                                "<--- receive {0} {1} ({2})".format(
                                    prefix, command, ", ".join(fargs)),
                                level="debug")
                            # for i,arg in enumerate(largs):
                            # if arg is not None: largs[i] = arg.decode(enc)
                            if command in self.command_handler:
                                self.command_handler[command](self, prefix,
                                                              *fargs)
                            elif "" in self.command_handler:
                                self.command_handler[""](self, prefix, command,
                                                         *fargs)
                        except Exception as e:
                            sys.stderr.write(traceback.format_exc())
                            raise e  # ?
                yield True
        finally:
            if self.socket:
                self.stream_handler('closing socket')
                self.socket.close()
                yield False
예제 #14
0
    def test_cert_error_ssl_module_present(self, mocker):
        open_url = mocker.patch.object(http, "open_url")
        open_url.side_effect = ssl.CertificateError("Invalid")

        with pytest.raises(errors.HttpError):
            http.request("GET", "example.com/bad")
예제 #15
0
    def test_certificate_error(self, mock: MagicMock) -> None:
        exc = ssl.CertificateError()
        mock.return_value = URLOpenMock(b"msg", exc)

        with self.assertRaises(www.WWWError):
            www.WWW("https://example.com").get()
예제 #16
0
 def request(*args, **kwargs):
     raise ssl.CertificateError()