diff --git a/keepercommander/commands/ssh_agent.py b/keepercommander/commands/ssh_agent.py index 5e519f630..3ac854170 100644 --- a/keepercommander/commands/ssh_agent.py +++ b/keepercommander/commands/ssh_agent.py @@ -181,6 +181,16 @@ def is_private_key_name(name): # type: (str) -> bool return False +KEY_SIZE_MIN = 119 # Smallest possible size for ed25519 private key in PKCS#8 format +KEY_SIZE_MAX = 4000 +def is_valid_key_value(value): + return isinstance(value, str) and KEY_SIZE_MIN <= len(value) < KEY_SIZE_MAX + +def is_valid_key_file(file): + try: + return KEY_SIZE_MIN <= file.size < KEY_SIZE_MAX + except: + return False def try_extract_private_key(params, record_or_uid): # type: (KeeperParams, Union[str, vault.KeeperRecord]) -> Optional[Tuple[str, str]] @@ -207,7 +217,7 @@ def try_extract_private_key(params, record_or_uid): # check notes field if not private_key: if isinstance(record, (vault.PasswordRecord, vault.TypedRecord)): - if 444 <= len(record.notes) < 4000: + if is_valid_key_value(record.notes): header, _, _ = record.notes.partition('\n') if is_private_key(header): private_key = record.notes @@ -217,14 +227,14 @@ def try_extract_private_key(params, record_or_uid): if isinstance(record, vault.TypedRecord): try_values = (x.get_default_value() for x in itertools.chain(record.fields, record.custom) if x.type in ('text', 'multiline', 'secret', 'note')) for value in (x for x in try_values if x): - if isinstance(value, str) and 444 <= len(value) < 4000: + if is_valid_key_value(value): header, _, _ = value.partition('\n') if is_private_key(header): private_key = value break elif isinstance(record, vault.PasswordRecord): for value in (x.value for x in record.custom if x.value): - if isinstance(value, str) and 444 <= len(value) < 4000: + if is_valid_key_value(value): header, _, _ = value.partition('\n') if is_private_key(header): private_key = value @@ -244,7 +254,7 @@ def try_extract_private_key(params, record_or_uid): if file_record.name and file_record.name != file_record.title: names.append(file_record.name) if any(True for x in names if is_private_key_name(x)): - if 444 <= file_record.size < 4000: + if is_valid_key_file(file_record): key_file_uids.append(file_uid) if len(key_file_uids) == 1: download_rq = next(attachment.prepare_attachment_download(params, key_file_uids[0]), None) @@ -258,7 +268,7 @@ def try_extract_private_key(params, record_or_uid): if atta.name and atta.title != atta.name: names.append(atta.name) if any(True for x in names if is_private_key_name(x)): - if 444 <= atta.size < 4000: + if is_valid_key_file(atta): key_attachment_ids.append(atta.id) if len(key_attachment_ids) == 1: download_rq = next(attachment.prepare_attachment_download(params, record.record_uid, key_attachment_ids[0]), None)