示例#1
0
    def _pubkey_handshake(self, srv_privkey, client_pubkeys):
        modp_group = DH_GROUP
        #private exponent
        srv_dh_privkey = int(os.urandom(modp_group["q_size"]+1).encode('hex'),
                             16)
        srv_dh_privkey = srv_dh_privkey % modp_group["q"]
        #public key
        srv_dh_pubkey_int = pow(modp_group["g"],
                                srv_dh_privkey,
                                modp_group["p"])
        srv_dh_pubkey = "{1:0{0}x}".format(modp_group['p_size']*2,
                                           srv_dh_pubkey_int)
        srv_dh_pubkey = srv_dh_pubkey.decode('hex')

        msg = self.recv_msg()
        if msg["type"] != "pubkey_client_hello":
            raise SecSocketException("Handshake failed.")
        ctl_identity = msg["identity"]
        try:
            ctl_pubkey = load_pem_public_key(msg["ctl_pubkey"], backend)
        except:
            raise SecSocketException("Handshake failed.")

        local_ctl_pubkey = client_pubkeys[ctl_identity]

        if not self._cmp_pub_keys(local_ctl_pubkey, ctl_pubkey):
            raise SecSocketException("Handshake failed.")

        ctl_dh_pubkey = msg["ctl_pub_dh"]
        signature = msg["signature"]
        if not self._verify_signature(local_ctl_pubkey,
                                      ctl_dh_pubkey,
                                      signature):
            raise SecSocketException("Handshake failed.")

        ctl_dh_pubkey_int = int(ctl_dh_pubkey.encode('hex'), 16)

        srv_pubkey = srv_privkey.public_key()
        srv_pubkey_pem = srv_pubkey.public_bytes(
                encoding=ser.Encoding.PEM,
                format=ser.PublicFormat.SubjectPublicKeyInfo)

        signature = self._sign_data(srv_dh_pubkey, srv_privkey)
        msg = {"type": "pubkey_server_hello",
               "srv_pubkey": srv_pubkey_pem,
               "srv_pub_dh": srv_dh_pubkey,
               "signature": signature}
        self.send_msg(msg)

        ZZ = pow(ctl_dh_pubkey_int, srv_dh_privkey, modp_group["p"])
        ZZ = "{1:0{0}x}".format(modp_group['p_size']*2, ZZ)
        ZZ = self._master_secret.decode('hex')

        self._master_secret = self.PRF(ZZ,
                                       "master secret",
                                       self._ctl_random + self._agent_random,
                                       48)

        self._init_cipher_spec()
        self._send_change_cipher_spec()
示例#2
0
    def _validate_secret(self, handshake_data):
        hashed_handshake_data = hashlib.sha256()
        hashed_handshake_data.update(handshake_data)

        srv_verify_data = self.PRF(self._master_secret,
                                   "server finished",
                                   hashed_handshake_data.digest(),
                                   12)

        finished_msg = {"type": "server finished",
                        "verify_data": srv_verify_data}
        self.send_msg(finished_msg)

        ctl_reply = self.recv_msg()
        if ctl_reply["type"] != "ctl finished":
            raise SecSocketException("Handshake failed.")

        ctl_verify_data = self.PRF(self._master_secret,
                                   "ctl finished",
                                   hashed_handshake_data.digest(),
                                   12)

        if ctl_verify_data != ctl_reply["verify_data"]:
            raise SecSocketException("Handshake failed.")
        return
示例#3
0
    def handshake(self, sec_params):
        ctl_hello = self.recv_msg()
        if ctl_hello["type"] != "ctl_hello":
            raise SecSocketException("Handshake failed.")

        self._ctl_random = ctl_hello["ctl_random"]
        self._slave_random = os.urandom(28)

        slave_hello = {
            "type": "slave_hello",
            "slave_random": self._slave_random
        }
        self.send_msg(slave_hello)

        if sec_params["auth_types"] == "none":
            logging.warning("===================================")
            logging.warning("NO SECURE CHANNEL SETUP IS IN PLACE")
            logging.warning(" ALL COMMUNICATION IS IN PLAINTEXT")
            logging.warning("===================================")
            return True
        if sec_params["auth_types"] == "no-auth":
            logging.warning("===========================================")
            logging.warning("        NO AUTHENTICATION IN PLACE")
            logging.warning("SECURE CHANNEL IS VULNERABLE TO MIM ATTACKS")
            logging.warning("===========================================")
            cryptography_imports()
            self._dh_handshake()
        elif sec_params["auth_types"] == "ssh":
            cryptography_imports()
            self._ssh_handshake()
        elif sec_params["auth_types"] == "pubkey":
            cryptography_imports()
            srv_key = None
            try:
                with open(sec_params["privkey"], 'r') as f:
                    srv_key = load_pem_private_key(f.read(), None, backend)
            except:
                srv_key = None

            ctl_pubkeys = {}
            for fname in os.listdir(sec_params["ctl_pubkeys"]):
                path = os.path.join(sec_params["ctl_pubkeys"], fname)
                if not os.path.isfile(path):
                    continue
                try:
                    with open(path, 'r') as f:
                        ctl_pubkeys[fname] = load_pem_public_key(
                            f.read(), backend)
                except:
                    continue

            self._pubkey_handshake(srv_key, ctl_pubkeys)
        elif sec_params["auth_types"] == "password":
            cryptography_imports()
            self._passwd_handshake(sec_params["auth_password"])
        else:
            raise SecSocketException("Unknown authentication method.")
示例#4
0
    def handshake(self, sec_params):
        self._ctl_random = os.urandom(28)

        ctl_hello = {"type": "ctl_hello",
                     "ctl_random": self._ctl_random}
        self.send_msg(ctl_hello)
        agent_hello = self.recv_msg()

        if agent_hello["type"] != "agent_hello":
            raise SecSocketException("Handshake failed.")

        self._agent_random = agent_hello["agent_random"]

        if sec_params["auth_type"] == "none":
            logging.warning("===================================")
            logging.warning("%s:%d" % self._socket.getpeername())
            logging.warning("NO SECURE CHANNEL SETUP IS IN PLACE")
            logging.warning(" ALL COMMUNICATION IS IN PLAINTEXT")
            logging.warning("===================================")
            return True
        if sec_params["auth_type"] == "no-auth":
            logging.warning("===========================================")
            logging.warning("        NO AUTHENTICATION IN PLACE")
            logging.warning("SECURE CHANNEL IS VULNERABLE TO MIM ATTACKS")
            logging.warning("===========================================")
            cryptography_imports()
            self._dh_handshake()
        elif sec_params["auth_type"] == "ssh":
            cryptography_imports()
            self._ssh_handshake()
        elif sec_params["auth_type"] == "pubkey":
            cryptography_imports()
            ctl_identity = sec_params["identity"]
            ctl_key_path = sec_params["privkey"]
            try:
                with open(ctl_key_path, 'r') as f:
                    ctl_key = load_pem_private_key(f.read(), None, backend)
            except:
                ctl_key = None

            srv_key_path = sec_params["pubkey_path"]
            try:
                with open(srv_key_path, 'r') as f:
                    srv_key = load_pem_public_key(f.read(), backend)
            except:
                srv_key = None

            if srv_key is None or ctl_key is None:
                raise SecSocketException("Handshake failed.")

            self._pubkey_handshake(ctl_identity, ctl_key, srv_key)
        elif sec_params["auth_type"] == "password":
            cryptography_imports()
            self._passwd_handshake(sec_params["auth_passwd"])
        else:
            raise SecSocketException("Unknown authentication method.")
示例#5
0
def cryptography_imports():
    global cryptography_imported
    if cryptography_imported:
        return

    global ser
    global load_pem_private_key
    global load_pem_public_key
    global load_ssh_public_key
    global backend

    try:
        import cryptography
        import cryptography.hazmat.primitives.serialization as ser
        from cryptography.hazmat.primitives.serialization import load_pem_private_key
        from cryptography.hazmat.primitives.serialization import load_pem_public_key
        from cryptography.hazmat.primitives.serialization import load_ssh_public_key
        from cryptography.hazmat.backends import default_backend
    except ImportError:
        logging.error("Library 'cryptography' missing "\
                      "can't establish secure channel.")
        raise SecSocketException("Library 'cryptography' missing "\
                                 "can't establish secure channel.")

    backend = default_backend()
    cryptography_imported = True
示例#6
0
    def _dh_handshake(self):
        modp_group = DH_GROUP
        #private exponent
        ctl_privkey = int(
            os.urandom(modp_group["q_size"] + 1).encode('hex'), 16)
        ctl_privkey = ctl_privkey % modp_group["q"]
        #public key
        ctl_pubkey = pow(modp_group["g"], ctl_privkey, modp_group["p"])

        msg = {"type": "pub_dh", "value": ctl_pubkey}
        self.send_msg(msg)

        reply = self.recv_msg()
        if reply["type"] != "pub_dh":
            raise SecSocketException("Handshake failed.")

        srv_pubkey = reply["value"]

        ZZ = pow(srv_pubkey, ctl_privkey, modp_group["p"])
        ZZ = "{1:0{0}x}".format(modp_group['p_size'] * 2, ZZ)
        ZZ = self._master_secret.decode('hex')

        self._master_secret = self.PRF(ZZ, "master secret",
                                       self._ctl_random + self._slave_random,
                                       48)

        handshake_data = ""
        handshake_data += ("{1:0{0}x}".format(modp_group['p_size'] * 2,
                                              ctl_pubkey)).decode('hex')
        handshake_data += ("{1:0{0}x}".format(modp_group['p_size'] * 2,
                                              srv_pubkey)).decode('hex')

        self._init_cipher_spec()
        self._send_change_cipher_spec()
        self._validate_secret(handshake_data)
示例#7
0
    def _passwd_handshake(self, auth_passwd):
        msg = self.recv_msg()
        if msg["type"] != "srp_client_begin":
            raise SecSocketException("Handshake failed.")

        if msg["username"] != "lnst_user":
            raise SecSocketException("Handshake failed.")

        srp_group = SRP_GROUP
        p_bytes = "{1:0{0}x}".format(srp_group['p_size']*2, srp_group['p'])
        p_bytes = p_bytes.decode('hex')
        g_bytes = "{0:02x}".format(srp_group['g'])
        g_bytes = g_bytes.decode('hex')
        k = hashlib.sha256(p_bytes + g_bytes).digest()
        k = int(k.encode('hex'), 16)
        username = msg["username"]

        salt = os.urandom(16)

        x = hashlib.sha256(salt + username + auth_passwd).digest()

        x_int = int(x.encode('hex'), 16)

        v = pow(srp_group["g"], x_int, srp_group["p"])

        msg = {"type": "srp_server_salt",
               "salt": salt}

        self.send_msg(msg)

        reply = self.recv_msg()
        if reply["type"] != "srp_client_pub":
            raise SecSocketException("Handshake failed.")

        ctl_pubkey = reply["ctl_pubkey"]
        ctl_pubkey_int = int(ctl_pubkey.encode('hex'), 16)

        if (ctl_pubkey_int % srp_group["p"]) == 0:
            raise SecSocketException("Handshake failed.")

        srv_privkey = os.urandom(srp_group["q_size"]+1)
        srv_privkey_int = int(srv_privkey.encode('hex'), 16) % srp_group["q"]

        srv_pubkey_int = pow(srp_group["g"], srv_privkey_int, srp_group["p"])
        srv_pubkey_int = (srv_pubkey_int + k*v) % srp_group["p"]
        srv_pubkey = "{1:0{0}x}".format(srp_group['p_size']*2, srv_pubkey_int)
        srv_pubkey = srv_pubkey.decode('hex')

        msg = {"type": "srp_server_pub",
               "srv_pubkey": srv_pubkey}
        self.send_msg(msg)

        u = hashlib.sha256(ctl_pubkey + srv_pubkey).digest()
        u_int = int(u.encode('hex'), 16)

        S_int = pow(v, u_int, srp_group['p'])*ctl_pubkey_int
        S_int = pow(S_int, srv_privkey_int, srp_group["p"])
        S = "{1:0{0}x}".format(srp_group['p_size']*2, S_int)
        S = S.decode('hex')

        msg = self.recv_msg()
        if msg["type"] != "srp_client_m1":
            raise SecSocketException("Handshake failed.")

        client_m1 = msg["m1"]

        srv_m1 = hashlib.sha256(ctl_pubkey + srv_pubkey + S).digest()
        if client_m1 != srv_m1:
            raise SecSocketException("Handshake failed.")

        srv_m2 = hashlib.sha256(ctl_pubkey + srv_m1 + S).digest()
        msg = {"type": "srp_server_m2",
               "m2": srv_m2}
        self.send_msg(msg)

        K = hashlib.sha256(S).digest()
        self._master_secret = self.PRF(K,
                                       "master secret",
                                       self._ctl_random + self._agent_random,
                                       48)

        self._init_cipher_spec()
        self._send_change_cipher_spec()
示例#8
0
    def _ssh_handshake(self):
        srv_keys = []
        srv_pubkeys = []
        authorized_keys = []
        sshd_key_paths = ["/etc/ssh/ssh_host_rsa_key",
                          "/etc/ssh/ssh_host_ecdsa_key"]
        ssh_dir_path = os.path.expanduser("~/.ssh")
        for f_name in sshd_key_paths:
            try:
                with open(f_name, 'r') as f:
                    srv_keys.append(load_pem_private_key(f.read(),
                                                         None,
                                                         backend))
                    srv_pubkeys.append(srv_keys[-1].public_key())
            except:
                continue

        if os.path.isfile(ssh_dir_path+"/authorized_keys"):
            with open(ssh_dir_path+"/authorized_keys", 'r') as f:
                for line in f.readlines():
                    try:
                        authorized_keys.append(load_ssh_public_key(line,
                                                                   backend))
                    except:
                        continue
        else:
            logging.error("No authorized keys loaded.")

        msg = self.recv_msg()
        if msg["type"] != "ssh_client_hello":
            raise SecSocketException("Handshake failed.")
        try:
            ctl_ssh_pubkey = load_pem_public_key(msg["ctl_ssh_pubkey"],
                                                 backend)
        except:
            raise SecSocketException("Handshake failed.")

        authorized = False
        for key in authorized_keys:
            if self._cmp_pub_keys(key, ctl_ssh_pubkey):
                authorized = True
                break
        if not authorized:
            raise SecSocketException("Handshake failed.")

        pem_pubkeys = []
        for key in srv_pubkeys:
            pem_key = key.public_bytes(
                            encoding=ser.Encoding.PEM,
                            format=ser.PublicFormat.SubjectPublicKeyInfo)
            pem_pubkeys.append(pem_key)

        msg = {"type": "ssh_server_hello",
               "srv_ssh_pubkeys": pem_pubkeys}
        self.send_msg(msg)

        msg = self.recv_msg()
        if msg["type"] != "ssh_client_key_select":
            raise SecSocketException("Handshake failed.")

        if not self._verify_signature(ctl_ssh_pubkey,
                                      str(msg["index"]),
                                      msg["signature"]):
            raise SecSocketException("Handshake failed.")

        self._pubkey_handshake(srv_keys[msg["index"]], {"ssh": ctl_ssh_pubkey})
示例#9
0
    def _passwd_handshake(self, auth_passwd):
        srp_group = SRP_GROUP
        p_bytes = "{1:0{0}x}".format(srp_group['p_size'] * 2, srp_group['p'])
        p_bytes = p_bytes.decode('hex')
        g_bytes = "{0:02x}".format(srp_group['g'])
        g_bytes = g_bytes.decode('hex')
        k = hashlib.sha256(p_bytes + g_bytes).digest()
        k = int(k.encode('hex'), 16)

        username = "******"

        msg = {"type": "srp_client_begin", "username": username}
        self.send_msg(msg)

        reply = self.recv_msg()
        if reply["type"] != "srp_server_salt":
            raise SecSocketException("Handshake failed.")

        salt = reply["salt"]

        x = hashlib.sha256(salt + username + auth_passwd).digest()
        x_int = int(x.encode('hex'), 16)

        ctl_privkey = os.urandom(srp_group["q_size"] + 1)
        ctl_privkey_int = int(ctl_privkey.encode('hex'), 16) % srp_group["q"]

        ctl_pubkey_int = pow(srp_group["g"], ctl_privkey_int, srp_group["p"])
        ctl_pubkey = "{1:0{0}x}".format(srp_group['p_size'] * 2,
                                        ctl_pubkey_int)
        ctl_pubkey = ctl_pubkey.decode('hex')

        msg = {"type": "srp_client_pub", "ctl_pubkey": ctl_pubkey}
        self.send_msg(msg)

        reply = self.recv_msg()
        if reply["type"] != "srp_server_pub":
            raise SecSocketException("Handshake failed.")

        srv_pubkey = reply["srv_pubkey"]
        srv_pubkey_int = int(srv_pubkey.encode('hex'), 16)

        if (srv_pubkey_int % srp_group["p"]) == 0:
            raise SecSocketException("Handshake failed.")

        u = hashlib.sha256(ctl_pubkey + srv_pubkey).digest()
        u_int = int(u.encode('hex'), 16)

        S_int = srv_pubkey_int - k * pow(srp_group['g'], x_int, srp_group['p'])
        S_int = pow(S_int, ctl_privkey_int + u_int * x_int, srp_group['p'])
        S = "{1:0{0}x}".format(srp_group['p_size'] * 2, S_int)
        S = S.decode('hex')

        m1 = hashlib.sha256(ctl_pubkey + srv_pubkey + S).digest()
        msg = {"type": "srp_client_m1", "m1": m1}
        self.send_msg(msg)

        reply = self.recv_msg()
        if reply["type"] != "srp_server_m2":
            raise SecSocketException("Handshake failed.")
        srv_m2 = reply["m2"]

        client_m2 = hashlib.sha256(ctl_pubkey + m1 + S).digest()
        if srv_m2 != client_m2:
            raise SecSocketException("Handshake failed.")

        K = hashlib.sha256(S).digest()
        self._master_secret = self.PRF(K, "master secret",
                                       self._ctl_random + self._slave_random,
                                       48)

        self._init_cipher_spec()
        self._send_change_cipher_spec()
示例#10
0
    def _ssh_handshake(self):
        ctl_ssh_key = None
        known_hosts = []
        ssh_dir_path = os.path.expanduser("~/.ssh")
        if os.path.isfile(ssh_dir_path + "/known_hosts"):
            with open(ssh_dir_path + "/known_hosts", 'r') as f:
                for line in f.readlines():
                    key = line[line.find(' ') + 1:]
                    try:
                        known_hosts.append(load_ssh_public_key(key, backend))
                    except:
                        continue
        else:
            logging.error("No known hosts loaded.")

        try:
            with open(ssh_dir_path + "/id_rsa", 'r') as f:
                ctl_ssh_key = load_pem_private_key(f.read(), None, backend)
        except:
            ctl_ssh_key = None
            logging.error("No controller ssh key loaded.")

        if not ctl_ssh_key:
            raise SecSocketException("Handshake failed.")

        ctl_ssh_pubkey = ctl_ssh_key.public_key()
        ctl_ssh_pubkey_pem = ctl_ssh_pubkey.public_bytes(
            encoding=ser.Encoding.PEM,
            format=ser.PublicFormat.SubjectPublicKeyInfo)
        msg = {
            "type": "ssh_client_hello",
            "ctl_ssh_pubkey": ctl_ssh_pubkey_pem
        }

        self.send_msg(msg)
        msg = self.recv_msg()
        if msg["type"] != "ssh_server_hello":
            raise SecSocketException("Handshake failed.")
        srv_ssh_pubkeys = []
        for key in msg["srv_ssh_pubkeys"]:
            try:
                srv_ssh_pubkeys.append(load_pem_public_key(key, backend))
            except:
                continue

        srv_ssh_pubkey = None
        i = 0
        for key in srv_ssh_pubkeys:
            for host in known_hosts:
                if self._cmp_pub_keys(key, host):
                    srv_ssh_pubkey = host
                    break
            if srv_ssh_pubkey is not None:
                break
            i += 1
        if not srv_ssh_pubkey:
            raise SecSocketException("Handshake failed.")

        msg = {
            "type": "ssh_client_key_select",
            "index": i,
            "signature": self._sign_data(str(i), ctl_ssh_key)
        }
        self.send_msg(msg)

        self._pubkey_handshake("ssh", ctl_ssh_key, srv_ssh_pubkey)