def handle_messages(self): self.c.establish_server_connection() server = "%s:%s" % self.c.server_conn.address()[:2] buf = memoryview(bytearray(self.chunk_size)) conns = [self.c.client_conn.rfile, self.c.server_conn.rfile] while not self.c.close: r, _, _ = select.select(conns, [], [], 10) for rfile in r: if self.c.client_conn.rfile == rfile: src, dst = self.c.client_conn, self.c.server_conn direction = "-> tcp ->" src_str, dst_str = "client", server else: dst, src = self.c.client_conn, self.c.server_conn direction = "<- tcp <-" dst_str, src_str = "client", server closed = False if src.ssl_established: # Unfortunately, pyOpenSSL lacks a recv_into function. contents = src.rfile.read( 1 ) # We need to read a single byte before .pending() becomes usable contents += src.rfile.read(src.connection.pending()) if not contents: closed = True else: size = src.connection.recv_into(buf) if not size: closed = True if closed: conns.remove(src.rfile) # Shutdown connection to the other peer if dst.ssl_established: dst.connection.shutdown() else: dst.connection.shutdown(socket.SHUT_WR) if len(conns) == 0: self.c.close = True continue if src.ssl_established or dst.ssl_established: # if one of the peers is over SSL, we need to send bytes/strings if not src.ssl_established: # only ssl to dst, i.e. we revc'd into buf but need bytes/string now. contents = buf[:size].tobytes() self.c.log( "%s %s\r\n%s" % (direction, dst_str, cleanBin(contents)), "debug") dst.connection.send(contents) else: # socket.socket.send supports raw bytearrays/memoryviews self.c.log( "%s %s\r\n%s" % (direction, dst_str, cleanBin(buf.tobytes())), "debug") dst.connection.send(buf[:size])
def handle_messages(self): self.c.establish_server_connection() server = "%s:%s" % self.c.server_conn.address()[:2] buf = memoryview(bytearray(self.chunk_size)) conns = [self.c.client_conn.rfile, self.c.server_conn.rfile] try: while True: r, _, _ = select.select(conns, [], [], 10) for rfile in r: if self.c.client_conn.rfile == rfile: src, dst = self.c.client_conn, self.c.server_conn direction = "-> tcp ->" src_str, dst_str = "client", server else: dst, src = self.c.client_conn, self.c.server_conn direction = "<- tcp <-" dst_str, src_str = "client", server closed = False if src.ssl_established: # Unfortunately, pyOpenSSL lacks a recv_into function. contents = src.rfile.read(1) # We need to read a single byte before .pending() becomes usable contents += src.rfile.read(src.connection.pending()) if not contents: closed = True else: size = src.connection.recv_into(buf) if not size: closed = True if closed: conns.remove(src.rfile) # Shutdown connection to the other peer if dst.ssl_established: dst.connection.shutdown() else: dst.connection.shutdown(socket.SHUT_WR) if len(conns) == 0: return continue if src.ssl_established or dst.ssl_established: # if one of the peers is over SSL, we need to send bytes/strings if not src.ssl_established: # only ssl to dst, i.e. we revc'd into buf but need bytes/string now. contents = buf[:size].tobytes() self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(contents)), "debug") dst.connection.send(contents) else: # socket.socket.send supports raw bytearrays/memoryviews self.c.log("%s %s\r\n%s" % (direction, dst_str, cleanBin(buf.tobytes())), "debug") dst.connection.send(buf[:size]) except socket.error as e: self.c.log("TCP connection closed unexpectedly.", "debug") return
def __call__(self): self.connect() buf = memoryview(bytearray(self.chunk_size)) client = self.client_conn.connection server = self.server_conn.connection conns = [client, server] try: while True: r, _, _ = select.select(conns, [], [], 10) for conn in r: dst = server if conn == client else client size = conn.recv_into(buf, self.chunk_size) if not size: conns.remove(conn) # Shutdown connection to the other peer if isinstance(conn, SSL.Connection): # We can't half-close a connection, so we just close everything here. # Sockets will be cleaned up on a higher level. return else: dst.shutdown(socket.SHUT_WR) if len(conns) == 0: return continue dst.sendall(buf[:size]) if self.logging: # log messages are prepended with the client address, # hence the "weird" direction string. if dst == server: direction = "-> tcp -> {}".format(repr(self.server_conn.address)) else: direction = "<- tcp <- {}".format(repr(self.server_conn.address)) data = cleanBin(buf[:size].tobytes()) self.log( "{}\r\n{}".format(direction, data), "info" ) except (socket.error, NetLibError, SSL.Error) as e: raise ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e)), e)
def __call__(self): self.connect() buf = memoryview(bytearray(self.chunk_size)) client = self.client_conn.connection server = self.server_conn.connection conns = [client, server] try: while True: r, _, _ = select.select(conns, [], [], 10) for conn in r: dst = server if conn == client else client size = conn.recv_into(buf, self.chunk_size) if not size: conns.remove(conn) # Shutdown connection to the other peer if isinstance(conn, SSL.Connection): # We can't half-close a connection, so we just close everything here. # Sockets will be cleaned up on a higher level. return else: dst.shutdown(socket.SHUT_WR) if len(conns) == 0: return continue dst.sendall(buf[:size]) if self.logging: # log messages are prepended with the client address, # hence the "weird" direction string. if dst == server: direction = "-> tcp -> {}".format( repr(self.server_conn.address)) else: direction = "<- tcp <- {}".format( repr(self.server_conn.address)) data = cleanBin(buf[:size].tobytes()) self.log("{}\r\n{}".format(direction, data), "info") except (socket.error, NetLibError, SSL.Error) as e: raise ProtocolException( "TCP connection closed unexpectedly: {}".format(repr(e)), e)
def handle_messages(self): self.c.establish_server_connection() server = "%s:%s" % self.c.server_conn.address()[:2] buf = memoryview(bytearray(self.chunk_size)) conns = [self.c.client_conn.rfile, self.c.server_conn.rfile] try: while True: r, _, _ = select.select(conns, [], [], 10) for rfile in r: if self.c.client_conn.rfile == rfile: src, dst = self.c.client_conn, self.c.server_conn direction = "-> tcp ->" src_str, dst_str = "client", server else: dst, src = self.c.client_conn, self.c.server_conn direction = "<- tcp <-" dst_str, src_str = "client", server closed = False if src.ssl_established: # Unfortunately, pyOpenSSL lacks a recv_into function. # We need to read a single byte before .pending() # becomes usable contents = src.rfile.read(1) contents += src.rfile.read(src.connection.pending()) if not contents: closed = True else: size = src.connection.recv_into(buf) if not size: closed = True if closed: conns.remove(src.rfile) # Shutdown connection to the other peer if dst.ssl_established: # We can't half-close a connection, so we just close everything here. # Sockets will be cleaned up on a higher level. return else: dst.connection.shutdown(socket.SHUT_WR) if len(conns) == 0: return continue if src.ssl_established or dst.ssl_established: # if one of the peers is over SSL, we need to send # bytes/strings if not src.ssl_established: # we revc'd into buf but need bytes/string now. contents = buf[:size].tobytes() if self.log: self.c.log( "%s %s\r\n%s" % (direction, dst_str, cleanBin(contents)), "info") # Do not use dst.connection.send here, which may raise OpenSSL-specific errors. dst.send(contents) else: # socket.socket.send supports raw bytearrays/memoryviews if self.log: self.c.log( "%s %s\r\n%s" % (direction, dst_str, cleanBin(buf.tobytes())), "info") dst.connection.send(buf[:size]) except (socket.error, NetLibError) as e: self.c.log("TCP connection closed unexpectedly.", "debug") return
def handle_messages(self): self.c.establish_server_connection() server = "%s:%s" % self.c.server_conn.address()[:2] buf = memoryview(bytearray(self.chunk_size)) conns = [self.c.client_conn.rfile, self.c.server_conn.rfile] try: while True: r, _, _ = select.select(conns, [], [], 10) for rfile in r: if self.c.client_conn.rfile == rfile: src, dst = self.c.client_conn, self.c.server_conn direction = "-> tcp ->" src_str, dst_str = "client", server else: dst, src = self.c.client_conn, self.c.server_conn direction = "<- tcp <-" dst_str, src_str = "client", server closed = False if src.ssl_established: # Unfortunately, pyOpenSSL lacks a recv_into function. # We need to read a single byte before .pending() # becomes usable contents = src.rfile.read(1) contents += src.rfile.read(src.connection.pending()) if not contents: closed = True else: size = src.connection.recv_into(buf) if not size: closed = True if closed: conns.remove(src.rfile) # Shutdown connection to the other peer if dst.ssl_established: # We can't half-close a connection, so we just close everything here. # Sockets will be cleaned up on a higher level. return else: dst.connection.shutdown(socket.SHUT_WR) if len(conns) == 0: return continue if src.ssl_established or dst.ssl_established: # if one of the peers is over SSL, we need to send # bytes/strings if not src.ssl_established: # we revc'd into buf but need bytes/string now. contents = buf[:size].tobytes() if self.log: self.c.log( "%s %s\r\n%s" % ( direction, dst_str, cleanBin(contents) ), "info" ) # Do not use dst.connection.send here, which may raise OpenSSL-specific errors. dst.send(contents) else: # socket.socket.send supports raw bytearrays/memoryviews if self.log: self.c.log( "%s %s\r\n%s" % ( direction, dst_str, cleanBin(buf.tobytes()) ), "info" ) dst.connection.send(buf[:size]) except (socket.error, NetLibError) as e: self.c.log("TCP connection closed unexpectedly.", "debug") return
def test_cleanBin(): assert utils.cleanBin("one") == "one" assert utils.cleanBin("\00ne") == ".ne" assert utils.cleanBin("\nne") == "\nne" assert utils.cleanBin("\nne", True) == ".ne"
def handle_messages(self): self.c.establish_server_connection() server = "%s:%s" % self.c.server_conn.address()[:2] buf = memoryview(bytearray(self.chunk_size)) conns = [self.c.client_conn.rfile, self.c.server_conn.rfile] bindump = open("dump.%s.bin" % str(time.time()), "w+b") counter = 0 try: while True: r, _, _ = select.select(conns, [], [], 10) for rfile in r: size = None if self.c.client_conn.rfile == rfile: src, dst = self.c.client_conn, self.c.server_conn direction = "-> tcp ->" src_str, dst_str = "client", server else: dst, src = self.c.client_conn, self.c.server_conn direction = "<- tcp <-" dst_str, src_str = "client", server closed = False if src.ssl_established: # Unfortunately, pyOpenSSL lacks a recv_into function. # We need to read a single byte before .pending() # becomes usable contents = src.rfile.read(1) contents += src.rfile.read(src.connection.pending()) if not contents: closed = True else: size = len(contents) else: size = src.connection.recv_into(buf) if not size: closed = True if closed: conns.remove(src.rfile) # Shutdown connection to the other peer if dst.ssl_established: dst.connection.shutdown() else: dst.connection.shutdown(socket.SHUT_WR) if len(conns) == 0: return continue if src.ssl_established or dst.ssl_established: # if one of the peers is over SSL, we need to send # bytes/strings if not src.ssl_established: # we revc'd into buf but need bytes/string now. contents = buf[:size].tobytes() if self.log: self.c.log( "%s %s\r\n%s" % ( direction, dst_str, cleanBin(contents) ), "info" ) bindump.write(struct.pack('iiii', 0x544b4350, int(self.c.client_conn.rfile == rfile), size or 0, counter)) bindump.write(contents) bindump.write(bytearray(15 & (16 - (len(contents) & 15)))) bindump.flush() counter = counter + 1 dst.connection.send(contents) else: # socket.socket.send supports raw bytearrays/memoryviews if self.log: self.c.log( "%s %s\r\n%s" % ( direction, dst_str, cleanBin(buf.tobytes()) ), "info" ) bindump.write(struct.pack('iiii', 0x544b4350, int(self.c.client_conn.rfile == rfile), size or 0, counter)) bindump.write(buf[:size]) bindump.write(bytearray(15 & (16 - (size & 15)))) bindump.flush() counter = counter + 1 dst.connection.send(buf[:size]) except socket.error as e: self.c.log("TCP connection closed unexpectedly.", "debug") return
def human_readable(self): ret = self.header.human_readable() if self.payload: ret = ret + "\nPayload:\n" + utils.cleanBin(self.payload) return ret