Ejemplo n.º 1
0
    def communication_win(self, is_check):
        import win32event
        import win32file
        import win32api
        import pywintypes
        import winerror

        # event for the socket
        hEvent_sock = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(self.comms_socket, hEvent_sock,
                                 win32file.FD_READ)

        # event, overlapped struct for the pipe or tunnel
        hEvent_pipe = win32event.CreateEvent(None, 0, 0,
                                             None)  # for reading from the pipe
        overlapped_pipe = pywintypes.OVERLAPPED()
        overlapped_pipe.hEvent = hEvent_pipe

        # buffer for the packets
        message_readfile = win32file.AllocateReadBuffer(4096)

        # showing if we already async reading or not
        not_reading_already = True
        first_run = True
        while not self._stop:
            try:
                if not self.tunnel_r:
                    # user is not authenticated yet, so there is no pipe
                    # only checking the socket for data
                    rc = win32event.WaitForSingleObject(
                        hEvent_sock, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue
                else:
                    # client mode so we have the socket and tunnel as well
                    # or the client authenticated and the pipe was created
                    if first_run or not_reading_already:
                        # no ReadFile was called before or finished, so we
                        # are calling it again
                        hr, _ = win32file.ReadFile(self.tunnel_r,
                                                   message_readfile,
                                                   overlapped_pipe)
                        not_reading_already = first_run = False

                    if (hr == winerror.ERROR_IO_PENDING):
                        # well, this was an async read, so we need to wait
                        # until it happens
                        rc = win32event.WaitForMultipleObjects(
                            [hEvent_sock, hEvent_pipe], 0,
                            int(self.timeout * 1000))
                        if rc == winerror.WAIT_TIMEOUT:
                            # timed out, just rerun and wait
                            continue
                    else:
                        if hr != 0:
                            common.internal_print(
                                "{0} ReadFile failed: {1}".format(
                                    self.module_short, hr), -1)
                            raise

                if rc < 0x80:  # STATUS_ABANDONED_WAIT_0
                    if rc == 0:
                        # socket got signalled
                        not_reading_already = False
                        messages = self.recv()
                        for message in messages:
                            # looping through the messages from socket
                            if len(message) == 0:
                                # this could happen when the socket died or
                                # partial message was read.
                                continue

                            if common.is_control_channel(message[0:1]):
                                # parse control messages
                                if self.controlchannel.handle_control_messages(
                                        self,
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):], None):
                                    continue
                                else:
                                    self.stop()
                                    break

                            if self.authenticated:
                                try:
                                    # write packet to the tunnel
                                    self.packet_writer(
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):])
                                except OSError as e:
                                    print(e)  # wut?
                                except Exception as e:
                                    if e.args[0] == 995:
                                        common.internal_print(
                                            "Interface disappered, exiting thread: {0}"
                                            .format(e), -1)
                                        self.stop()
                                        continue

                    if rc == 1:
                        # pipe/tunnel got signalled
                        not_reading_already = True
                        if (overlapped_pipe.InternalHigh <
                                4) or (message_readfile[0:1] !=
                                       "\x45"):  #Only care about IPv4
                            # too small which should not happen or not IPv4, so we just drop it.
                            continue

                        # reading out the packet from the buffer and discarding the rest
                        readytogo = message_readfile[0:overlapped_pipe.
                                                     InternalHigh]
                        self.send(common.DATA_CHANNEL_BYTE, readytogo, None)

            except win32api.error as e:
                common.internal_print("TCP Exception: {0}".format(e), -1)

        self.cleanup()

        return True
Ejemplo n.º 2
0
    def communication_unix(self, is_check):
        rlist = [self.comms_socket]
        wlist = []
        xlist = []

        while not self._stop:
            if self.tunnel_r:
                rlist = [self.tunnel_r, self.comms_socket]
            try:
                readable, writable, exceptional = select.select(
                    rlist, wlist, xlist, self.timeout)
            except select.error, e:
                break
            if self._stop:
                self.comms_socket.close()
                break
            try:
                for s in readable:
                    if (s is self.tunnel_r) and not self._stop:
                        message = self.packet_reader(self.tunnel_r, True,
                                                     self.serverorclient)
                        while True:
                            if (len(message) < 4) or (message[0:1] != "\x45"
                                                      ):  #Only care about IPv4
                                break
                            packetlen = struct.unpack(
                                ">H", message[2:4])[0]  # IP Total length
                            if packetlen > len(message):
                                message += self.packet_reader(
                                    self.tunnel_r, False, self.serverorclient)

                            readytogo = message[0:packetlen]
                            message = message[packetlen:]
                            self.send(common.DATA_CHANNEL_BYTE, readytogo,
                                      None)

                    if (s is self.comms_socket) and not self._stop:
                        messages = self.recv()
                        for message in messages:
                            if len(message) == 0:
                                continue

                            if common.is_control_channel(message[0:1]):
                                if self.controlchannel.handle_control_messages(
                                        self,
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):], None):
                                    continue
                                else:
                                    self.stop()
                                    break

                            if self.authenticated:
                                try:
                                    self.packet_writer(
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):])
                                except OSError as e:
                                    print(e)  # wut?
                                except Exception as e:
                                    print(e)

            except (socket.error, OSError, IOError):
                if self.serverorclient:
                    common.internal_print("Client lost. Closing down thread.",
                                          -1)
                    self.cleanup()

                    return
                if not self.serverorclient:
                    common.internal_print("Server lost. Closing connection.",
                                          -1)
                    self.comms_socket.close()
                break
            except:
                print("another error")
                raise
Ejemplo n.º 3
0
    def communication_unix(self, is_check):
        sequence = 0
        identifier = 0
        self.rlist = [self.comms_socket]
        if not self.serverorclient and self.tunnel:
            self.rlist = [self.tunnel, self.comms_socket]
        wlist = []
        xlist = []

        while not self._stop:
            try:
                readable, writable, exceptional = select.select(
                    self.rlist, wlist, xlist, self.timeout)
            except select.error, e:
                common.internal_print("select.error: %r".format(e), -1)
                break
            try:
                if not readable:
                    if is_check:
                        raise socket.timeout
                    if not self.serverorclient:
                        if self.authenticated:
                            self.ICMP_sequence = (self.ICMP_sequence +
                                                  1) % 65536
                            self.do_dummy_packet(self.ICMP_identifier,
                                                 self.ICMP_sequence)
                            common.internal_print("Keep alive sent", 0,
                                                  self.verbosity, common.DEBUG)
                    continue

                for s in readable:
                    if (s in self.rlist) and not (s is self.comms_socket):
                        message = self.packet_reader(s, True,
                                                     self.serverorclient)
                        while True:
                            if (len(message) < 4) or (message[0:1] != "\x45"
                                                      ):  #Only care about IPv4
                                break
                            packetlen = struct.unpack(
                                ">H", message[2:4])[0]  # IP Total length
                            if packetlen > len(message):
                                message += self.packet_reader(
                                    s, False, self.serverorclient)

                            readytogo = message[0:packetlen]
                            message = message[packetlen:]
                            if self.serverorclient:
                                c = self.lookup_client_priv(readytogo)

                                if c:
                                    # if the differece between the received and set sequences too big
                                    # some routers/firewalls just drop older sequences. If it gets
                                    # too big, we just drop the older ones and use the latest X packet
                                    # this helps on stabality.
                                    if (c.get_ICMP_received_sequence() -
                                            c.get_ICMP_sent_sequence()
                                        ) >= self.TRACKING_THRESHOLD:
                                        c.set_ICMP_sent_sequence(
                                            c.get_ICMP_received_sequence() -
                                            self.TRACKING_ADJUST)

                                    # get client related values: identifier and sequence number
                                    identifier = c.get_ICMP_sent_identifier()
                                    sequence = c.get_ICMP_sent_sequence()

                                    # queueing every packet first
                                    c.queue_put(readytogo)
                                    # are there any packets to answer?
                                    if (c.get_ICMP_received_sequence() -
                                            sequence) == 0:
                                        continue
                                    else:
                                        request_num = 0
                                        # if there is less packet than that we have in the queue
                                        # then we cap the outgoing packet number
                                        if (c.get_ICMP_received_sequence() -
                                                sequence) < (c.queue_length()):
                                            number_to_get = (
                                                c.get_ICMP_received_sequence()
                                                - sequence)
                                        else:
                                            # send all packets from the queue
                                            number_to_get = c.queue_length()

                                        for i in range(0, number_to_get):

                                            # get first packet
                                            readytogo = c.queue_get()
                                            # is it he last one we are sending now?
                                            if i == (number_to_get - 1):
                                                # if the last one and there is more in the queue
                                                # then we ask for dummy packets
                                                request_num = c.queue_length()
                                            # go packets go!
                                            self.send(
                                                common.DATA_CHANNEL_BYTE,
                                                readytogo,
                                                ((socket.inet_ntoa(
                                                    c.get_public_ip_addr()),
                                                  c.get_public_src_port()),
                                                 identifier, sequence + i + 1,
                                                 request_num))

                                        sequence = (sequence + i + 1) % 65536
                                        c.set_ICMP_sent_sequence(sequence)
                                else:
                                    # there is no client with that IP
                                    common.internal_print(
                                        "Client not found, strange?!", 0,
                                        self.verbosity, common.DEBUG)
                                    continue

                            else:
                                if self.authenticated:
                                    # whatever we have from the tunnel, just encapsulate it
                                    # and send it out
                                    self.ICMP_sequence = (self.ICMP_sequence +
                                                          1) % 65536
                                    self.send(common.DATA_CHANNEL_BYTE,
                                              readytogo,
                                              (self.server_tuple,
                                               self.ICMP_identifier,
                                               self.ICMP_sequence, 0))  #??
                                else:
                                    common.internal_print(
                                        "Spoofed packets, strange?!", 0,
                                        self.verbosity, common.DEBUG)
                                    continue

                    if s is self.comms_socket:
                        message, addr, identifier, sequence, queue_length = self.recv(
                        )

                        if len(message) == 0:
                            continue

                        c = None
                        if self.serverorclient:
                            self.authenticated = False
                            c = self.lookup_client_pub((addr, identifier))
                            if c:
                                c.set_ICMP_received_identifier(identifier)
                                # packets does not arrive in order sometime
                                # if higher sequence arrived already, then we
                                # do not modify
                                # 16bit integer MAX could be a bit tricky, a
                                # threshold had to be introduced to make it
                                # fail safe. Hacky but should work.
                                ICMP_THRESHOLD = 100
                                if (sequence > c.get_ICMP_received_sequence()
                                    ) or ((sequence < ICMP_THRESHOLD) and
                                          ((sequence + 65536) >
                                           c.get_ICMP_received_sequence()) and
                                          (c.get_ICMP_received_sequence() >
                                           ICMP_THRESHOLD)):
                                    c.set_ICMP_received_sequence(sequence)
                        else:
                            if queue_length:
                                common.internal_print(
                                    "sending {0} dummy packets".format(
                                        queue_length), 0, self.verbosity,
                                    common.DEBUG)
                                for i in range(queue_length + 10):
                                    self.ICMP_sequence = (self.ICMP_sequence +
                                                          1) % 65536
                                    self.do_dummy_packet(
                                        self.ICMP_identifier,
                                        self.ICMP_sequence)

                        if common.is_control_channel(message[0:1]):
                            if self.controlchannel.handle_control_messages(
                                    self,
                                    message[len(common.CONTROL_CHANNEL_BYTE):],
                                (addr, identifier, sequence, 0)):
                                continue
                            else:
                                self.stop()
                                break

                        if c:
                            self.authenticated = c.get_authenticated()

                        if self.authenticated:
                            try:
                                self.packet_writer(
                                    message[len(common.CONTROL_CHANNEL_BYTE):])
                            except OSError as e:
                                print(e)

            except (socket.error, OSError):
                raise
                if self.serverorclient:
                    self.comms_socket.close()
                break
            except:
                print("another error")
                raise
Ejemplo n.º 4
0
    def communication_win(self, is_check):
        import win32event
        import win32file
        import win32api
        import pywintypes
        import winerror

        # event for the socket
        hEvent_sock = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(self.comms_socket, hEvent_sock,
                                 win32file.FD_READ)

        # descriptor list
        self.rlist = [self.comms_socket]
        # overlapped list
        self.olist = [0]
        # event list
        self.elist = [hEvent_sock]
        # message buffer list
        self.mlist = [0]
        # id of the read object - put in this if it was read
        self.ulist = []
        if not self.serverorclient and self.tunnel:
            # client mode
            # objects created for the tunnel and put in the corresponding
            # lists
            hEvent_pipe = win32event.CreateEvent(
                None, 0, 0, None)  # for reading from the pipe
            overlapped_pipe = pywintypes.OVERLAPPED()
            overlapped_pipe.hEvent = hEvent_pipe
            message_buffer = win32file.AllocateReadBuffer(4096)
            self.rlist.append(self.tunnel)
            self.olist.append(overlapped_pipe)
            self.elist.append(hEvent_pipe)
            self.mlist.append(message_buffer)
            self.ulist.append(1)

        while not self._stop:
            try:
                if not self.tunnel:
                    # check or server mode without client only with socket
                    #message, addr = self.comms_socket.recvfrom(1508)
                    rc = win32event.WaitForSingleObject(
                        hEvent_sock, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue

                else:
                    if self.ulist:
                        # there is somebody waiting to be read
                        for idx in self.ulist:
                            # issueing ReadFile on all not yet read mailslots/tunnel
                            hr, _ = win32file.ReadFile(self.rlist[idx],
                                                       self.mlist[idx],
                                                       self.olist[idx])
                            if (hr != 0) and (hr != winerror.ERROR_IO_PENDING):
                                common.internal_print(
                                    "UDP ReadFile failed: {0}".format(hr), -1)
                                raise

                        self.ulist = []

                    # waiting to get some data somewhere
                    rc = win32event.WaitForMultipleObjects(
                        self.elist, 0, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue

                if rc < 0x80:  # STATUS_ABANDONED_WAIT_0
                    if rc > 0:
                        # the tunnel or one of the mailslots got signalled
                        self.ulist.append(rc)
                        if (self.olist[rc].InternalHigh <
                                4) or (self.mlist[rc][0:1] !=
                                       "\x45"):  #Only care about IPv4
                            continue

                        readytogo = self.mlist[rc][0:self.olist[rc].
                                                   InternalHigh]

                        if self.serverorclient:
                            c = self.lookup_client_priv(readytogo)
                            if c:
                                # if the differece between the received and set sequences too big
                                # some routers/firewalls just drop older sequences. If it gets
                                # too big, we just drop the older ones and use the latest X packet
                                # this helps on stabality.
                                if (c.get_ICMP_received_sequence() -
                                        c.get_ICMP_sent_sequence()
                                    ) >= self.TRACKING_THRESHOLD:
                                    c.set_ICMP_sent_sequence(
                                        c.get_ICMP_received_sequence() -
                                        self.TRACKING_ADJUST)

                                # get client related values: identifier and sequence number
                                identifier = c.get_ICMP_sent_identifier()
                                sequence = c.get_ICMP_sent_sequence()

                                # queueing every packet first
                                c.queue_put(readytogo)
                                # are there any packets to answer?
                                if (c.get_ICMP_received_sequence() -
                                        sequence) == 0:
                                    continue
                                else:
                                    request_num = 0
                                    # if there is less packet than that we have in the queue
                                    # then we cap the outgoing packet number
                                    if (c.get_ICMP_received_sequence() -
                                            sequence) < (c.queue_length()):
                                        number_to_get = (
                                            c.get_ICMP_received_sequence() -
                                            sequence)
                                    else:
                                        # send all packets from the queue
                                        number_to_get = c.queue_length()

                                    for i in range(0, number_to_get):
                                        # get first packet
                                        readytogo = c.queue_get()
                                        # is it he last one we are sending now?
                                        if i == (number_to_get - 1):
                                            # if the last one and there is more in the queue
                                            # then we ask for dummy packets
                                            request_num = c.queue_length()
                                        # go packets go!
                                        self.send(common.DATA_CHANNEL_BYTE,
                                                  readytogo,
                                                  ((socket.inet_ntoa(
                                                      c.get_public_ip_addr()),
                                                    c.get_public_src_port()),
                                                   identifier, sequence + i +
                                                   1, request_num))

                                    sequence = (sequence + i + 1) % 65536
                                    c.set_ICMP_sent_sequence(sequence)
                            else:
                                # there is no client with that IP
                                common.internal_print(
                                    "Client not found, strange?!", 0,
                                    self.verbosity, common.DEBUG)
                                continue
                        else:
                            if self.authenticated:
                                # whatever we have from the tunnel, just encapsulate it
                                # and send it out
                                self.ICMP_sequence = (self.ICMP_sequence +
                                                      1) % 65536
                                self.send(
                                    common.DATA_CHANNEL_BYTE, readytogo,
                                    (self.server_tuple, self.ICMP_identifier,
                                     self.ICMP_sequence, 0))  #??
                            else:
                                common.internal_print(
                                    "Spoofed packets, strange?!", 0,
                                    self.verbosity, common.DEBUG)
                                continue
                    if rc == 0:
                        # socket got signalled
                        message, addr, identifier, sequence, queue_length = self.recv(
                        )

                        if len(message) == 0:
                            continue

                        c = None
                        if self.serverorclient:
                            self.authenticated = False
                            c = self.lookup_client_pub((addr, 0))
                            if c:
                                c.set_ICMP_received_identifier(identifier)
                                # packets does not arrive in order sometime
                                # if higher sequence arrived already, then we
                                # do not modify
                                # 16bit integer MAX could be a bit tricky, a
                                # threshold had to be introduced to make it
                                # fail safe. Hacky but should work.
                                ICMP_THRESHOLD = 100
                                if (sequence > c.get_ICMP_received_sequence()
                                    ) or ((sequence < ICMP_THRESHOLD) and
                                          ((sequence + 65536) >
                                           c.get_ICMP_received_sequence()) and
                                          (c.get_ICMP_received_sequence() >
                                           ICMP_THRESHOLD)):
                                    c.set_ICMP_received_sequence(sequence)
                        else:
                            if queue_length:
                                common.internal_print(
                                    "sending {0} dummy packets".format(
                                        queue_length), 0, self.verbosity,
                                    common.DEBUG)
                                for i in range(queue_length + 10):
                                    self.ICMP_sequence = (self.ICMP_sequence +
                                                          1) % 65536
                                    self.do_dummy_packet(
                                        self.ICMP_identifier,
                                        self.ICMP_sequence)

                        if common.is_control_channel(message[0:1]):
                            if self.controlchannel.handle_control_messages(
                                    self,
                                    message[len(common.CONTROL_CHANNEL_BYTE):],
                                (addr, identifier, sequence, 0)):
                                continue
                            else:
                                self.stop()
                                break

                        if c:
                            self.authenticated = c.get_authenticated()

                        if self.authenticated:
                            try:
                                self.packet_writer(
                                    message[len(common.CONTROL_CHANNEL_BYTE):])
                            except OSError as e:
                                print(e)

            except win32api.error as e:
                common.internal_print("UDP Exception: {0}".format(e), -1)
            except socket.error as se:
                if se.args[0] == 10054:  # port is unreachable
                    common.internal_print(
                        "Server's port is unreachable: {0}".format(se), -1)
                    self._stop = True

        return True
Ejemplo n.º 5
0
    def communication_unix(self, is_check):
        self.rlist = [self.comms_socket]
        if not self.serverorclient and self.tunnel:
            self.rlist = [self.tunnel, self.comms_socket]
        wlist = []
        xlist = []

        while not self._stop:
            try:
                readable, writable, exceptional = select.select(
                    self.rlist, wlist, xlist, self.timeout)
            except select.error as e:
                common.internal_print("select.error: %r".format(e), -1)
                break

            if (not readable) and is_check:
                raise socket.timeout
            try:
                for s in readable:
                    if (s in self.rlist) and not (s is self.comms_socket):
                        message = self.packet_reader(s, True,
                                                     self.serverorclient)
                        while True:
                            if (len(message) < 4) or (message[0:1] != "\x45"
                                                      ):  #Only care about IPv4
                                break
                            packetlen = struct.unpack(
                                ">H", message[2:4])[0]  # IP Total length
                            if packetlen > len(message):
                                message += self.packet_reader(
                                    s, False, self.serverorclient)

                            readytogo = message[0:packetlen]
                            message = message[packetlen:]
                            if self.serverorclient:
                                c = self.lookup_client_priv(readytogo)
                                if c:
                                    self.send(
                                        common.DATA_CHANNEL_BYTE, readytogo,
                                        ((socket.inet_ntoa(
                                            c.get_public_ip_addr()),
                                          c.get_public_src_port()), None))
                                else:
                                    common.internal_print(
                                        "Client not found, strange?!", 0,
                                        self.verbosity, common.DEBUG)
                                    continue
                            else:
                                if self.authenticated:
                                    self.send(common.DATA_CHANNEL_BYTE,
                                              readytogo,
                                              (self.server_tuple, None))

                    if s is self.comms_socket:
                        messages = self.recv()
                        if len(messages) == 0:
                            continue

                        for addr in messages:
                            for message in messages[addr]:
                                c = None
                                if self.serverorclient:
                                    self.authenticated = False
                                    c = self.lookup_client_pub((addr, 0))

                                if common.is_control_channel(message[0:1]):
                                    if self.controlchannel.handle_control_messages(
                                            self, message[len(
                                                common.CONTROL_CHANNEL_BYTE):],
                                        (addr, None)):
                                        continue
                                    else:
                                        self.stop()
                                        break

                                if c:
                                    self.authenticated = c.get_authenticated()

                                if self.authenticated:
                                    try:
                                        self.packet_writer(message[
                                            len(common.CONTROL_CHANNEL_BYTE):])
                                    except OSError as e:
                                        print(e)

            except (socket.error, OSError):
                raise
                if self.serverorclient:
                    self.comms_socket.close()
                break
            except:
                print("another error")
                raise

        return
Ejemplo n.º 6
0
    def communication_win(self, is_check):
        import win32event
        import win32file
        import win32api
        import pywintypes
        import winerror

        # event for the socket
        hEvent_sock = win32event.CreateEvent(None, 0, 0, None)
        win32file.WSAEventSelect(self.comms_socket, hEvent_sock,
                                 win32file.FD_READ)

        # descriptor list
        self.rlist = [self.comms_socket]
        # overlapped list
        self.olist = [0]
        # event list
        self.elist = [hEvent_sock]
        # message buffer list
        self.mlist = [0]
        # id of the read object - put in this if it was read
        self.ulist = []
        if not self.serverorclient and self.tunnel:
            # client mode
            # objects created for the tunnel and put in the corresponding
            # lists
            hEvent_pipe = win32event.CreateEvent(
                None, 0, 0, None)  # for reading from the pipe
            overlapped_pipe = pywintypes.OVERLAPPED()
            overlapped_pipe.hEvent = hEvent_pipe
            message_buffer = win32file.AllocateReadBuffer(4096)
            self.rlist.append(self.tunnel)
            self.olist.append(overlapped_pipe)
            self.elist.append(hEvent_pipe)
            self.mlist.append(message_buffer)
            self.ulist.append(1)

        while not self._stop:
            try:
                if not self.tunnel:
                    # check or server mode without client only with socket
                    rc = win32event.WaitForSingleObject(
                        hEvent_sock, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue
                else:
                    if self.ulist:
                        # there is somebody waiting to be read
                        for idx in self.ulist:
                            # issueing ReadFile on all not yet read mailslots/tunnel
                            hr, _ = win32file.ReadFile(self.rlist[idx],
                                                       self.mlist[idx],
                                                       self.olist[idx])
                            if (hr != 0) and (hr != winerror.ERROR_IO_PENDING):
                                common.internal_print(
                                    "UDP ReadFile failed: {0}".format(hr), -1)
                                raise

                        self.ulist = []

                    # waiting to get some data somewhere
                    rc = win32event.WaitForMultipleObjects(
                        self.elist, 0, int(self.timeout * 1000))
                    if rc == winerror.WAIT_TIMEOUT:
                        # timed out, just rerun and wait
                        continue

                if rc < 0x80:  # STATUS_ABANDONED_WAIT_0
                    if rc > 0:
                        # the tunnel or one of the mailslots got signalled
                        self.ulist.append(rc)
                        if (self.olist[rc].InternalHigh <
                                4) or (self.mlist[rc][0:1] !=
                                       "\x45"):  #Only care about IPv4
                            continue

                        readytogo = self.mlist[rc][0:self.olist[rc].
                                                   InternalHigh]
                        if self.serverorclient:
                            c = self.lookup_client_priv(readytogo)
                            if c:
                                self.send(
                                    common.DATA_CHANNEL_BYTE, readytogo,
                                    ((socket.inet_ntoa(c.get_public_ip_addr()),
                                      c.get_public_src_port()), None))
                            else:
                                common.internal_print(
                                    "Client not found, strange?!", 0,
                                    self.verbosity, common.DEBUG)
                                continue
                        else:
                            if self.authenticated:
                                self.send(common.DATA_CHANNEL_BYTE, readytogo,
                                          (self.server_tuple, None))
                    if rc == 0:
                        # socket got signalled
                        messages = self.recv()
                        if len(messages) == 0:
                            continue

                        for addr in messages:
                            for message in messages[addr]:
                                c = None
                                if self.serverorclient:
                                    self.authenticated = False
                                    c = self.lookup_client_pub((addr, 0))

                                if common.is_control_channel(message[0:1]):
                                    if self.controlchannel.handle_control_messages(
                                            self, message[len(
                                                common.CONTROL_CHANNEL_BYTE):],
                                        (addr, None)):
                                        continue
                                    else:
                                        self.stop()
                                        break

                                if c:
                                    self.authenticated = c.get_authenticated()

                                if self.authenticated:
                                    try:
                                        self.packet_writer(message[
                                            len(common.CONTROL_CHANNEL_BYTE):])
                                    except OSError as e:
                                        print(e)

            except win32api.error as e:
                common.internal_print("UDP Exception: {0}".format(e), -1)
            except socket.error as se:
                if se.args[0] == 10054:  # port is unreachable
                    common.internal_print(
                        "Server's port is unreachable: {0}".format(se), -1)
                    self._stop = True

        return True
Ejemplo n.º 7
0
    def communication_win(self, is_check):
        # event, overlapped struct for the pipe or tunnel
        hEvent_pipe = win32event.CreateEvent(None, 0, 0,
                                             None)  # for reading from the pipe
        overlapped_pipe = pywintypes.OVERLAPPED()
        overlapped_pipe.hEvent = hEvent_pipe

        # event, overlapped struct for the pipe or tunnel
        hEvent_rdp = win32event.CreateEvent(None, 0, 0,
                                            None)  # for reading from the pipe
        overlapped_rdp = pywintypes.OVERLAPPED()
        overlapped_rdp.hEvent = hEvent_rdp

        # buffer for the packets
        message_readfile_pipe = win32file.AllocateReadBuffer(4096)
        message_readfile_rdp = win32file.AllocateReadBuffer(4096)

        # showing if we already async reading or not
        read_pipe = True
        read_rdp = False
        first_run = True

        while not self._stop:
            try:
                if not self.tunnel_r:
                    # user is not authenticated yet, so there is no pipe
                    # only checking the socket for data
                    hr, _ = win32file.ReadFile(self.comms_socket,
                                               message_readfile_rdp,
                                               overlapped_rdp)
                    if (hr == winerror.ERROR_IO_PENDING):
                        rc = win32event.WaitForSingleObject(
                            hEvent_rdp, int(self.timeout * 1000))
                        read_rdp = True
                    else:
                        raise
                        rc = 0
                else:
                    # client mode so we have the socket and tunnel as well
                    # or the client authenticated and the pipe was created
                    if read_pipe or first_run:
                        # no ReadFile was called before or finished, so we
                        # are calling it again
                        first_run = False
                        hr, _ = win32file.ReadFile(self.tunnel_r,
                                                   message_readfile_pipe,
                                                   overlapped_pipe)

                    if read_rdp:
                        # no ReadFile was called before or finished, so we
                        # are calling it again
                        hr, _ = win32file.ReadFile(self.comms_socket,
                                                   message_readfile_rdp,
                                                   overlapped_rdp)

                    if (hr == winerror.ERROR_IO_PENDING):
                        # well, this was an async read, so we need to wait
                        # until it happens
                        rc = win32event.WaitForMultipleObjects(
                            [hEvent_rdp, hEvent_pipe], 0,
                            int(self.timeout * 1000))
                        if rc == winerror.WAIT_TIMEOUT:
                            # timed out, just rerun and wait
                            continue
                    else:
                        if hr != 0:
                            common.internal_print(
                                "RDP ReadFile failed: {0}".format(hr), -1)
                            raise

                if rc < 0x80:  # STATUS_ABANDONED_WAIT_0
                    if rc == 0:
                        read_rdp = True
                        read_pipe = False
                        # socket got signalled
                        # skipping header (8):length of read
                        messages = self.recv(
                            message_readfile_rdp[8:overlapped_rdp.
                                                 InternalHigh])  # SLOW?
                        for message in messages:
                            # looping through the messages from socket
                            if len(message) == 0:
                                # this could happen when the socket died or
                                # partial message was read.
                                continue

                            if common.is_control_channel(message[0:1]):
                                # parse control messages
                                if self.controlchannel.handle_control_messages(
                                        self,
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):], None):
                                    continue
                                else:
                                    # If the module is stopped right away, then
                                    # the channel will be closing down as well.
                                    # Because of the buffering the message will
                                    # not be sent. That is why we need to sleep
                                    time.sleep(0.5)
                                    self.stop()
                                    break

                            if self.authenticated:
                                try:
                                    # write packet to the tunnel
                                    self.packet_writer(
                                        message[len(common.CONTROL_CHANNEL_BYTE
                                                    ):])
                                except OSError as e:
                                    print(e)  # wut?
                                except Exception as e:
                                    if e.args[0] == 995:
                                        common.internal_print(
                                            "Interface disappered, exiting thread: {0}"
                                            .format(e), -1)
                                        self.stop()
                                        continue
                                    print(e)
                    if rc == 1:
                        read_rdp = False
                        read_pipe = True
                        # pipe/tunnel got signalled
                        if (overlapped_pipe.InternalHigh <
                                4) or (message_readfile_pipe[0:1] !=
                                       "\x45"):  #Only care about IPv4
                            # too small which should not happen or not IPv4, so we just drop it.
                            continue

                        # reading out the packet from the buffer and discarding the rest
                        readytogo = message_readfile_pipe[0:overlapped_pipe.
                                                          InternalHigh]
                        self.send(common.DATA_CHANNEL_BYTE, readytogo, None)

            except win32api.error as e:
                if e.args[0] == 233:
                    # No process is on the other end of the pipe.
                    self._stop = True
                    common.internal_print("Client disconnected from the pipe.",
                                          -1)
                    continue
                common.internal_print("RDP Exception: {0}".format(e), -1)

        self.cleanup()

        return True