예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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")
예제 #4
0
    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)
예제 #5
0
    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
예제 #6
0
    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
예제 #7
0
    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)
예제 #8
0
    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"]))
예제 #9
0
    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"]))
예제 #10
0
    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)
예제 #11
0
    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)
예제 #12
0
    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
예제 #13
0
    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
예제 #14
0
    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)
예제 #15
0
    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")
예제 #16
0
    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")
예제 #17
0
    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)
예제 #18
0
    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")