def receive_file_descriptors( self, sock: socket.SocketType) -> Tuple[str, dict[str, Any], bool]: """Receive file descriptors. See https://docs.python.org/3/library/socket.html#socket.socket.recvmsg . Protocol: 1. Size of the filenames array (json) (64bites, #filenames_length). 2. Connector name, filenames, presigned flag & file descriptors. 3. Send response in the form {"success": bool, "presigned_urls": list}. """ filenames_length = int.from_bytes(sock.recv(8), byteorder="big") logger.debug("Received file descriptors message of length: %d.", filenames_length) if filenames_length == 0: return ("", dict(), False) fds = array.array("i") # Array of ints msg, ancdata, flags, addr = sock.recvmsg( filenames_length, socket.CMSG_LEN(DESCRIPTOR_CHUNK_SIZE * fds.itemsize)) logger.debug("Received file descriptors: %s, %s.", msg, ancdata) storage_name, filenames, need_presigned_urls = json.loads(msg.decode()) for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: # Append data, ignoring any truncated integers at the end. fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) return (storage_name, dict(zip(filenames, fds)), need_presigned_urls)
def handle_transaction(self, csock: socket.SocketType): logging.debug('handling transaction') data = b'' while len(data) < 12: recvd = csock.recv(12 - len(data)) data += recvd # check for closed connection if not recvd: raise ConnectionResetError logging.debug(f'Received buffer: {repr(data)}') _, _, _, _, dev_id, op = struct.unpack('<HHHHHH', data) # requesting repeat transaction if dev_id in self.devs and self.devs[dev_id].status == op: resp_op = ALREADY logging.info( f'{dev_id}:already {"Registered" if op == REG else "Deregistered"}' ) # record transaction else: self.devs[dev_id] = Device(dev_id, op, csock) resp_op = op logging.info( f'{dev_id}:{"Registered" if op == REG else "Deregistered"}') # send response resp = struct.pack('<2sHHHHh', b'SC', dev_id, SSS_ID, 4, dev_id, resp_op) logging.debug(f'Sending response {repr(data)}') csock.send(resp)
def receive_file_descriptors(self, sock: socket.SocketType) -> dict[str, Any]: """Receive file descriptors. See https://docs.python.org/3/library/socket.html#socket.socket.recvmsg . Protocol: 1. Size of the filenames array (json) (64bites, #filenames_length). 2. Filenames & file descriptors. 3. Wait for single byte to confirm. """ filenames_length = int.from_bytes(sock.recv(8), byteorder="big") logger.debug("Received file descriptors message of length: %d.", filenames_length) if filenames_length == 0: return dict() fds = array.array("i") # Array of ints msg, ancdata, flags, addr = sock.recvmsg( filenames_length, socket.CMSG_LEN(DESCRIPTOR_CHUNK_SIZE * fds.itemsize)) logger.debug("Received file descriptors: %s, %s.", msg, ancdata) filenames = json.loads(msg.decode()) for cmsg_level, cmsg_type, cmsg_data in ancdata: if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: # Append data, ignoring any truncated integers at the end. fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) return dict(zip(filenames, fds))
def __init__(self, server="localhost", port=config.port, password=None): self.server = server self.port = port if password: self.password = md5(password).hexdigest() else: self.password = None self.socket = SocketType()
def _handle_connection(self, connection: SocketType, address: Tuple, callback: Callable) -> None: with connection: data = connection.recv(self.BUFFER_SIZE) task = CommandParser(data).get_command_match() if not task: connection.send(b'ERROR') response = callback(task) connection.send(response)
def __init__(self, request_socket: SocketType, *args, **kwargs): self.path_split: List[str] = [] self.response = HTTPResponse() if self.ssl_wrapper_func is not None: request_socket.settimeout(self.pre_ssl_socket_timeout) request_socket = self.ssl_wrapper_func(request_socket) request_socket.settimeout(self.socket_timeout) super().__init__(request_socket, *args, **kwargs)
def s1mple(s: socket.SocketType): for i in range(100): p = f'[print(x) for x in [[().__class__.__base__.__subclasses__()[{i}]]]]\n' s.sendall(bytes(p, 'utf8')) d = s.recv(8096).replace(b'\n', b'').decode().split('>>>')[0] print(f'[*] {d} : {i}') if i % 2 or s.fileno() == -1: s = connect()
def handle_transaction(self, csock: socket.SocketType): logging.debug('handling transaction') data = b'' reg_packet_len = 32 #need to match controller.c/.h 's definition while len(data) < reg_packet_len: recvd = csock.recv(reg_packet_len - len(data)) data += recvd # check for closed connection if not recvd: raise ConnectionResetError logging.debug(f'Received buffer: {repr(data)}') # _, _, _, _, dev_id, op = struct.unpack('<HHHHHH', data) _, _, _, _, dev_id, op, reg_num, _ = struct.unpack('<HHHHHHL16s', data) valid = True #load all registration number from file numlist = open('/secrets/reg_num_list','r').read() numlist = [list(map(int,i.split(','))) for i in numlist.split('|')[1:]] reg_nums = {} for i in numlist: reg_nums[i[0]] = i[1] #check if the registration number match with the recorded number if reg_num != reg_nums.get(dev_id): logging.info(f'{dev_id}:invaild sed') valid = False # requesting repeat transaction elif dev_id in self.devs and self.devs[dev_id].status == op: resp_op = ALREADY logging.info(f'{dev_id}:already {"Registered" if op == REG else "Deregistered"}') # record transaction else: self.devs[dev_id] = Device(dev_id, op, csock) resp_op = op logging.info(f'{dev_id}:{"Registered" if op == REG else "Deregistered"}') # send response if valid: resp = struct.pack('<2sHHHHhL16s', b'SC', dev_id, SSS_ID, 4+4+16, dev_id, resp_op, 0, KEY) else: #send fake key if the registration isn't vaild resp = struct.pack('<2sHHHHhL16s', b'SC', dev_id, SSS_ID, 4+4+16, dev_id, resp_op, 0, b'\x00'*16) logging.debug(f'Sending response {repr(data)}') csock.send(resp)
def send_int64(socket: SocketType, data: int) -> None: """Sends an int as a 64-bit signed little endian number. Args: socket: The socket to send on. data: The number to send. Raises: RuntimeError: If there was an error sending the data. """ buf = data.to_bytes(8, byteorder='little') socket.sendall(buf)
def __init__(self, game, addresses, port, versionString, adminPassword): self.game = game self.versionString = versionString self.shutdownOrder = False self.adminPassword = adminPassword self.rawConnections = [] self.playerCons = [] self.sockets = [] self.updating = {} self.socketsOpened = [] self.listening = False ### open listener sockets for address in addresses: try: socket = SocketType() socket.setblocking(0) socket.bind((address, port)) socket.listen(10) socket.setblocking(0) print "opened socket on %s:%i" % (address, port) self.sockets.append(socket) self.socketsOpened.append(address) self.listening = True tSocket = Thread(name="socket on %s:%i" % (address, port), target=self.threadListener, args=(socket, )) tSocket.start() except Exception, ex: print "failed to open socket on %s:" % address, ex[1]
async def wait_socket_writable(sock: socket.SocketType) -> None: check_cancelled() if _write_events.get(sock): raise ResourceBusyError('writing to') from None loop = get_running_loop() event = _write_events[sock] = asyncio.Event(loop=loop) loop.add_writer(sock.fileno(), event.set) try: await event.wait() finally: loop.remove_writer(sock) del _write_events[sock] if sock.fileno() == -1: raise ClosedResourceError
def recv_all(socket: SocketType, length: int) -> bytes: """Receive length bytes from a socket. Args: socket: Socket to receive on. length: Number of bytes to receive. Raises: SocketClosed: If the socket was closed by the peer. RuntimeError: If a read error occurred. """ databuf = bytearray(length) received_count = 0 while received_count < length: bytes_left = length - received_count received_now = socket.recv_into( memoryview(databuf)[received_count:], bytes_left) if received_now == 0: raise SocketClosed("Socket closed while receiving") if received_now == -1: raise RuntimeError("Error receiving") received_count += received_now return databuf
def _share_socket(sock: socket.SocketType) -> socket.SocketType: # Windows requires the socket be explicitly shared across # multiple workers (processes). from socket import fromshare # type: ignore sock_data = sock.share(os.getpid()) # type: ignore return fromshare(sock_data)
def __request_client_name(connection: socket.SocketType, clients): '''Send name prompt to client client connection. If the name is already taken it will attempt to reprompt 4 times before moving on.''' msg = "name" msg = json.dumps(msg) names = [] client_info = {NAME: None, CONN: connection} for client in clients: names.append(client) for i in range(4): connection.sendall(msg.encode('utf-8')) client_name = receive_msg(connection, 'client') # client_name = connection.recv(4096).decode('utf-8') if client_name not in names: client_info[NAME] = client_name break return client_info
def __set_keepalive(sock: socket.SocketType, after_idle_sec: int = 1, interval_sec: int = 3, max_fails: int = 5): _logger.debug('Enable TCP keep-alive') sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)
def __init__( self, server="localhost", port=config.port, password=None ): self.server = server self.port = port if password: self.password = md5(password).hexdigest() else: self.password = None self.socket = SocketType()
def run(self, sock: SocketType) -> typing.Any: "reference implementation of how to deal with socket" self.send(b"") while True: for to_send, close, exc, result in self: if to_send: sock.sendall(to_send) if close: sock.close() if exc: raise exc if result is not _no_result: return result data = sock.recv(1024) if not data: raise ParseError("need data") self.send(data)
def send_data( s: socket.SocketType, data: dict, size_bytes: int = 8, encoder: Optional[Type[json.JSONEncoder]] = None, ): """Send data over socket. :param s: socket to send over. :param data: dict that must be serialzable to JSON. :param size_bytes: how first many bytes in message are dedicated to the message size (pre-padded with zeros). :raises: exception on failure. """ message = json.dumps(data, cls=encoder).encode() message_length = len(message).to_bytes(size_bytes, byteorder="big") s.sendall(message_length) s.sendall(message)
async def wait_socket_writable(sock: socket.SocketType) -> None: check_cancelled() loop = get_running_loop() event = asyncio.Event(loop=loop) loop.add_writer(sock.fileno(), event.set) try: await event.wait() finally: loop.remove_writer(sock)
def receive_msg(sock: socket.SocketType, from_: str): data = sock.recv(4096) if not data: return data res = data.decode('utf-8') if isinstance(res, dict): print(from_, '>>', res.__dict__) else: print(from_, '>>', res.replace('\\', '')) return res
def send_data( s: socket.SocketType, data: dict, size_bytes: int = 5, encoder: Optional[Type[json.JSONEncoder]] = None, ): """Send data over socket. :param s: socket to send over. :param data: dict that must be serialzable to JSON. :param size_bytes: how first many bytes in message are dedicated to the message size (pre-padded with zeros). :raises: exception on failure. """ message = json.dumps(data, cls=encoder).encode() message_length = "{length:0{size}d}".format( length=len(message), size=size_bytes).encode("utf-8") bytes_to_send = message_length + message s.sendall(bytes_to_send)
def wrap_socket(self, sock: socket.SocketType) -> socket.SocketType: """ Check the first byte of the TCP request for a TLS handshake by looking for the SYN (\x16) and wrap the connection in a TLS context. This will wait for the first byte to be received through the socket, therefore it should be treated as *blocking* and should only be invoked from inside of the handler thread/forked process. """ if self.context: if sock.recv(1, socket.MSG_PEEK) == b"\x16": return self.context.wrap_socket(sock, server_side=True) return sock
def __init__(self, client: socket.SocketType): """ Initialize a new Pty Handler. This will handle creating the PTY and setting the local terminal to raw. It also maintains the state to open a local terminal if requested and exit raw mode. """ self.client = client self.state = "normal" self.saved_term_state = None self.input = b"" self.lhost = None self.known_binaries = {} self.vars = {"lhost": None} # Ensure history is disabled util.info("disabling remote command history", overlay=True) client.sendall(b"unset HISTFILE\n") util.info("setting terminal prompt", overlay=True) client.sendall(b'export PS1="(remote) \\u@\\h\\$ "\n\n') # Locate interesting binaries for name, friendly, priority in PtyHandler.INTERESTING_BINARIES: util.info(f"resolving remote binary: {name}", overlay=True) # We already found a preferred option if ( friendly in self.known_binaries and self.known_binaries[friendly][1] > priority ): continue # Look for the given binary response = self.run(f"which {shlex.quote(name)}", has_pty=False) if response == b"": continue self.known_binaries[friendly] = (response.decode("utf-8"), priority) for m, cmd in PtyHandler.OPEN_METHODS.items(): if m in self.known_binaries: method_cmd = cmd.format(self.known_binaries[m][0]) method = m break else: util.error("no available methods to spawn a pty!") raise RuntimeError("no available methods to spawn a pty!") # Open the PTY util.info(f"opening pseudoterminal via {method}", overlay=True) client.sendall(method_cmd.encode("utf-8") + b"\n") # Synchronize the terminals util.info("synchronizing terminal state", overlay=True) self.do_sync([]) # Force the local TTY to enter raw mode self.enter_raw()
def __wait_for_client_connections(server_socket: socket.SocketType, server_addr, no_clients, timeout, max_games): '''Sets the timeout and waits for client connections. If the socket timesout the sever closes sockets and exits''' server_socket.settimeout(float(timeout)) clients = [] start = time.perf_counter() while len(clients) < no_clients * max_games: start = time.perf_counter() try: conn, addr = server_socket.accept() __send_server_welcome(conn, server_addr[0]) client_info = __request_client_name(conn, clients) clients.append(client_info) except socket.timeout: end = time.perf_counter() dur = int(end - start) for client in clients: client[CONN].close() print( 'Timeout: {} seconds have passed since last player connected'. format(dur)) server_socket.close() exit() return clients
def read_bytes(s: socket.SocketType, message_size: int) -> bytes: """Read message_size bytes from the given socket. The method will block until enough bytes are available. :param message_size: size (in bytes) of the message to read. :returns: received message. """ message = b"" while len(message) < message_size: received = s.recv(message_size - len(message)) message += received if not received: return message return message
def _handle_client(self, client_socket : socket.SocketType): print("Connection started: %s" % client_socket) try: while True: request = client_socket.recv(BUFFERSIZE).decode('utf-8') print("Got a request: %s (length: %s)" % (request, len(request))) if request.startswith("ECHO "): print("SEND ECHO") client_socket.send(request[len("ECHO "):].encode()) elif request.startswith("EXEC "): cmd = request[(len("EXEC ")):] result = 'EXEC RESULT: %s' % '\n'.join(os.popen(cmd).readlines()) print("THE LINES: %s" % result) client_socket.send(result.encode()) else: print('Close connection: %s' % request) client_socket.close() return except socket.error: pass print('Closing socket.') client_socket.close()
def checkSmtp(): """ Make a connection socket test into STMP server. Return status code of SocketType.connect_ex(). """ try : S = SocketType() S.settimeout(2) smtpStatus = S.connect_ex( ( settings.SNAFU['smtp-server'],settings.SNAFU['smtp-port']) ) S.close() except (error,gaierror), e : smtpStatus = e return smtpStatus
async def wait_socket_writable(sock: socket.SocketType) -> None: check_cancelled() if _write_events.get(sock): raise ResourceBusyError('writing to') from None loop = get_running_loop() event = _write_events[sock] = asyncio.Event(loop=loop) loop.add_writer(sock.fileno(), event.set) try: await event.wait() finally: if _write_events.pop(sock, None) is not None: loop.remove_writer(sock) writable = True else: writable = False if not writable: raise ClosedResourceError
class Admin: def __init__( self, server="localhost", port=config.port, password=None ): self.server = server self.port = port if password: self.password = md5(password).hexdigest() else: self.password = None self.socket = SocketType() def connect( self ): self.socket.connect( ( self.server, self.port ) ) def sendMessage( self, message ): if self.password: self.socket.send( message+" "+self.password+"\n" ) else: self.socket.send( message+"\n" ) def quit( self ): self.socket.close()
class Admin: def __init__(self, server="localhost", port=config.port, password=None): self.server = server self.port = port if password: self.password = md5(password).hexdigest() else: self.password = None self.socket = SocketType() def connect(self): self.socket.connect((self.server, self.port)) def sendMessage(self, message): if self.password: self.socket.send(message + " " + self.password + "\n") else: self.socket.send(message + "\n") def quit(self): self.socket.close()
def data_receiver(sock: socket.SocketType, queue: Queue, buff_size=1024): buffer = b"" while True: if len(buffer) > 4: size = buffer[:4] size = int.from_bytes(size, 'big') if len(buffer) >= 4 + size: queue.put(buffer[4:4 + size]) buffer = buffer[4 + size:] continue received = sock.recv(buff_size) if len(received) == 0: print("Received 0 bytes, exiting client thread...") queue.put("EXIT".encode()) break buffer += received
def is_on(self): """ Make a connection socket test. """ from urlparse import urlsplit S = SocketType() S.settimeout(2) errno = S.connect_ex((urlsplit(settings.SNAFU['glpi-url']).netloc, 80)) S.close() if errno < 0 : return False return True
def handle(self, sock: socket.SocketType, addr): print('connected', addr) buf = "" while True: try: data = bytes(sock.recv(4096)) data = data.decode('UTF-8') buf += data while True: idx = buf.find('\n') if idx < 0: break part = buf[:idx] if part: try: self.cmd(part) except Exception as e: print('exc: ' + str(e)) buf = buf[idx + 1:] except ConnectionResetError: print('closed', addr) break
def _handler(self, socket_obj: socket.SocketType, address: Tuple[str, int]): while not self._stop.ready(): try: raw = receive(socket_obj) # BLOCK except OSError as e: self.log("?", e, "Call failed", "WARNING") return if not raw: return try: method, json = Request.decode(raw).values except Tcp500 as e: try: method, _ = str(raw[:-1], encoding="utf-8").split("\n", 1) except: method = str(None) self.log(method, "500", str(e.args), "WARNING") socket_obj.sendall(Response(e.status, e).encode()) return if method not in self.methods_map: e = Tcp404("method not found") self.log(method, "404", "Method not found", "WARNING") socket_obj.sendall(Response(e.status, e).encode()) return try: resp = self.methods_map[method](json) self.log(method, "200", "", "INFO") except ATcpException as e: self.log(method, str(e.status), str(e.args), "WARNING") resp = Response(e.status, e.text) except Exception as e: self.log(method, "500", str(e.args), "WARNING") resp = Response(500, "Fail") else: if type(resp) is tuple: resp = Response(*resp) socket_obj.sendall(resp.encode())
def accept_from_socket(server_socket: socket.SocketType) -> Tuple[socket.SocketType, str]: """ Accept from the sever socket a client socket :param server_socket: The Server's Socket :return: The client socket and the address of the client """ return server_socket.accept()