def _process_server_event(self, unix_fd, oc_fd, data): status = True server_data = None fd, event_no = data if fd == oc_fd: # self.logger.debug("received event '%d' on oc socket" # % event_no) if event_no & POLLHUP > 0: # FIXME: notify IN channel? self.logger.debug("connection closed from OC") status = False elif event_no & POLLIN > 0: oc_packet = RPCPacket.from_file(self.oc_conn, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) if isinstance(oc_packet, RPCRTSPacket): raise Exception("Unexpected rts packet received") self.logger.debug("sending data to client") self.bytes_read = self.bytes_read + oc_packet.size server_data = oc_packet.data elif fd == unix_fd: if event_no & POLLHUP > 0: # FIXME: notify IN channel? self.logger.debug("connection closed from IN channel") status = False elif event_no & POLLIN > 0: oc_packet = RPCPacket.from_file(self.unix_socket, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) if not isinstance(oc_packet, RPCRTSPacket): raise Exception( 'Unexpected non-RTS RPC packet received from IN channel' ) if RTS_CMD_CUSTOM_OUT in map(itemgetter('type'), oc_packet.commands): self.logger.debug('Notified the IN channel has left out') status = False else: self.logger.debug('Sending RTS RPC packet to client') self.bytes_read += oc_packet.size server_data = oc_packet.data else: raise Exception("invalid poll event: %s" % str(data)) return (status, server_data)
def _process_server_event(self, unix_fd, oc_fd, data): status = True server_data = None fd, event_no = data if fd == oc_fd: # self.logger.debug("received event '%d' on oc socket" # % event_no) if event_no & POLLHUP > 0: # FIXME: notify IN channel? self.logger.debug("connection closed from OC") status = False elif event_no & POLLIN > 0: oc_packet = RPCPacket.from_file(self.oc_conn, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) if isinstance(oc_packet, RPCRTSPacket): raise Exception("Unexpected rts packet received") self.logger.debug("sending data to client") self.bytes_read = self.bytes_read + oc_packet.size server_data = oc_packet.data elif fd == unix_fd: if event_no & POLLHUP > 0: # FIXME: notify IN channel? self.logger.debug("connection closed from IN channel") status = False elif event_no & POLLIN > 0: oc_packet = RPCPacket.from_file(self.unix_socket, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) if not isinstance(oc_packet, RPCRTSPacket): raise Exception('Unexpected non-RTS RPC packet received from IN channel') if RTS_CMD_CUSTOM_OUT in map(itemgetter('type'), oc_packet.commands): self.logger.debug('Notified the IN channel has left out') status = False else: self.logger.debug('Sending RTS RPC packet to client') self.bytes_read += oc_packet.size server_data = oc_packet.data else: raise Exception("invalid poll event: %s" % str(data)) return (status, server_data)
def _runloop(self): self.logger.debug("runloop") status = True while status: try: oc_packet = RPCPacket.from_file(self.client_socket, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) self.bytes_read = self.bytes_read + oc_packet.size if isinstance(oc_packet, RPCRTSPacket): labels = [ RTS_CMD_DATA_LABELS[command["type"]] for command in oc_packet.commands ] self.logger.debug("ignored RTS packet with commands: %s" % ", ".join(labels)) else: self.logger.debug("sending packet to OC") self.oc_conn.sendall(oc_packet.data) self.bytes_written = self.bytes_written + oc_packet.size except IOError: status = False self.logger.debug("handling socket.error: %s" % str(sys.exc_info())) # exc = sys.exc_info() self.logger.error("client connection closed")
def _process_server_event(self, unix_fd, oc_fd, data): status = True server_data = None fd, event_no = data if fd == oc_fd: # self.logger.debug("received event '%d' on oc socket" # % event_no) if event_no & POLLHUP > 0: # FIXME: notify IN channel? self.logger.debug("connection closed from OC") status = False elif event_no & POLLIN > 0: oc_packet = RPCPacket.from_file(self.oc_conn, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) if isinstance(oc_packet, RPCRTSPacket): raise Exception("Unexpected rts packet received") self.logger.debug("sending data to client") self.bytes_read = self.bytes_read + oc_packet.size server_data = oc_packet.data elif fd == unix_fd: if event_no & POLLHUP > 0: # FIXME: notify IN channel? self.logger.debug("connection closed from IN channel") status = False self.logger.debug("ignored event '%d' on unix socket (closing)" % event_no) # FIXME: we should listen to what the IN channel has to say status = False else: raise Exception("invalid poll event: %s" % str(data)) return (status, server_data)
def _handle_auth(self, client_id, ntlm_payload): self.log.debug("* client auth stage1") server = self.client_data[client_id]["server"] self.log.debug("host: %s", str(server.getsockname())) self.log.debug("building auth_3 and ping packets") packet = RPCAuth3OutPacket() packet.ntlm_payload = ntlm_payload server.sendall(packet.make()) # FIXME, this is a hack: # A ping at this stage will trigger a connection close from Samba and # an error from Exchange. Since a successful authentication does not # trigger a response from the server, this provides a simple way to # ensure that it passed, without actually performing an RPC operation # on the "mgmt" interface. The choice of "mgmt" was due to the fact # that we want to keep this authenticator middleware to be reusable # for other Samba services while "mgmt" seemes to be the only # available interface from Samba outside of the ones provided by # OpenChange. packet = RPCPingOutPacket() packet.call_id = 2 server.sendall(packet.make()) self.log.debug("sent auth3 and ping packets, receiving response") try: packet = RPCPacket.from_file(server) if isinstance(packet, RPCFaultPacket): if packet.header["call_id"] == 2: # the Fault packet related to our Ping operation response = 1 else: response = 0 else: raise ValueError("unexpected packet") except socket_error: # Samba closed the connection response = 1 except struct_error: # Samba closed the connection response = 1 if response == 1: self.client_data[client_id]["status"] = "ok" del self.client_data[client_id]["server"] self.log.debug("Authentication completed") else: # we start over with the whole process self.log.debug("Authentication not completed starting over again") del self.client_data[client_id] _safe_close(server) self.log.debug("* done with client auth stage1") return response
def _handle_negotiate(self, client_id, ntlm_payload): self.log.debug("* client auth stage0") self.log.debug("connecting to host") server = None connected = False attempt = 0 while not connected and attempt < SAMBA_CONNECT_MAX_TRIES: try: attempt = attempt + 1 # TODO: we should query port 135 for the right service server = socket(AF_INET, SOCK_STREAM) server.connect((self.samba_host, SAMBA_PORT)) connected = True except: self.log.error( "NTLMAuthHandler: caught exception when" " connecting to samba host: attempt %d", attempt) sleep(1) if not connected: raise Exception("NTLMAuthHandler: unable to connect to samba host" " aborting after %d attempts" % attempt) self.log.debug("server.sockname: %s", str(server.getsockname())) self.log.debug("building bind packet") packet = RPCBindOutPacket() packet.ntlm_payload = ntlm_payload self.log.debug("sending bind packet") server.sendall(packet.make()) self.log.debug("sent bind packet, receiving response") packet = RPCPacket.from_file(server) self.log.debug("response parsed: %s", packet.pretty_dump()) if isinstance(packet, RPCBindACKPacket): self.log.debug("ACK received") self.client_data[client_id] = { "status": "challenged", "last_used": time(), "server": server } response = 1 ntlm_payload = packet.ntlm_payload else: response = 0 ntlm_payload = "" self.log.debug("* done with client auth stage0") return (response, ntlm_payload)
def _receive_conn_a1(self): # receive the cookie # TODO: validation of CONN/A1 self.logger.debug("receiving CONN/A1") packet = RPCPacket.from_file(self.client_socket, self.logger) if not isinstance(packet, RPCRTSPacket): raise Exception("Unexpected non-rts packet received for CONN/A1") self.logger.debug("packet headers = " + packet.pretty_dump()) self.connection_cookie = str(UUID(bytes_le=packet.commands[1]["Cookie"])) self.channel_cookie = str(UUID(bytes_le=packet.commands[2]["Cookie"]))
def _receive_conn_a1(self): # receive the cookie # TODO: validation of CONN/A1 self.logger.debug("receiving CONN/A1") packet = RPCPacket.from_file(self.client_socket, self.logger) if not isinstance(packet, RPCRTSPacket): raise Exception("Unexpected non-rts packet received for CONN/A1") self.logger.debug("packet headers = " + packet.pretty_dump()) self.connection_cookie = str(UUID(bytes=packet.commands[1]["Cookie"])) self.channel_cookie = str(UUID(bytes=packet.commands[2]["Cookie"]))
def _handle_negotiate(self, client_id, ntlm_payload): self.log.debug("* client auth stage0") self.log.debug("connecting to host") server = None connected = False attempt = 0 while not connected and attempt < SAMBA_CONNECT_MAX_TRIES : try: attempt = attempt + 1 # TODO: we should query port 135 for the right service server = socket(AF_INET, SOCK_STREAM) server.connect((self.samba_host, SAMBA_PORT)) connected = True except: self.log.error("NTLMAuthHandler: caught exception when" " connecting to samba host: attempt %d", attempt) sleep(1) if not connected: raise Exception("NTLMAuthHandler: unable to connect to samba host" " aborting after %d attempts" % attempt) self.log.debug("server.sockname: %s", str(server.getsockname())) self.log.debug("building bind packet") packet = RPCBindOutPacket() packet.ntlm_payload = ntlm_payload self.log.debug("sending bind packet") server.sendall(packet.make()) self.log.debug("sent bind packet, receiving response") packet = RPCPacket.from_file(server) self.log.debug("response parsed: %s", packet.pretty_dump()) if isinstance(packet, RPCBindACKPacket): self.log.debug("ACK received") self.client_data[client_id] = {"status": "challenged", "last_used": time(), "server": server} response = 1 ntlm_payload = packet.ntlm_payload else: response = 0 ntlm_payload = "" self.log.debug("* done with client auth stage0") return (response, ntlm_payload)
def _handle_negotiate(self, client_id, ntlm_payload): # print >> sys.stderr, "* client auth stage0" # print >> sys.stderr, "connecting to host" server = None connected = False attempt = 0 while not connected: try: attempt = attempt + 1 # TODO: we should query port 135 for the right service server = socket(AF_INET, SOCK_STREAM) server.connect((self.samba_host, SAMBA_PORT)) connected = True except: print >> sys.stderr, ("NTLMAuthHandler: caught exception when" " connecting to samba host: attempt %d" % attempt) sleep(1) # print >> sys.stderr, "host: %s" % str(server.getsockname()) # print >> sys.stderr, "building bind packet" packet = RPCBindOutPacket() packet.ntlm_payload = ntlm_payload # print >> sys.stderr, "sending bind packet" server.sendall(packet.make()) # print >> sys.stderr, "sent bind packet, receiving response" packet = RPCPacket.from_file(server) # print >> sys.stderr, "response parsed: %s" % packet.pretty_dump() if isinstance(packet, RPCBindACKPacket): # print >> sys.stderr, "ACK received" self.client_data[client_id] = { "status": "challenged", "last_used": time(), "server": server } response = 1 ntlm_payload = packet.ntlm_payload else: response = 0 ntlm_payload = "" # print >> sys.stderr, "* done with client auth stage0" return (response, ntlm_payload)
def _receive_conn_b1(self): # CONN/B1 RTS PDU (TODO: validation) # receive the cookie self.logger.debug("receiving CONN/B1") packet = RPCPacket.from_file(self.client_socket, self.logger) if not isinstance(packet, RPCRTSPacket): raise Exception("Unexpected non-rts packet received for CONN/B1") self.logger.debug("packet headers = " + packet.pretty_dump()) self.connection_cookie = str(UUID(bytes_le=packet.commands[1]["Cookie"])) self.channel_cookie = str(UUID(bytes_le=packet.commands[2]["Cookie"])) self.client_keepalive = packet.commands[4]["ClientKeepalive"] self.association_group_id = str(UUID(bytes_le=packet.commands[5]["AssociationGroupId"])) self.bytes_read = self.bytes_read + packet.size
def _receive_conn_b1(self): # CONN/B1 RTS PDU (TODO: validation) # receive the cookie self.logger.debug("receiving CONN/B1") packet = RPCPacket.from_file(self.client_socket, self.logger) if not isinstance(packet, RPCRTSPacket): raise Exception("Unexpected non-rts packet received for CONN/B1") self.logger.debug("packet headers = " + packet.pretty_dump()) self.connection_cookie = str(UUID(bytes=packet.commands[1]["Cookie"])) self.channel_cookie = str(UUID(bytes=packet.commands[2]["Cookie"])) self.client_keepalive = packet.commands[4]["ClientKeepalive"] self.association_group_id = str(UUID(bytes=packet.commands[5] \ ["AssociationGroupId"])) self.bytes_read = self.bytes_read + packet.size
def _handle_negotiate(self, client_id, ntlm_payload): # print >> sys.stderr, "* client auth stage0" # print >> sys.stderr, "connecting to host" server = None connected = False attempt = 0 while not connected: try: attempt = attempt + 1 # TODO: we should query port 135 for the right service server = socket(AF_INET, SOCK_STREAM) server.connect((self.samba_host, SAMBA_PORT)) connected = True except: print >>sys.stderr, ( "NTLMAuthHandler: caught exception when" " connecting to samba host: attempt %d" % attempt ) sleep(1) # print >> sys.stderr, "host: %s" % str(server.getsockname()) # print >> sys.stderr, "building bind packet" packet = RPCBindOutPacket() packet.ntlm_payload = ntlm_payload # print >> sys.stderr, "sending bind packet" server.sendall(packet.make()) # print >> sys.stderr, "sent bind packet, receiving response" packet = RPCPacket.from_file(server) # print >> sys.stderr, "response parsed: %s" % packet.pretty_dump() if isinstance(packet, RPCBindACKPacket): # print >> sys.stderr, "ACK received" self.client_data[client_id] = {"status": "challenged", "last_used": time(), "server": server} response = 1 ntlm_payload = packet.ntlm_payload else: response = 0 ntlm_payload = "" # print >> sys.stderr, "* done with client auth stage0" return (response, ntlm_payload)
def _runloop(self): self.logger.debug("runloop") status = True while status: try: oc_packet = RPCPacket.from_file(self.client_socket, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) self.bytes_read = self.bytes_read + oc_packet.size if isinstance(oc_packet, RPCRTSPacket): labels = [RTS_CMD_DATA_LABELS[command["type"]] for command in oc_packet.commands] self.logger.debug("ignored RTS packet with commands: %s" % ", ".join(labels)) else: self.logger.debug("sending packet to OC") self.oc_conn.sendall(oc_packet.data) self.bytes_written = self.bytes_written + oc_packet.size except IOError: status = False self.logger.debug("handling socket.error: %s" % str(sys.exc_info())) # exc = sys.exc_info() self.logger.error("client connection closed")
def _runloop(self): self.logger.debug("runloop") status = True while status: try: oc_packet = RPCPacket.from_file(self.client_socket, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) self.bytes_read = self.bytes_read + oc_packet.size if isinstance(oc_packet, RPCRTSPacket): labels = [ RTS_CMD_DATA_LABELS[command["type"]] for command in oc_packet.commands ] self.logger.debug("ignored RTS packet with commands: %s" % ", ".join(labels)) else: self.logger.debug("sending packet to OC") self.oc_conn.sendall(oc_packet.data) self.bytes_written = self.bytes_written + oc_packet.size # Flow control (only subject to RPC PDUs) self.local_available_window -= oc_packet.size self.rpc_pdu_bytes_received += oc_packet.size # This check can be any as it is not explicitly specified if self.local_available_window < self.window_size / 2: self._send_flow_control_ack() self.local_available_window = self.window_size except IOError: status = False self.logger.debug("handling socket.error: %s" % str(sys.exc_info())) # exc = sys.exc_info() self.logger.error("client connection closed")
def _runloop(self): self.logger.debug("runloop") status = True while status: try: oc_packet = RPCPacket.from_file(self.client_socket, self.logger) self.logger.debug("packet headers = " + oc_packet.pretty_dump()) self.bytes_read = self.bytes_read + oc_packet.size if isinstance(oc_packet, RPCRTSPacket): labels = [RTS_CMD_DATA_LABELS[command["type"]] for command in oc_packet.commands] self.logger.debug("ignored RTS packet with commands: %s" % ", ".join(labels)) else: self.logger.debug("sending packet to OC") self.oc_conn.sendall(oc_packet.data) self.bytes_written = self.bytes_written + oc_packet.size # Flow control (only subject to RPC PDUs) self.local_available_window -= oc_packet.size self.rpc_pdu_bytes_received += oc_packet.size # This check can be any as it is not explicitly specified if self.local_available_window < self.window_size / 2: self._send_flow_control_ack() self.local_available_window = self.window_size except IOError: status = False self.logger.debug("handling socket.error: %s" % str(sys.exc_info())) # exc = sys.exc_info() self.logger.error("client connection closed")