def infoCallback(connection: SSL.Connection, where: int, ret: int) -> None: try: return wrapped(connection, where, ret) except BaseException: f = Failure() logger.exception("Error during info_callback") connection.get_app_data().failVerification(f)
def _ssl_handshake(self): """ Perform an SSL handshake w/ the server. Precondition: a successful STARTTLS exchange has taken place with Riak returns True upon success, otherwise an exception is raised """ if self._client._credentials: ssl_ctx = \ Context(self._client._credentials.ssl_version) try: configure_context(ssl_ctx, self._client._credentials) # attempt to upgrade the socket to SSL ssl_socket = Connection(ssl_ctx, self._socket) ssl_socket.set_connect_state() ssl_socket.do_handshake() # ssl handshake successful self._socket = ssl_socket if self._client._credentials.has_credential('crl'): self._client._credentials.check_revoked_cert(ssl_socket) return True except Exception as e: # fail if *any* exceptions are thrown during SSL handshake raise RiakError(e.message)
def testPFSCipher(host,port,cipher): try: # Construct the socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.settimeout(10) client.connect((host, port)) # Define the method as serverpreferred and use the Cipher from the test contextToUse = Context(pfsCipherList[cipher]) contextToUse.set_cipher_list(cipher) # Estabilish a SSL connection using the server's preferred connection client_ssl = Connection(contextToUse, client) client_ssl.set_connect_state() client_ssl.set_tlsext_host_name(host) # Try to perform an SSL handshake client_ssl.do_handshake() # Close the connection client_ssl.close() client.close() return True except openSSLError as e: # Server may be down or avoiding SSL connection return False except ValueError as e: # Not configured or not allowed return False pass
def will_use_tls_1_3(): """ Will OpenSSL negotiate TLS 1.3? """ ctx = Context(SSLv23_METHOD) connection = Connection(ctx, None) return connection.get_protocol_version_name() == u'TLSv1.3'
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 and not sni: conn.cert_error = exceptions.InvalidCertificateException( f"Certificate verification error for {address}: Cannot validate hostname, SNI missing." ) 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
def _pick_certificate_cb(self, connection: SSL.Connection) -> None: """SNI certificate callback. This method will set a new OpenSSL context object for this connection when an incoming connection provides an SNI name (in order to serve the appropriate certificate, if any). :param connection: The TLS connection object on which the SNI extension was received. :type connection: :class:`OpenSSL.Connection` """ pair = self.cert_selection(connection) if pair is None: logger.debug( "Certificate selection for server name %s failed, dropping SSL", connection.get_servername()) return key, cert = pair new_context = SSL.Context(self.method) new_context.set_options(SSL.OP_NO_SSLv2) new_context.set_options(SSL.OP_NO_SSLv3) new_context.use_privatekey(key) new_context.use_certificate(cert) if self.alpn_selection is not None: new_context.set_alpn_select_callback(self.alpn_selection) connection.set_context(new_context)
def makeConnection(self, transport): """ Connect this wrapper to the given transport and initialize the necessary L{OpenSSL.SSL.Connection} with a memory BIO. """ tlsContext = self.factory._contextFactory.getContext() self._tlsConnection = Connection(tlsContext, None) if self.factory._isClient: self._tlsConnection.set_connect_state() else: self._tlsConnection.set_accept_state() self._appSendBuffer = [] # Intentionally skip ProtocolWrapper.makeConnection - it might call # wrappedProtocol.makeConnection, which we want to make conditional. Protocol.makeConnection(self, transport) self.factory.registerProtocol(self) if self._connectWrapped: # Now that the TLS layer is initialized, notify the application of # the connection. ProtocolWrapper.makeConnection(self, transport) # Now that we ourselves have a transport (initialized by the # ProtocolWrapper.makeConnection call above), kick off the TLS # handshake. try: self._tlsConnection.do_handshake() except WantReadError: # This is the expected case - there's no data in the connection's # input buffer yet, so it won't be able to complete the whole # handshake now. If this is the speak-first side of the # connection, then some bytes will be in the send buffer now; flush # them. self._flushSendBIO()
def start(keystore, keystorealias, keypass, keystorepassphrase, hostandport, timeout): verify(keystore, keystorealias, keypass, keystorepassphrase, hostandport) sslContext = getOpensslContext(keystore, keystorealias, keypass, keystorepassphrase) socket = socket_any_family() socket.settimeout(timeout) hostandport = hostandport.split(":", 2) socket.connect((hostandport[0], int(hostandport[1]))) sslConnection = Connection(sslContext, socket) sslConnection.set_connect_state() sslConnection.set_tlsext_host_name(hostandport[0].encode('utf-8')) while True: try: sslConnection.do_handshake() except OpenSSL.SSL.WantReadError: rd, _, _ = select.select([socket], [], [], socket.gettimeout()) if not rd: raise timeout('select timed out') continue except OpenSSL.SSL.Error as e: raise ssl.SSLError('bad handshake: %r' % e) break sslContext.set_timeout(timeout) sslConnection.send(b"GET / HTTP/1.0\r\n\r\n") socket.recv(1024)
def serve(socket, get_secrets : Callable[[None], List[Tuple[bytes, bytes]]], handle_message : Callable[[str, str], None], running : bool) -> None: patch_context() ctx = Context(TLSv1_2_METHOD) ctx.set_cipher_list(b'ECDHE-PSK-CHACHA20-POLY1305') ctx.use_psk_identity_hint(b'our_chosen_server_identity_hint') partial_get_secret = partial(get_secret, get_secrets=get_secrets) ctx.set_psk_server_callback(partial_get_secret) server = Connection(ctx, socket) open_sockets = [] addr, port = socket.getsockname() print(f"Serving on: {addr}:{port}") while running: try: client_socket, from_addr = server.accept() except: continue addr, port = from_addr print(f"Accepted connection from {addr}:{port}") thread = Thread(target=handle_client, args=(client_socket, handle_message, )) thread.start() open_sockets.append(thread) for thread in open_sockets: if not thread.is_alive(): thread.join() for thread in open_sockets: thread.join()
def test_set_default_verify_paths(self): """ L{Context.set_default_verify_paths} causes the platform-specific CA certificate locations to be used for verification purposes. """ # Testing this requires a server with a certificate signed by one of # the CAs in the platform CA location. Getting one of those costs # money. Fortunately (or unfortunately, depending on your # perspective), it's easy to think of a public server on the # internet which has such a certificate. Connecting to the network # in a unit test is bad, but it's the only way I can think of to # really test this. -exarkun # Arg, verisign.com doesn't speak TLSv1 context = Context(SSLv3_METHOD) context.set_default_verify_paths() context.set_verify( VERIFY_PEER, lambda conn, cert, errno, depth, preverify_ok: preverify_ok) client = socket() client.connect(('verisign.com', 443)) clientSSL = Connection(context, client) clientSSL.set_connect_state() clientSSL.do_handshake() clientSSL.send('GET / HTTP/1.0\r\n\r\n') self.assertTrue(clientSSL.recv(1024))
def do_handshake(self): while True: try: _Connection.do_handshake(self) break except WantReadError: exc_clear() wait_read(self._sock.fileno(), timeout=self._timeout) except WantWriteError: exc_clear() wait_write(self._sock.fileno(), timeout=self._timeout)
def connect(self, *args, **kwargs): while True: try: _Connection.connect(self, *args, **kwargs) break except WantReadError: exc_clear() wait_read(self._sock.fileno(), timeout=self._timeout) except WantWriteError: exc_clear() wait_write(self._sock.fileno(), timeout=self._timeout)
class ManInTheMiddle: def __init__(self, client_socket, host, port): self.client_socket = client_socket self.host = host self.port = port self.sni = None self.client_ssl_sock = None self.server_ssl_sock = None def start_hacking(self): self.client_socket.sendall(('HTTP/1.1 %d %s\r\n\r\n' % (200, 'OK')).encode('latin-1', 'strict')) self.accept_client_conn() def accept_client_conn(self): context = Context(SSLv23_METHOD) context.set_tlsext_servername_callback(self.prepare_handshake) self.client_ssl_sock = Connection(context, self.client_socket) self.client_ssl_sock.set_accept_state() self.client_ssl_sock.do_handshake() def prepare_handshake(self, connection): raw_sni = connection.get_servername() if raw_sni is not None: self.sni = str(raw_sni, 'ascii') self.build_server_conn() cert_dict = self.server_ssl_sock.getpeercert() crt_dir = generate_fake_cert(cert_dict) try: key, cert = load(crt_dir) except crypto.Error: raise CertificateRaceCondition new_context = Context(SSLv23_METHOD) new_context.use_privatekey(key) new_context.use_certificate(cert) connection.set_context(new_context) def build_server_conn(self): server_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) server_context.verify_mode = ssl.CERT_OPTIONAL # context.load_verify_locations('/etc/ssl/certs/ca-bundle.crt') server_context.set_default_verify_paths() ssl_sock = server_context.wrap_socket(socket.socket(socket.AF_INET), server_hostname=self.sni) try: ssl_sock.connect((self.host, self.port)) except socket.gaierror: print(self.host, self.port) raise ServerConnectionError self.server_ssl_sock = ssl_sock
def test_set_info_callback(self): """ L{Context.set_info_callback} accepts a callable which will be invoked when certain information about an SSL connection is available. """ (server, client) = socket_pair() clientSSL = Connection(Context(TLSv1_METHOD), client) clientSSL.set_connect_state() called = [] def info(conn, where, ret): called.append((conn, where, ret)) context = Context(TLSv1_METHOD) context.set_info_callback(info) context.use_certificate( load_certificate(FILETYPE_PEM, cleartextCertificatePEM)) context.use_privatekey( load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)) serverSSL = Connection(context, server) serverSSL.set_accept_state() while not called: for ssl in clientSSL, serverSSL: try: ssl.do_handshake() except WantReadError: pass # Kind of lame. Just make sure it got called somehow. self.assertTrue(called)
def _connectionForTLS(self, protocol): """ Create an L{OpenSSL.SSL.Connection} object. @param protocol: The protocol initiating a TLS connection. @type protocol: L{TLSMemoryBIOProtocol} @return: a connection @rtype: L{OpenSSL.SSL.Connection} """ context = self._oldStyleContextFactory.getContext() connection = Connection(context, None) connection.set_app_data(protocol) return connection
def server_ok(serverarg, capath, timeout): server_ctx = Context(TLSv1_METHOD) server_ctx.load_verify_locations(None, capath) def verify_cb(conn, cert, errnum, depth, ok): return ok server_ctx.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) serverarg = re.split("/*", serverarg)[1] if ':' in serverarg: serverarg = serverarg.split(':') server = serverarg[0] port = int(serverarg[1] if not '?' in serverarg[1] else serverarg[1]. split('?')[0]) else: server = serverarg port = DEFAULT_PORT try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((server, port)) server_conn = Connection(server_ctx, sock) server_conn.set_connect_state() try: def handler(signum, frame): raise socket.error([('Timeout', 'after', str(timeout) + 's')]) signal.signal(signal.SIGALRM, handler) signal.alarm(timeout) server_conn.do_handshake() signal.alarm(0) except socket.timeout as e: nagios_out( 'Critical', 'Connection error %s - %s' % (server + ':' + str(port), errmsg_from_excp(e)), 2) server_conn.shutdown() server_conn.close() except (SSLError, socket.error) as e: if 'sslv3 alert handshake failure' in errmsg_from_excp(e): pass else: nagios_out( 'Critical', 'Connection error %s - %s' % (server + ':' + str(port), errmsg_from_excp(e)), 2) return True
def recv(self, bufsiz, flags=0): pending = _Connection.pending(self) if pending: return _Connection.recv(min(pending, bufsiz)) while True: try: return _Connection.recv(self, buflen, flags) except WantReadError: exc_clear() wait_read(self._sock.fileno(), timeout=self._timeout) except WantWriteError: exc_clear() wait_write(self._sock.fileno(), timeout=self._timeout) except ZeroReturnError: return ''
def _openssl_connect(hostname): client = socket() client.connect((hostname, 443)) client_ssl = Connection(Context(SSLv23_METHOD), client) client_ssl.set_connect_state() client_ssl.set_tlsext_host_name(hostname.encode('utf-8')) client_ssl.do_handshake() return client_ssl
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.Cert(x509) try: crt: typing.Dict[str, typing.Any] = dict( subjectAltName=[("DNS", x.decode("ascii", "strict")) for x in cert.altnames] ) 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
def send(self, data, flags=0): while True: try: _Connection.send(self, data, flags) break except WantReadError: exc_clear() wait_read(self._sock.fileno(), timeout=self._timeout) except WantWriteError: exc_clear() wait_write(self._sock.fileno(), timeout=self._timeout) except SysCallError as e: if e[0] == -1 and not data: # errors when writing empty strings are expected and can be ignored return 0 raise
def __call__( self, connection: SSL.Connection ) -> Optional[Tuple[crypto.PKey, crypto.X509]]: server_name = connection.get_servername() if server_name: return self.certs.get(server_name, None) return None # pragma: no cover
def accept_client_conn(self): context = Context(SSLv23_METHOD) context.set_tlsext_servername_callback(self.prepare_handshake) self.client_ssl_sock = Connection(context, self.client_socket) self.client_ssl_sock.set_accept_state() self.client_ssl_sock.do_handshake()
def verify_context_info_cb( self, ssl_connection: SSL.Connection, where: int ) -> None: if where & SSL.SSL_CB_HANDSHAKE_START and not self._is_ip_address: ssl_connection.set_tlsext_host_name(self._hostnameBytes) if where & SSL.SSL_CB_HANDSHAKE_DONE and self._verify_certs: try: if self._is_ip_address: verify_ip_address(ssl_connection, self._hostnameASCII) else: verify_hostname(ssl_connection, self._hostnameASCII) except VerificationError: f = Failure() tls_protocol = ssl_connection.get_app_data() tls_protocol.failVerification(f)
def _cert_selection( self, connection: SSL.Connection ) -> Optional[Tuple[crypto.PKey, crypto.X509]]: # pragma: no cover """Callback selecting certificate for connection.""" server_name = connection.get_servername() if server_name: return self.certs.get(server_name, None) return None
def _connect(self): """This method implements the functionality of establishing a secure connection using TLS Extension""" self._socket_client = socket() self._socket_client.connect((self._host, self._port)) self._ssl_client = Connection(Context(TLSv1_METHOD), self._socket_client) self._ssl_client.set_connect_state() self._ssl_client.set_tlsext_host_name(self._host) self._ssl_client.do_handshake()
def server_ok(serverarg, capath, timeout): "Check if the server is active and responsive" server_ctx = Context(TLSv1_METHOD) server_ctx.load_verify_locations(None, capath) def verify_cb(conn, cert, errnum, depth, ok): return ok server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb) serverarg = re.split("/*", serverarg)[1] if ':' in serverarg: serverarg = serverarg.split(':') server = serverarg[0] port = int(serverarg[1] if not '?' in serverarg[1] else serverarg[1].split('?')[0]) else: server = serverarg port = DEFAULT_PORT try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((server, port)) server_conn = Connection(server_ctx, sock) server_conn.set_connect_state() try: def handler(signum, frame): raise socket.error([('Timeout', 'after', str(timeout) + 's')]) signal.signal(signal.SIGALRM, handler) signal.alarm(timeout) server_conn.do_handshake() signal.alarm(0) except socket.timeout as e: nagios_out('Critical', 'Connection error %s - %s' % (server + ':' + str(port), errmsg_from_excp(e)),2) server_conn.shutdown() server_conn.close() except (SSLError, socket.error) as e: if 'sslv3 alert handshake failure' in errmsg_from_excp(e): pass else: nagios_out('Critical', 'Connection error %s - %s' % (server + ':' + str(port), errmsg_from_excp(e)), 2) return True
def _client(self, sock): """ Create a new client-side SSL L{Connection} object wrapped around C{sock}. """ # Now create the client side Connection. Similar boilerplate to the # above. client_ctx = Context(TLSv1_METHOD) client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE ) client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb) client_store = client_ctx.get_cert_store() client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem)) client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem)) client_ctx.check_privatekey() client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem)) client_conn = Connection(client_ctx, sock) client_conn.set_connect_state() return client_conn
class OpenSSLSNI(object): """This class implements the functionality of obtaining certificates secure connection using apache TLS Extension Server Name Indication (SNI) """ def connection(func): def wrapped(self): self._connect() try: return func(self) finally: self._close() return wrapped def __init__(self, host, port): #Set host name self._host = str(host).split('//')[-1].split(':')[0] #Set port self._port = int(port) if str(port).isdigit() else 443 def _connect(self): """This method implements the functionality of establishing a secure connection using TLS Extension""" self._socket_client = socket() self._socket_client.connect((self._host, self._port)) self._ssl_client = Connection(Context(TLSv1_METHOD), self._socket_client) self._ssl_client.set_connect_state() self._ssl_client.set_tlsext_host_name(self._host) self._ssl_client.do_handshake() def _close(self): """This method implements the functional termination created connection""" self._ssl_client.close() del self._socket_client @property @connection def serial_number(self): """Returns certificates serial number""" return self._ssl_client.get_peer_certificate().get_serial_number() @property @connection def certificate(self): """Returns certificate""" return OpenSSL.crypto.dump_certificate(FILETYPE_PEM, self._ssl_client.get_peer_certificate())
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 _server(self, sock): """ Create a new server-side SSL L{Connection} object wrapped around C{sock}. """ # Create the server side Connection. This is mostly setup boilerplate # - use TLSv1, use a particular certificate, etc. server_ctx = Context(TLSv1_METHOD) server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE ) server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb) server_store = server_ctx.get_cert_store() server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem)) server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem)) server_ctx.check_privatekey() server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem)) # Here the Connection is actually created. If None is passed as the 2nd # parameter, it indicates a memory BIO should be created. server_conn = Connection(server_ctx, sock) server_conn.set_accept_state() return server_conn
def netflix_openssl_test_retry(ip): client = socket() print 'Connecting...', stdout.flush() client.connect((ip, port)) print 'connected', client.getpeername() client_ssl = Connection(Context(TLSv1_METHOD), client) client_ssl.set_connect_state() client_ssl.set_tlsext_host_name(hostname) client_ssl.do_handshake() cert = client_ssl.get_peer_certificate().get_subject() cn = [comp for comp in cert.get_components() if comp[0] in ['CN']] client_ssl.close() print cn if hostname in cn[0][1]: return True else: return False
def _cert_selection(self, connection: SSL.Connection) -> Tuple[crypto.PKey, crypto.X509]: # TODO: We would like to serve challenge cert only if asked for it via # ALPN. To do this, we need to retrieve the list of protos from client # hello, but this is currently impossible with openssl [0], and ALPN # negotiation is done after cert selection. # Therefore, currently we always return challenge cert, and terminate # handshake in alpn_selection() if ALPN protos are not what we expect. # [0] https://github.com/openssl/openssl/issues/4952 server_name = connection.get_servername() logger.debug("Serving challenge cert for server name %s", server_name) return self.challenge_certs[server_name]
def test_socketOverridesMemory(self): """ Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't work on L{OpenSSL.SSL.Connection}() that use sockets. """ context = Context(SSLv3_METHOD) client = socket() clientSSL = Connection(context, client) self.assertRaises(TypeError, clientSSL.bio_read, 100) self.assertRaises(TypeError, clientSSL.bio_write, "foo") self.assertRaises(TypeError, clientSSL.bio_shutdown)
def alpn_select_callback(conn: SSL.Connection, options: List[bytes]) -> Any: app_data: AppData = conn.get_app_data() server_alpn = app_data["server_alpn"] http2 = app_data["http2"] if server_alpn and server_alpn in options: return server_alpn http_alpns = tls.HTTP_ALPNS if http2 else tls.HTTP1_ALPNS for alpn in options: # client sends in order of preference, so we are nice and respect that. if alpn in http_alpns: return alpn else: return SSL.NO_OVERLAPPING_PROTOCOLS
def serverConnectionForTLS(self, protocol): """ Construct an OpenSSL server connection. @param protocol: The protocol initiating a TLS connection. @type protocol: L{TLSMemoryBIOProtocol} @return: a connection @rtype: L{OpenSSL.SSL.Connection} """ conn = Connection(self.context, None) return _ConnectionProxy(conn, self)
def _validate_certificate_hostname_pyopenssl(self): """ Use pyOpenSSL check if the host's certifcate matches the hostname. Python < 2.7.9 is not able to provide a server hostname for SNI, so this is a fallback that opens an additional connection if the initial validation failed. Returns: bool: Whether or not the hostname is valid on the certificate. """ client = socket.socket() client.connect((self.host, self.port)) client_ssl = Connection(Context(TLSv1_METHOD), client) client_ssl.set_connect_state() client_ssl.set_tlsext_host_name(self.host) client_ssl.do_handshake() cert = client_ssl.get_peer_certificate() client_ssl.close() common_name = cert.get_subject().commonName return self._cert_host_matches_hostname(common_name, self.host)
def _ssl_handshake(self): """ Perform an SSL handshake w/ the server. Precondition: a successful STARTTLS exchange has taken place with Riak returns True upon success, otherwise an exception is raised """ if self._client._credentials: ssl_ctx = \ Context(self._client._credentials.ssl_version) try: configure_context(ssl_ctx, self._client._credentials) # attempt to upgrade the socket to SSL ssl_socket = Connection(ssl_ctx, self._socket) ssl_socket.set_connect_state() ssl_socket.do_handshake() # ssl handshake successful self._socket = ssl_socket self._client._credentials._check_revoked_cert(ssl_socket) return True except Exception as e: # fail if *any* exceptions are thrown during SSL handshake raise SecurityError(e.message)
def __init__(self, HOST='130.236.216.131', PORT = 443): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) context = Context(TLSv1_METHOD) context.use_certificate_file((self.certpath)) context.use_privatekey_file(self.keypath) context.set_timeout(2) conn = Connection(context,s) conn.bind((HOST,PORT)) print 'Server is listening...' conn.listen(5) # self.client_table is a dictionary of clients # where key = unique id and value = socket self.client_table = {} self.id_counter = 0 self.in_q = Queue.Queue() self.out_q = Queue.Queue() threading.Thread(target=self.sendinput).start() threading.Thread(target=self.in_processor).start() threading.Thread(target=self.out_processor).start() try: while True: # Waiting for new client to accept, sslsocket is the socket that will be used for communication with this client after a client sets up a connection with the server sslsocket, addr = conn.accept() self.client_table[self.id_counter] = sslsocket self.id_counter = self.id_counter + 1 threading.Thread(target=self.client_handler,args=(self.id_counter-1,)).start() except KeyboardInterrupt: for key, value in self.client_table.iteritems(): value.shutdown() value.close() sys.exit(0)
def get_mppe_keys(master: bytes, client_random: bytes, server_random: bytes, label: bytes, ssl_connection: SSL.Connection) -> List[bytes]: ''' Generate MS-MPPE-Send/Recv-Key as defined in RFC 2548 On newer OpenSSLs, to support TLS 1.2, randomness is now generated via export_keying_material. See T39616 for details. ''' if SSL.OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_101: randomstuff = ssl_connection.export_keying_material(label, 64) else: label += client_random label += server_random randomstuff = PRF(master, label, 64) return [randomstuff[:32], randomstuff[32:64]]
def main(): """ Connect to an SNI-enabled server and request a specific hostname, specified by argv[1], of it. """ if len(argv) < 2: print 'Usage: %s <hostname>' % (argv[0],) return 1 client = socket() print 'Connecting...', stdout.flush() client.connect(('127.0.0.1', 8443)) print 'connected', client.getpeername() client_ssl = Connection(Context(TLSv1_METHOD), client) client_ssl.set_connect_state() client_ssl.set_tlsext_host_name(argv[1]) client_ssl.do_handshake() print 'Server subject is', client_ssl.get_peer_certificate().get_subject() client_ssl.close()
def _client(self, sock): """ Create a new client-side SSL L{Connection} object wrapped around C{sock}. """ # Now create the client side Connection. Similar boilerplate to the # above. client_ctx = Context(TLSv1_METHOD) client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE) client_ctx.set_verify( VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_cb) client_store = client_ctx.get_cert_store() client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem)) client_ctx.use_certificate( load_certificate(FILETYPE_PEM, client_cert_pem)) client_ctx.check_privatekey() client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem)) client_conn = Connection(client_ctx, sock) client_conn.set_connect_state() return client_conn
def main(): """ Run an SNI-enabled server which selects between a few certificates in a C{dict} based on the handshake request it receives from a client. """ port = socket() port.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) port.bind(('', 8443)) port.listen(3) print 'Accepting...', stdout.flush() server, addr = port.accept() print 'accepted', addr server_context = Context(TLSv1_METHOD) server_context.set_tlsext_servername_callback(pick_certificate) server_ssl = Connection(server_context, server) server_ssl.set_accept_state() server_ssl.do_handshake() server.close()
def _dump_all_certs(self, cert_file, address): # This will also include intermediate certs context = Context(SSLv23_METHOD) context.set_default_verify_paths() client = socket.socket() client.connect((address, 443)) clientSSL = Connection(context, client) clientSSL.set_connect_state() clientSSL.do_handshake() chains = clientSSL.get_peer_cert_chain() for chain in chains: cert_file.write(dump_certificate(FILETYPE_PEM, chain).decode())
def verify_servercert(host, timeout, capath): server_ctx = Context(TLSv1_METHOD) server_ctx.load_verify_locations(None, capath) server_cert_chain = [] 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 global server_expire server_expire = server_cert_chain[-1].get_notAfter() except PyOpenSSLError as e: raise e finally: server_conn.shutdown() server_conn.close() return True
def _load_verify_locations_test(self, *args): port = socket() port.bind(('', 0)) port.listen(1) client = socket() client.setblocking(False) client.connect_ex(port.getsockname()) clientContext = Context(TLSv1_METHOD) clientContext.load_verify_locations(*args) # Require that the server certificate verify properly or the # connection will fail. clientContext.set_verify( VERIFY_PEER, lambda conn, cert, errno, depth, preverify_ok: preverify_ok) clientSSL = Connection(clientContext, client) clientSSL.set_connect_state() server, _ = port.accept() server.setblocking(False) serverContext = Context(TLSv1_METHOD) serverContext.use_certificate( load_certificate(FILETYPE_PEM, cleartextCertificatePEM)) serverContext.use_privatekey( load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)) serverSSL = Connection(serverContext, server) serverSSL.set_accept_state() for i in range(3): for ssl in clientSSL, serverSSL: try: # Without load_verify_locations above, the handshake # will fail: # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', # 'certificate verify failed')] ssl.do_handshake() except WantReadError: pass cert = clientSSL.get_peer_certificate() self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
def connect(self): print "You are trying to connect..." for x in range(7): if not self.connected: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) context = Context(TLSv1_METHOD) context.use_certificate_file(self.cacertpath) context.set_timeout(2) self.sslsocket = Connection(context,s) self.sslsocket.connect((self.host_addr,self.host_port)) #starting a thread that listen to what server sends which the clients need to be able to send and recive data at the same time t = threading.Thread(target=self.receive) t.daemon = True t.start() if self.sslsocket: self.connected = True print "connection established" #self.authentication("Kalle", "te") t = threading.Thread(target=self.sendinput) t.start() except socket.error: print "You failed to connect, retrying......." time.sleep(5)
class SSLSock(TcpSock): def __init__(self,*args,**kwargs): TcpSock.__init__(self,*args,**kwargs) self.raw_sock=self.sock self.sock=Connection(Context(TLSv1_METHOD),self.raw_sock) self.sock.set_connect_state() self.sock.do_handshake() def sock_recv(self,size,nodata_delay): if size is None: size=self.recv_size try: return self.sock.read(size) except WantReadError: tmout=self.timeout if tmout is None: raise if not select.select([self.sock],[],[],tmout)[0]: raise socket.timeout,"No data in %s seconds"%(tmout,) try: return self.sock.read(size) except ZeroReturnError: return "" except ZeroReturnError: return "" except SysCallError,e: if e[0]==-1: return "" raise
def main(): port = socket() port.bind(('', 0)) port.listen(5) client = socket() client.setblocking(False) client.connect_ex(port.getsockname()) client.setblocking(True) server = port.accept()[0] clientCtx = Context(TLSv1_METHOD) clientCtx.set_cipher_list('ALL:ADH') clientCtx.load_tmp_dh('dhparam.pem') sslClient = Connection(clientCtx, client) sslClient.set_connect_state() serverCtx = Context(TLSv1_METHOD) serverCtx.set_cipher_list('ALL:ADH') serverCtx.load_tmp_dh('dhparam.pem') sslServer = Connection(serverCtx, server) sslServer.set_accept_state() t1 = Thread(target=send, args=(sslClient,)) t2 = Thread(target=send, args=(sslServer,)) t3 = Thread(target=recv, args=(sslClient,)) t4 = Thread(target=recv, args=(sslServer,)) t1.start() t2.start() t3.start() t4.start() t1.join() t2.join() t3.join() t4.join()
def go(): port = socket() port.bind(('', 0)) port.listen(1) called = [] def info(*args): print count.next() called.append(None) return 1 context = Context(TLSv1_METHOD) context.set_verify(VERIFY_PEER, info) context.use_certificate( load_certificate(FILETYPE_PEM, cleartextCertificatePEM)) context.use_privatekey( load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)) while 1: client = socket() client.setblocking(False) client.connect_ex(port.getsockname()) clientSSL = Connection(context, client) clientSSL.set_connect_state() server, ignored = port.accept() server.setblocking(False) serverSSL = Connection(context, server) serverSSL.set_accept_state() del called[:] while not called: for ssl in clientSSL, serverSSL: try: ssl.send('foo') except WantReadError, e: pass
def go(): port = socket() port.bind(('', 0)) port.listen(1) called = [] def info(conn, where, ret): print count.next() called.append(None) context = Context(TLSv1_METHOD) context.set_info_callback(info) context.use_certificate( load_certificate(FILETYPE_PEM, cleartextCertificatePEM)) context.use_privatekey( load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)) while 1: client = socket() client.setblocking(False) client.connect_ex(port.getsockname()) clientSSL = Connection(Context(TLSv1_METHOD), client) clientSSL.set_connect_state() server, ignored = port.accept() server.setblocking(False) serverSSL = Connection(context, server) serverSSL.set_accept_state() del called[:] while not called: for ssl in clientSSL, serverSSL: try: ssl.do_handshake() except WantReadError: pass