Example #1
0
 def __init__(self):
     self.__address = gethostbyname(gethostname())
     self.__main_socket = socket()
     self.__database = ComputerDatabase()
     self.__database_lock = Lock()
     self.__announce_socket = socket(AF_INET, SOCK_DGRAM)
     self.running = False
     self.starting = False
     self._connected_clients = ClientList()
     self.__signature = None
     self.__public_key = None
Example #2
0
class Server(object):
    # constructor
    def __init__(self):
        self.__address = gethostbyname(gethostname())
        self.__main_socket = socket()
        self.__database = ComputerDatabase()
        self.__database_lock = Lock()
        self.__announce_socket = socket(AF_INET, SOCK_DGRAM)
        self.running = False
        self.starting = False
        self._connected_clients = ClientList()
        self.__signature = None
        self.__public_key = None

    # starts server - updates database and starts threads
    def start(self):
        """
        Starts the server
        """
        if self.starting or self.running:
            raise NameError('Already running or starting...')
        self.starting = True
        self.__signature = Cipher.crate_signature()
        self.__public_key = Cipher()
        self.__print("Updating database...")
        pythoncom.CoInitialize()
        current_arp = NetMap.map()
        pythoncom.CoUninitialize()
        database = self.__database.read()
        # Loop for updating the state of the computer
        for computer in database:
            if computer.ip == gethostbyname(gethostname()):
                computer.active = True
                self.__database.update_state(computer)
            elif computer not in current_arp:
                computer.active = False
                self.__database.update_state(computer)
        # Loop for updating the database
        for computer in current_arp:
            if computer not in database:
                self.__database.add_row(computer)
                database = self.__database.read()
        self.__print("Database updated.")
        if not exists(DOWNLOAD_UPLOAD):
            makedirs(DOWNLOAD_UPLOAD)
        network_scan_thread = Thread(target=self.__network_scan)
        network_scan_thread.setDaemon(True)
        network_scan_thread.start()
        broadcast_announce_thread = Thread(target=self.__broadcast_announce)
        broadcast_announce_thread.setDaemon(True)
        broadcast_announce_thread.start()
        self.__main_socket.bind(("0.0.0.0", SERVER_PORT))
        self.__main_socket.listen(1)
        self.starting = False
        self.running = True
        self.__run()

    # the main running method of the server
    def __run(self):
        """
        Actual main code of the server
        """
        self.__print("Server started!")
        while True:
            to_read, to_write, error = select([self.__main_socket], [], [])
            for sock in to_read:
                if sock is self.__main_socket:
                    client_socket, client_address = self.__main_socket.accept()
                    for computer in self.__database.read():
                        if computer.ip == client_address[0]:
                            new_client_thread = Thread(target=self.__new_client, args=[client_socket, computer])
                            new_client_thread.setDaemon(True)
                            new_client_thread.start()

    # handles a newly connected client
    def __new_client(self, client_socket, computer):
        key = self.__key_exchange(client_socket)
        if isinstance(key, Cipher):
            self._connected_clients.append(ClientInterface(client_socket, computer, key))

    # Operates the key exchange with client
    def __key_exchange(self, sock):
        sock.send(self.__public_key.public_key().pack())
        data = sock.recv(BUFFER_SIZE)
        key = self.__public_key.decrypt(data)
        key, his_hashed_key = key.split(IN_PACK_SEPARATOR)
        if Cipher.hash(key) == his_hashed_key:
            key = Cipher.unpack(key)
            return key

    # Has it's own thread - announces the server address to the network
    def __broadcast_announce(self):
        """
        Runs in a thread. Announces the server's existence in the network
        """
        message = SERVER_ANNOUNCE_MESSAGE
        self.__announce_socket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
        while True:
            self.__announce_socket.sendto(message, ("<broadcast>", BROADCAST_PORT))
            sleep(ANNOUNCE_SLEEP_TIME)

    
    def __network_scan(self):
        """
        Scans the network
        """
        while True:
            sleep(NET_SCAN_WAIT)
            pythoncom.CoInitialize()
            current_arp = NetMap.map()
            pythoncom.CoUninitialize()
            database = self.__database.read()
            for computer in database:
                if computer.ip == gethostbyname(gethostname()):
                    computer.active = True
                    self.__database.update_state(computer)
                elif computer not in current_arp:
                    computer.active = False
                    self.__database.update_state(computer)
            for computer in current_arp:
                if computer not in database:
                    self.__database.add_row(computer)
                    database = self.__database.read()

    def __print(self, data):
        print data

    def do_action(self, computer, hour, minute, second, action):
        if isinstance(computer, Computer):
            for other_computer in self.__database.read():
                if other_computer == computer:
                    now = datetime.now()
                    my_time = datetime(now.year, now.month, now.day, int(hour), int(minute), int(second))
                    to_wait = (my_time - now).seconds
                    wait_thread = Thread(target=self.__wait_to_action, args=(to_wait, action, computer))
                    wait_thread.start()
                    return

    def do_action_now(self, computer, action):
        if isinstance(computer, Computer):
            for other_computer in self.__database.read():
                if other_computer == computer:
                    self.__wait_to_action(0, action, computer)
                    return

    def __wait_to_action(self, time_to_wait, action, computer):
        sleep(time_to_wait)
        if action == "shutdown":
            client = self.__find_client(computer)
            if isinstance(client, ClientInterface):
                self._connected_clients.remove(client)
            computer.shutdown()
        else:
            computer.wake_up()
        self.__database.update_state(computer)

    def make_computers_dictionary(self):
        dictionary = self.__database.make_dictionary()
        dictionary["CONNECTED"] = []
        for i in xrange(len(dictionary["MAC"])):
            dictionary["CONNECTED"].append(str(Computer(dictionary["MAC"][i], dictionary["IP"][i]) in self._connected_clients))
        return dictionary

    def __find_client(self, computer):
        for client in self._connected_clients:
            if computer == client:
                return client

    def computer_data(self, computer):
        client = self.__find_client(computer)
        return {"MAC": client.get_mac(),
                "IP": client.get_ip(),
                "HOST": client.name}

    def get_processes_data(self, computer):
        client = self.__find_client(computer)
        if isinstance(client, ClientInterface):
            try:
                client.update_processes()
            except:
                self._connected_clients.remove(client)
            else:
                processes_list = [dict(NAME=process.name, PID=process.pid, PARENT_ID=process.parent_id) for process in client.processes]
                return processes_list

    def terminate_process(self, computer, processes):
        client = self.__find_client(computer)
        if isinstance(client, ClientInterface):
            try:
                result = client.terminate(processes)
            except:
                self._connected_clients.remove(client)
            else:
                return result

    def open_process(self, computer, command):
        client = self.__find_client(computer)
        if isinstance(client, ClientInterface):
            try:
                result = client.open_process(command)
            except:
                self._connected_clients.remove(client)
            else:
                return result

    def get_file(self, computer, directory):
        client = self.__find_client(computer)
        if isinstance(client, ClientInterface):
            try:
                result = client.send_files(directory)
            except:
                self._connected_clients.remove(client)
            else:
                return {
                    'NAME': directory,
                    'ITEMS': result
                }

    def delete_file(self, computer, directory):
        client = self.__find_client(computer)
        if isinstance(client, ClientInterface):
            try:
                result = client.delete_file(directory)
            except:
                self._connected_clients.remove(client)
            else:
                return result

    def create_file(self, computer, path, name):
        client = self.__find_client(computer)
        if isinstance(client, ClientInterface):
            try:
                result = client.create_file(path, name)
            except:
                self._connected_clients.remove(client)
            else:
                return result

    def add_computer(self, computer):
        if isinstance(computer, Computer):
            if re.match(MAC_REGULAR_EXPRESSION, computer.mac):
                if re.match(IP_REGULAR_EXPRESSION, computer.ip):
                    if NetMap.can_ip_in_my_network(computer.ip):
                        computer.active = False
                        self.__database.add_row(computer)
                        return "Computer successfully added."
                    return "The IP address entered cannot exist in this network"
                return "Invalid IP format"
            return "Invalid MAC format"

    def download(self, computer, directory):
        client = self.__find_client(computer)
        if isinstance(client, ClientInterface):
            file_data = client.download(directory)
            file_name = directory.split('\\')[-1]
            file_dump = open(DOWNLOAD_UPLOAD + '\\' + file_name, 'wb+')
            file_dump.write(file_data)
            file_dump.close()
            return file_name

    def remote_desktop(self, computer_list):
        for computer in computer_list:
            subprocess.Popen(['mstsc', '/v:' + computer.ip])