def test_hijack_tty_ok_ssl_error(self, fake_Terminal, fake_get_stdin_pump, fake_select): """``dockerpty.pty`` PseudoTerminal '_hijack_tty' can handle some SSL errors""" fake_select.return_value = ([], []) fake_client = MagicMock() fake_run_operation = MagicMock() fake_pump = MagicMock() ssl_error = SSLError() ssl_error.strerror = 'The operation did not complete' fake_pump.do_write.side_effect = [ssl_error, MagicMock()] fake_pumps = [fake_pump] fake_select.return_value = ([fake_pump], [fake_pump]) pty.PseudoTerminal(fake_client, fake_run_operation)._hijack_tty(fake_pumps)
def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None, server_hostname=None, ssl_version=PROTOCOL_SSLv23): """ All arguments except `server_hostname` have the same meaning as for :func:`ssl.wrap_socket` :param server_hostname: Hostname of the expected certificate """ context = SSLContext(ssl_version) context.verify_mode = cert_reqs if ca_certs: try: context.load_verify_locations(ca_certs) except TypeError as e: # Reraise as SSLError # fixme: This block needs a test. raise SSLError(e) if certfile: # fixme: This block needs a test. context.load_cert_chain(certfile, keyfile) if HAS_SNI: # Platform-specific: OpenSSL with enabled SNI return context.wrap_socket(sock, server_hostname=server_hostname) return context.wrap_socket(sock)
def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, ca_certs=None, server_hostname=None, ssl_version=None): context = SSLContext(ssl_version) context.verify_mode = cert_reqs if ca_certs: try: context.load_verify_locations(ca_certs) print('------') except Exception as e: raise SSLError(e) else: context.load_default_certs(purpose=Purpose.SERVER_AUTH) if certfile: context.load_cert_chain(certfile, keyfile) if HAS_SNI: # server name indication enabled by OpenSSL return context.wrap_socket(sock, server_hostname=server_hostname) return context.wrap_socket(sock)
def setup_method(self, method): class MockGHManager(GHManager): def create_instance(self): pass super(TestInternalRetries, self).setup_method(method) # Define mock objects self.gh = self.mox.CreateMock(Github) self.user = self.mox.CreateMock(AuthenticatedUser) self.user.login = "******" self.org = self.mox.CreateMock(AuthenticatedUser) self.repo = self.mox.CreateMock(Repository) self.repo.organization = None self.issue = self.mox.CreateMock(Issue) self.pull = self.mox.CreateMock(PullRequest) # Define mock manager self.gh_manager = MockGHManager() self.gh_manager.github = self.gh self.gh_manager.login_or_token = "mock" # Define errors to test self.server_error = GithubException(502, 'Server Error') self.no_retry_exception = GithubException(-1, 'No retry') self.socket_timeout = socket.timeout() self.ssl_error = SSLError()
def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, ca_certs=None, server_hostname=None, ssl_version=None): """ All arguments except `server_hostname` have the same meaning as for :func:`ssl.wrap_socket` :param server_hostname: Hostname of the expected certificate """ context = SSLContext(ssl_version) context.verify_mode = cert_reqs if ca_certs: try: context.load_verify_locations(ca_certs) # Py32 raises IOError # Py33 raises FileNotFoundError except Exception as e: # Reraise as SSLError raise SSLError(e) if certfile: # FIXME: This block needs a test. context.load_cert_chain(certfile, keyfile) if HAS_SNI: # Platform-specific: OpenSSL with enabled SNI return context.wrap_socket(sock, server_hostname=server_hostname) return context.wrap_socket(sock)
def mock_get_certificate(*args, **kwargs): check_ca = kwargs.get('check_ca', True) if check_ca: error = SSLError(1, "Self-signed") raise error else: return self._get_mock_certificate()
def test_hijack_tty_bad_ssl_error(self, fake_Terminal, fake_get_stdin_pump, fake_select): """``dockerpty.pty`` PseudoTerminal '_hijack_tty' raises if it catches an expected SSL error""" fake_select.return_value = ([], []) fake_client = MagicMock() fake_run_operation = MagicMock() fake_pump = MagicMock() ssl_error = SSLError() ssl_error.strerror = 'doh' fake_pump.do_write.side_effect = [ssl_error, MagicMock()] fake_pumps = [fake_pump] fake_select.return_value = ([fake_pump], [fake_pump]) with self.assertRaises(SSLError): pty.PseudoTerminal(fake_client, fake_run_operation)._hijack_tty(fake_pumps)
def enable_https(self): if not self.secure: if not self.certfile: raise SSLError("Certificate info missing.") if self.cert_reqs != CERT_NONE and not self.ca_certs: raise SSLError( "Certificate validation requested but no ca certs available." ) self.logger.debug( "Enabling https with certfile=%s kefile=%s ca_certs=%s cert_reqs=%s", self.certfile, self.keyfile, self.ca_certs, self.cert_reqs) self.socket = wrap_socket(self.socket, server_side=True, keyfile=self.keyfile, certfile=self.certfile, ca_certs=self.ca_certs, cert_reqs=self.cert_reqs)
def test_push_auth_timeout(patcher, duo_user, interactive): with pytest.raises(MFAAuthenticationFailure) as e: instance = patcher.return_value instance.preauth.return_value = {"result": "auth", "devices": [{"capabilities": ["push"]}]} instance.auth.side_effect = SSLError("The read operation timed out.") client = Client("ikey", "skey", "host") client.push_authenticate(duo_user) assert e.match("timed out")
def handle_tls_connected_event(self, event): """Verify the peer certificate on the `TLSConnectedEvent`. """ if self.settings["tls_verify_peer"]: valid = self.settings["tls_verify_callback"]( event.stream, event.peer_certificate) if not valid: raise SSLError("Certificate verification failed") event.stream.tls_established = True with event.stream.lock: event.stream._restart_stream() # pylint: disable-msg=W0212
def testAcceptConnection(self): self._tls_context.wrap_socket = MagicMock() self._tls_context.wrap_socket.side_effect = SSLError() self._sut._accept_connection() self.assertEqual(self._sut._state, ServerState.ACCEPT) self._tls_context.wrap_socket = MagicMock() self._sut._accept_connection() self.assertEqual(self._sut._state, ServerState.DISPATCH)
def verify_cert(host, ca, timeout): server_ctx = Context(TLSv1_METHOD) server_cert_chain = [] if os.path.isdir(ca): server_ctx.load_verify_locations(None, ca) else: server_ctx.load_verify_locations(ca, None) def verify_cb(conn, cert, errnum, depth, ok): server_cert_chain.append(cert) return ok server_ctx.set_verify(VERIFY_PEER, verify_cb) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(1) sock.settimeout(timeout) sock.connect((host, 443)) server_conn = Connection(server_ctx, sock) server_conn.set_connect_state() def iosock_try(): ok = True try: server_conn.do_handshake() sleep(0.5) except SSLWantReadError as e: ok = False pass except Exception as e: raise e return ok try: while True: if iosock_try(): break server_subject = server_cert_chain[-1].get_subject() if host != server_subject.CN: raise SSLError('Server certificate CN does not match %s' % host) except SSLError as e: raise e finally: server_conn.shutdown() server_conn.close() return True
def __init__(self, conn, host, port): SocketTransport.__init__(self, conn, host, port) if conn.ssl_trustfile: validate = CERT_REQUIRED else: validate = CERT_NONE # if user manually set flag to false then require cert actual = getattr(conn, "_ssl_skip_hostname_check_actual", None) if actual is not None and conn.ssl_skip_hostname_check is False: validate = CERT_REQUIRED self.tls = wrap_socket(self.socket, keyfile=conn.ssl_keyfile, certfile=conn.ssl_certfile, ca_certs=conn.ssl_trustfile, cert_reqs=validate) if validate == CERT_REQUIRED and not conn.ssl_skip_hostname_check: match_found = False peer_cert = self.tls.getpeercert() if peer_cert: peer_names = [] if 'subjectAltName' in peer_cert: for san in peer_cert['subjectAltName']: if san[0] == 'DNS': peer_names.append(san[1].lower()) if 'subject' in peer_cert: for sub in peer_cert['subject']: while isinstance(sub, tuple) and isinstance( sub[0], tuple): sub = sub[ 0] # why the extra level of indirection??? if sub[0] == 'commonName': peer_names.append(sub[1].lower()) for pattern in peer_names: if _match_dns_pattern(host.lower(), pattern): #print "Match found %s" % pattern match_found = True break if not match_found: raise SSLError( "Connection hostname '%s' does not match names from peer certificate: %s" % (host, peer_names)) self.socket.setblocking(0) self.state = None # See qpid-4872: need to store the parameters last passed to tls.write() # in case the calls fail with an SSL_ERROR_WANT_* error and we have to # retry the call with the same parameters. self.write_retry = None # buffer passed to last call of tls.write()
def testInternalRecvStrict(self): sock = ws.WebSocket() s = sock.sock = SockMock() s.add_packet(six.b("foo")) s.add_packet(socket.timeout()) s.add_packet(six.b("bar")) s.add_packet(SSLError("The read operation timed out")) s.add_packet(six.b("baz")) with self.assertRaises(ws.WebSocketTimeoutException): data = sock._recv_strict(9) with self.assertRaises(SSLError): data = sock._recv_strict(9) data = sock._recv_strict(9) self.assertEqual(data, six.b("foobarbaz")) with self.assertRaises(ws.WebSocketConnectionClosedException): data = sock._recv_strict(1)
def test_run_with_exception(self, make_request_mock): for exception, expected_result in ((APNSServerError( 'status', 'identifier'), { 'description': 'None (unknown)', 'identifier': 'identifier', 'status': 'status' }), (SSLError('oh noes'), 'Invalid certificate.'), (TypeError(), 'Invalid registration_id value.'), (Exception('oh noes'), 'Internal server error.')): make_request_mock.side_effect = exception self.task.run(self.message.pk, instance_pk=self.instance.pk) self.message.refresh_from_db() self.assertTrue(make_request_mock.called) self.assertEqual(self.message.status, APNSMessage.STATUSES.ERROR) self.assertEqual(self.message.result, expected_result)
def _fake_requests_send(self, request, **kwargs): url = URL(request.url) address = (url.hostname, url.port or url.default_port) handler, ssl = _registered_addresses.get(address, (None, None)) if handler is None: return _orig_session_send(self, request, **kwargs) request_is_ssl = url.scheme == "https" if request_is_ssl and not ssl: if SSLError is None: raise NotImplementedError() # pragma: no cover raise SSLError() if not request_is_ssl and ssl: raise requests.ConnectionError() return handler.handle_request(self, url, request)
def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, ca_certs=None, server_hostname=None, ssl_version=None): context = SSLContext(ssl_version) context.verify_mode = cert_reqs if ca_certs: try: context.load_verify_locations(ca_certs) except Exception as e: raise SSLError(e) if certfile: context.load_cert_chain(certifile, keyfile) if HAS_SNI: return context.wrap_socket(sock, server_hostname=server_hostname) return context.wrap_socket(sock)
def attempt_connection(self): """ Try connecting to the (host, port) tuples specified at construction time. """ self.connection_error = False sleep_exp = 1 connect_count = 0 while self.running and self.socket is None and connect_count < self.__reconnect_attempts_max: for host_and_port in self.__host_and_ports: try: log.info("Attempting connection to host %s, port %s", host_and_port[0], host_and_port[1]) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__enable_keepalive() need_ssl = self.__need_ssl(host_and_port) if need_ssl: # wrap socket ssl_params = self.get_ssl(host_and_port) if ssl_params['ca_certs']: cert_validation = ssl.CERT_REQUIRED else: cert_validation = ssl.CERT_NONE self.socket = ssl.wrap_socket( self.socket, keyfile=ssl_params['key_file'], certfile=ssl_params['cert_file'], cert_reqs=cert_validation, ca_certs=ssl_params['ca_certs'], ssl_version=ssl_params['ssl_version']) self.socket.settimeout(self.__timeout) if self.blocking is not None: self.socket.setblocking(self.blocking) self.socket.connect(host_and_port) # # Validate server cert # if need_ssl and ssl_params['cert_validator']: cert = self.socket.getpeercert() (ok, errmsg) = ssl_params['cert_validator']( cert, host_and_port[0]) if not ok: raise SSLError( "Server certificate validation failed: %s", errmsg) self.current_host_and_port = host_and_port log.info("Established connection to host %s, port %s", host_and_port[0], host_and_port[1]) break except socket.error: self.socket = None connect_count += 1 log.warning("Could not connect to host %s, port %s", host_and_port[0], host_and_port[1], exc_info=1) if self.socket is None: sleep_duration = (min(self.__reconnect_sleep_max, ( (self.__reconnect_sleep_initial / (1.0 + self.__reconnect_sleep_increase)) * math.pow(1.0 + self.__reconnect_sleep_increase, sleep_exp) )) * (1.0 + random.random() * self.__reconnect_sleep_jitter)) sleep_end = time.time() + sleep_duration log.debug( "Sleeping for %.1f seconds before attempting reconnect", sleep_duration) while self.running and time.time() < sleep_end: time.sleep(0.2) if sleep_duration < self.__reconnect_sleep_max: sleep_exp += 1 if not self.socket: raise exception.ConnectFailedException()
def attempt_connection(self): """ Try connecting to the (host, port) tuples specified at construction time. """ self.connection_error = False sleep_exp = 1 connect_count = 0 while self.running and self.socket is None and connect_count < self.__reconnect_attempts_max: for host_and_port in self.__host_and_ports: try: log.info("Attempting connection to host %s, port %s", host_and_port[0], host_and_port[1]) self.socket = get_socket(host_and_port[0], host_and_port[1], self.__timeout) self.__enable_keepalive() need_ssl = self.__need_ssl(host_and_port) if need_ssl: # wrap socket ssl_params = self.get_ssl(host_and_port) if ssl_params['ca_certs']: cert_validation = ssl.CERT_REQUIRED else: cert_validation = ssl.CERT_NONE try: tls_context = ssl.create_default_context( cafile=ssl_params['ca_certs']) except AttributeError: tls_context = None if tls_context: # Wrap the socket for TLS certfile = ssl_params['cert_file'] keyfile = ssl_params['key_file'] password = ssl_params.get('password') if certfile and not keyfile: keyfile = certfile if certfile: tls_context.load_cert_chain( certfile, keyfile, password) if cert_validation is None or cert_validation == ssl.CERT_NONE: tls_context.check_hostname = False tls_context.verify_mode = cert_validation self.socket = tls_context.wrap_socket( self.socket, server_hostname=host_and_port[0]) else: # Old-style wrap_socket where we don't have a modern SSLContext (so no SNI) self.socket = ssl.wrap_socket( self.socket, keyfile=ssl_params['key_file'], certfile=ssl_params['cert_file'], cert_reqs=cert_validation, ca_certs=ssl_params['ca_certs'], ssl_version=ssl_params['ssl_version']) self.socket.settimeout(self.__timeout) if self.blocking is not None: self.socket.setblocking(self.blocking) # # Validate server cert # if need_ssl and ssl_params['cert_validator']: cert = self.socket.getpeercert() (ok, errmsg) = ssl_params['cert_validator']( cert, host_and_port[0]) if not ok: raise SSLError( "Server certificate validation failed: %s", errmsg) self.current_host_and_port = host_and_port log.info("Established connection to host %s, port %s", host_and_port[0], host_and_port[1]) break except socket.error: self.socket = None connect_count += 1 log.warning("Could not connect to host %s, port %s", host_and_port[0], host_and_port[1], exc_info=1) if self.socket is None: sleep_duration = (min(self.__reconnect_sleep_max, ( (self.__reconnect_sleep_initial / (1.0 + self.__reconnect_sleep_increase)) * math.pow(1.0 + self.__reconnect_sleep_increase, sleep_exp) )) * (1.0 + random.random() * self.__reconnect_sleep_jitter)) sleep_end = monotonic() + sleep_duration log.debug( "Sleeping for %.1f seconds before attempting reconnect", sleep_duration) while self.running and monotonic() < sleep_end: time.sleep(0.2) if sleep_duration < self.__reconnect_sleep_max: sleep_exp += 1 if not self.socket: raise exception.ConnectFailedException()
def test_make_call_ssl_error(self): self.api.client.service.TestService.side_effect = SSLError('a', 'b') self.assertRaises(AuthorizeConnectionError, self.api._make_call, 'TestService', 'foo') self.assertEqual(self.api.client.service.TestService.call_args[0], (self.api.client_auth, 'foo'))
def loggingUrlOpen(*fArgs, **fKwargs): calls.append(fKwargs) raise SSLError("Some error")
def _mock_wrap_socket(*args, **kwargs): from ssl import SSLError raise SSLError("unit test exception")
def mock_get_certificate(*args, **kwargs): error = SSLError(8, "Certificate is unavailble") raise error
def test_two_retriable_errors(self): self.add_transient_error(socket.error(110, 'Connection timed out')) self.add_transient_error(SSLError('The read operation timed out')) self.assertEqual(self.wrapped_client.list_buckets(), dict(Buckets=[])) self.assertTrue(self.log.info.called)
def test_other_ssl_error(self): self.assert_no_retry(SSLError('certificate verify failed'))
def test_ssl_write_op_timed_out_error(self): self.assert_retry(SSLError('The write operation timed out'))
def test_ssl_read_op_timed_out_error(self): self.assert_retry(SSLError('The read operation timed out'))
def __attempt_connection(self): """ Try connecting to the (host, port) tuples specified at construction time. """ sleep_exp = 1 connect_count = 0 while self.__running and self.__socket is None and connect_count < self.__reconnect_attempts_max: for host_and_port in self.__host_and_ports: try: log.debug("Attempting connection to host %s, port %s" % host_and_port) self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if self.__ssl: # wrap socket if self.__ssl_ca_certs: cert_validation = ssl.CERT_REQUIRED else: cert_validation = ssl.CERT_NONE self.__socket = ssl.wrap_socket( self.__socket, keyfile=self.__ssl_key_file, certfile=self.__ssl_cert_file, cert_reqs=cert_validation, ca_certs=self.__ssl_ca_certs, ssl_version=ssl.PROTOCOL_SSLv3) self.__socket.settimeout(None) if self.blocking is not None: self.__socket.setblocking(self.blocking) self.__socket.connect(host_and_port) # # Validate server cert # if self.__ssl and self.__ssl_cert_validator: cert = self.__socket.getpeercert() (ok, errmsg) = apply(self.__ssl_cert_validator, (cert, host_and_port[0])) if not ok: raise SSLError( "Server certificate validation failed: %s" % errmsg) self.__current_host_and_port = host_and_port log.info("Established connection to host %s, port %s" % host_and_port) break except socket.error: self.__socket = None if isinstance(sys.exc_info()[1], tuple): exc = sys.exc_info()[1][1] else: exc = sys.exc_info()[1] connect_count += 1 print(exc) log.warning("Could not connect to host %s, port %s: %s" % (host_and_port[0], host_and_port[1], exc)) if self.__socket is None: sleep_duration = (min(self.__reconnect_sleep_max, ( (self.__reconnect_sleep_initial / (1.0 + self.__reconnect_sleep_increase)) * math.pow(1.0 + self.__reconnect_sleep_increase, sleep_exp) )) * (1.0 + random.random() * self.__reconnect_sleep_jitter)) sleep_end = time.time() + sleep_duration log.debug( "Sleeping for %.1f seconds before attempting reconnect" % sleep_duration) while self.__running and time.time() < sleep_end: time.sleep(0.2) if sleep_duration < self.__reconnect_sleep_max: sleep_exp += 1 if not self.__socket: raise exception.ReconnectFailedException