Ejemplo n.º 1
0
Archivo: irc.py Proyecto: Ivoz/Modum
class Irc(object):
    """Handles a client connection to the IRC protocol"""

    def __init__(self, server, publisher, flood_prevention=1):
        self.server = server
        self.publisher = publisher
        self.flood_prevention = flood_prevention
        self._conn = Connection(server['host'], server['port'],
                    server['ssl'], server['timeout'])  # Internal connection
        # Timer to prevent flooding
        self.timer = Event()
        self.timer.set()
        # The canonical channels of IRC to subscribe / publish
        # Receives input to send to irc server
        self.sender = Queue()
        # Receives output to publish
        self.receiver = Queue()
        # Suscribe my output to receive data from connection
        self.publisher.subscribe(self.receiver,
                self._conn.receiver, Msg.from_msg)
        # Subscribe connection to send data from my input
        self.publisher.subscribe(self._conn.sender,
                self.sender, self._prevent_flood)

    @property
    def connected(self):
        return self._conn.connected

    def connect(self):
        if self.connected:
            return True
        self._conn.connect()
        if self.connected:
            return True
        else:
            return self._conn.state

    def disconnect(self):
        self._conn.disconnect()
        return self.connected

    def kill(self):
        """Completely terminate the irc connection"""
        self.publisher.unsubscribe(self.receiver, self._conn.receiver)
        self.publisher.unsubscribe(self._conn.sender, self.sender)
        self._conn.kill()

    def _prevent_flood(self, msg):
        """Used to prevent sending messages extremely quickly"""
        if self.flood_prevention > 0 and msg.cmd != 'PONG':
            self.timer.wait()
            self.timer.clear()
            gevent.spawn_later(self.flood_prevention, self.timer.set)
        return str(msg)
Ejemplo n.º 2
0
def main():
    HOST, PORT, REVERSE, PUB_KEY_FILE, PRV_KEY_FILE, KN_HOSTS_FILE = read_conf(
    )

    # Si se pasa dirección y/o puerto como argumento, sobreescribirlo
    addr, port = read_args()
    if addr: HOST = addr
    if port: PORT = port

    # Si existe el known_hosts, leerlo y convertirlo en una lista
    if os.path.isfile(KN_HOSTS_FILE):
        with open(KN_HOSTS_FILE, "rb") as f:
            known_hosts = f.read()
        known_hosts = known_hosts.split("\n")
    else:
        known_hosts = False

    # Creación del socket
    conn = Connection(HOST, PORT)

    try:
        if REVERSE == '1':
            conn.listen(timeout=10)
        else:
            conn.connect()

        keyring = Keyring()

        # Lee los ficheros de claves pub/priv
        with open(PRV_KEY_FILE, 'rb') as f:
            prv_key = f.read()
        with open(PUB_KEY_FILE, 'rb') as f:
            pub_key = f.read()

        # Envía su clave pública al servidor
        conn.send(pub_key)

        # Recibe la clave pública del servidor
        srv_pub_key = conn.receive()
        if srv_pub_key == ':ERR:':
            print '{}[!]{} ERROR: El servidor no reconoce tu clave pública.'.format(
                color.RED, color.END)
            sys.exit(1)

        # Comparación de clave pública recibida con las contenidas en el known_hosts
        if (not known_hosts) or (srv_pub_key not in known_hosts):
            add_srv_to_known_hosts = raw_input(
                "{}[!]{} WARNING: La clave pública de este servidor no se encuentra almacenada:\n{} \nSi lo desea, puede añadirla [y/n] >>> "
                .format(color.YELLOW, color.END, srv_pub_key))
            if add_srv_to_known_hosts.lower() == "y":
                with open(KN_HOSTS_FILE, "ab") as f:
                    f.write(srv_pub_key + "\n")

        # Envía firma de autenticación
        signature = keyring.sign(prv_key)
        conn.send(signature)

        srv_signature = conn.receive()
        # Si recibe error de autenticación, informa y cierra el programa
        if srv_signature == ':ERR:':
            print '{}[!]{} ERROR: La autenticación ha fallado'.format(
                color.RED, color.END)
            sys.exit(1)

        # Si logra autenticarse, comprueba la firma del servidor
        print '{}[+]{} Cliente autenticado correctamente'.format(
            color.GREEN, color.END)
        sign_valid = keyring.verify(srv_pub_key, srv_signature)
        if sign_valid:
            conn.send(':OK:')
            print '{}[+]{} Servidor autenticado correctamente'.format(
                color.GREEN, color.END)
        else:
            conn.send(':ERR:')
            print '{}[!]{} ERROR: La autenticación ha fallado'.format(
                color.RED, color.END)
            sys.exit(1)

        # Marca de sincronización
        sync = conn.receive()

        # Intercambio de clave de sesión mediante PKI
        session_key = keyring.genSessionKey()
        session_key_crypted = keyring.cipherRSA(session_key, srv_pub_key)
        conn.send(session_key_crypted)
        print '{}[+]{} Intercambiando clave de sesión...'.format(
            color.BLUE, color.END)
        # Una vez establecida e intercambiada la clave de sesión, asociamos el keyring a la conexión
        keyring.session_key = session_key
        conn.keyring = keyring

        shell = Shell(conn)
        shell.start()

    except conn.timeout:
        print '\n{}[!]{} El servidor está desconectado.\n'.format(
            color.RED, color.END)
Ejemplo n.º 3
0
def main():
    initial_path = os.path.dirname(os.path.abspath(__file__))

    HOST, PORT, REVERSE, PUB_KEY_FILE, PRV_KEY_FILE, KN_HOSTS_FILE = read_conf(
    )

    # Comprobar que exista un fichero con la clave pública del cliente
    if os.path.isfile(KN_HOSTS_FILE):
        with open(KN_HOSTS_FILE, "rb") as f:
            known_hosts = f.read()
        known_hosts = known_hosts.split("\n")
    else:
        print '[!] ERROR: El fichero {} debe existir.'.format(KN_HOSTS_FILE)
        sys.exit(1)

    while True:
        time.sleep(1)

        # Creación del socket
        conn = Connection(HOST, PORT)

        try:
            if REVERSE == '1':
                conn.connect()
            else:
                conn.listen(timeout=5)

            keyring = Keyring()

            # Lee los ficheros de claves pub/priv
            with open(PRV_KEY_FILE, 'rb') as f:
                prv_key = f.read()
            with open(PUB_KEY_FILE, 'rb') as f:
                pub_key = f.read()

            # Recibe la clave pública del cliente
            cli_pub_key = conn.receive()

            # Si no reconoce la clave pub del cliente, informa de que se cierra la conexión
            if cli_pub_key not in known_hosts:
                conn.send(':ERR:')
                sys.exit(1)
            # Si reconoce la clave pub del cliente, le envía su clave pública
            conn.send(pub_key)

            # Recibe firma de autenticación del cliente y la comprueba
            cli_signature = conn.receive()
            sign_valid = keyring.verify(cli_pub_key, cli_signature)
            # Si es válida, envía su firma de autenticación
            if sign_valid:
                signature = keyring.sign(prv_key)
                conn.send(signature)
            else:
                conn.send(':ERR:')
                sys.exit(1)

            # Si el cliente no acepta la firma, cierra el programa
            auth = conn.receive()
            if auth == ':ERR:':
                sys.exit(1)

            # Marca de sincronización
            conn.send(':SYNC:')
            # Intercambio de clave de sesión mediante PKI
            session_key_crypted = conn.receive()
            session_key = keyring.decipherRSA(session_key_crypted, prv_key)

            # Una vez establecida e intercambiada la clave de sesión, asociamos el keyring a la conexión
            keyring.session_key = session_key
            conn.keyring = keyring

            shell = Shell(conn)
            shell.start()
            os.chdir(initial_path)  # Por si el cliente se cambió de directorio

        except:
            pass