def _ssh_authentication_input_loop(self, hostkeys: paramiko.HostKeys, key: paramiko.PKey) -> None: # Ask user for permission to continue # let it look like openssh sha64_fingerprint = base64.b64encode( hashlib.sha256(base64.b64decode( key.get_base64())).digest()).decode("utf-8")[:-1] key_type = key.get_name().replace("ssh-", "").upper() print(f"The authenticity of host '{self.hostname}' can't " "be established.") print(f"{key_type} key fingerprint is {sha64_fingerprint}.") print("Are you sure you want to continue connecting (yes/no)? ", end="") add = input() while True: if add == "yes": hostkeys.add(self.hostname, key.get_name(), key) # ask user if the key should be added permanently print( f"Do you want to add {self.hostname} " "to known_hosts (yes/no)? ", end="", ) save = input() while True: if save == "yes": try: hostkeys.save(filename=self.known_hosts_file) except OSError as e: raise GvmError( "Something went wrong with writing " f"the known_hosts file: {e}") from None logger.info( "Warning: Permanently added '%s' (%s) to " "the list of known hosts.", self.hostname, key_type, ) break elif save == "no": logger.info( "Warning: Host '%s' (%s) not added to " "the list of known hosts.", self.hostname, key_type, ) break else: print("Please type 'yes' or 'no': ", end="") save = input() break elif add == "no": return sys.exit( "User denied key. Host key verification failed.") else: print("Please type 'yes' or 'no': ", end="") add = input()
def _create_connection(self, params: StorageConfig) -> SFTPClient: self.__log.debug('Creating connection to SSH server ' + params['host']) self.__ssh = SSHClient() if 'enableHostKeys' not in params or params['enableHostKeys']: self.__ssh.load_system_host_keys(filename=params.get('hostKeysFilePath')) should_save_host_keys = False if 'knownHostsPolicy' in params: policy: str = params['knownHostsPolicy'].lower() if policy == 'reject': self.__ssh.set_missing_host_key_policy(RejectPolicy) elif policy == 'auto-add': self.__ssh.set_missing_host_key_policy(AutoAddPolicy) should_save_host_keys = True elif policy == 'ignore': self.__ssh.set_missing_host_key_policy(WarningPolicy) pkey = None if 'privateKey' in params: pkey = PKey(data=params['privateKey']) self.__ssh.connect(hostname=params['host'], port=params.get('port', 22), username=params.get('user'), password=params.get('password'), pkey=pkey, key_filename=params.get('privateKeyPath'), allow_agent=params.get('allowAgent'), compress=params.get('compress')) if should_save_host_keys and 'hostKeysFilePath' in params: self.__ssh.save_host_keys(filename=params['hostKeysFilePath']) self.__log.debug('Starting SFTP client') return self.__ssh.open_sftp()
def _validate_key(host: str, server_key: PKey): known_hosts_file = '~/.ssh/known_hosts' host_keys = HostKeys() host_keys.load(os.path.expanduser(known_hosts_file)) known_server_keys = host_keys.get(host) add_host_key_instructions = 'You can add the host key with `\n' \ f'ssh-keyscan -H {host} >> {known_hosts_file}\n`' if known_server_keys is None: raise SSHAuthenticationError( f'plz host is not known. {add_host_key_instructions}') known_server_keys = host_keys.get(host) if known_server_keys.get(server_key.get_name()) is None: raise SSHAuthenticationError( f'No key found for host {host} with name ' f'{server_key.get_name()}. {add_host_key_instructions}') if server_key != known_server_keys.get(server_key.get_name()): raise SSHAuthenticationError( f'Bad host key for `{host}`. Fix your `{known_hosts_file}` file')
def auth_publickey(self, username: Text, host: Text, port: int, key: PKey) -> int: ssh_pub_key = SSHKey(f"{key.get_name()} {key.get_base64()}") ssh_pub_key.parse() if key.can_sign(): logging.debug( "AuthenticatorPassThrough.auth_publickey: username=%s, key=%s %s %sbits", username, key.get_name(), ssh_pub_key.hash_sha256(), ssh_pub_key.bits) return self.connect(username, host, port, AuthenticationMethod.publickey, key=key) # Ein Publickey wird nur direkt von check_auth_publickey # übergeben. In dem Fall müssen wir den Client authentifizieren, # damit wir auf den Agent warten können! publickey = paramiko.pkey.PublicBlob(key.get_name(), key.asbytes()) if probe_host(host, port, username, publickey): logging.debug( f"Found valid key for host {host}:{port} username={username}, key={key.get_name()} {ssh_pub_key.hash_sha256()} {ssh_pub_key.bits}bits" ) return paramiko.common.AUTH_SUCCESSFUL return paramiko.common.AUTH_FAILED
def get_sftp_conn(config): """Make a SFTP connection, returns sftp client and connection objects""" remote = config.get('remote_location') parts = urlparse(remote) if ':' in parts.netloc: hostname, port = parts.netloc.split(':') else: hostname = parts.netloc port = 22 port = int(port) username = config.get('remote_username') or getuser() luser = get_local_user(username) sshdir = get_ssh_dir(config, luser) hostkey = get_host_keys(hostname, sshdir) try: sftp = None keys = get_ssh_keys(sshdir) transport = Transport((hostname, port)) while not keys.empty(): try: key = PKey.from_private_key_file(keys.get()) transport.connect( hostkey=hostkey, username=username, password=None, pkey=key) sftp = SFTPClient.from_transport(transport) break except (PasswordRequiredException, SSHException): pass if sftp is None: raise SaChannelUpdateTransportError("SFTP connection failed") return sftp, transport except BaseException as msg: raise SaChannelUpdateTransportError(msg)
def get_sftp_conn(config): """Make a SFTP connection, returns sftp client and connection objects""" remote = config.get('remote_location') parts = urlparse(remote) if ':' in parts.netloc: hostname, port = parts.netloc.split(':') else: hostname = parts.netloc port = 22 port = int(port) username = config.get('remote_username') or getuser() luser = get_local_user(username) sshdir = get_ssh_dir(config, luser) hostkey = get_host_keys(hostname, sshdir) try: sftp = None keys = get_ssh_keys(sshdir) transport = Transport((hostname, port)) while not keys.empty(): try: key = PKey.from_private_key_file(keys.get()) transport.connect(hostkey=hostkey, username=username, password=None, pkey=key) sftp = SFTPClient.from_transport(transport) break except (PasswordRequiredException, SSHException): pass if sftp is None: raise SaChannelUpdateTransportError("SFTP connection failed") return sftp, transport except BaseException as msg: raise SaChannelUpdateTransportError(msg)
def generate_host_key(pkey: paramiko.PKey): key_fh = StringIO() pkey.write_private_key(key_fh) key_fh.seek(0) key_obj = paramiko.RSAKey(file_obj=key_fh) return key_obj.get_base64()
def generate_key_string(pkey: paramiko.PKey): key_fh = StringIO() pkey.write_private_key(key_fh) key_fh.seek(0) key_str = key_fh.read() return key_str
def generate_key_string(pkey: paramiko.PKey, passphrase: Optional[str] = None): key_fh = StringIO() pkey.write_private_key(key_fh, password=passphrase) key_fh.seek(0) key_str = key_fh.read() return key_str