Marco Ricci commited on 2024-12-13 14:52:17
Zeige 2 geänderte Dateien mit 38 Einfügungen und 8 Löschungen.
While the configuration and interactive selection of an SSH key is properly guarded against (i.e., any exceptions are wrapped into proper command-line error messages), the calls to `vault.Vault.phrase_from_key` were not similarly guarded. This has now been fixed. The fix also uncovered an incorrectly specified mock function in the test suite, which has been repaired as well.
| ... | ... |
@@ -1703,6 +1703,36 @@ def derivepassphrase_vault( # noqa: C901,PLR0912,PLR0913,PLR0914,PLR0915 |
| 1703 | 1703 |
logger.error(msg, *args, stacklevel=stacklevel, **kwargs) |
| 1704 | 1704 |
ctx.exit(1) |
| 1705 | 1705 |
|
| 1706 |
+ def key_to_phrase(key_: str | bytes | bytearray, /) -> bytes | bytearray: |
|
| 1707 |
+ key = base64.standard_b64decode(key_) |
|
| 1708 |
+ try: |
|
| 1709 |
+ with ssh_agent.SSHAgentClient.ensure_agent_subcontext() as client: |
|
| 1710 |
+ try: |
|
| 1711 |
+ return vault.Vault.phrase_from_key(key, conn=client) |
|
| 1712 |
+ except ssh_agent.SSHAgentFailedError as e: |
|
| 1713 |
+ try: |
|
| 1714 |
+ keylist = client.list_keys() |
|
| 1715 |
+ except ssh_agent.SSHAgentFailedError: |
|
| 1716 |
+ pass |
|
| 1717 |
+ except Exception as e2: # noqa: BLE001 |
|
| 1718 |
+ e.__context__ = e2 |
|
| 1719 |
+ else: |
|
| 1720 |
+ if not any(k == key for k, _ in keylist): |
|
| 1721 |
+ err( |
|
| 1722 |
+ 'The requested SSH key is not loaded ' |
|
| 1723 |
+ 'into the agent.' |
|
| 1724 |
+ ) |
|
| 1725 |
+ err(e) |
|
| 1726 |
+ except KeyError: |
|
| 1727 |
+ err('Cannot find running SSH agent; check SSH_AUTH_SOCK')
|
|
| 1728 |
+ except NotImplementedError: |
|
| 1729 |
+ err( |
|
| 1730 |
+ 'Cannot connect to SSH agent because ' |
|
| 1731 |
+ 'this Python version does not support UNIX domain sockets' |
|
| 1732 |
+ ) |
|
| 1733 |
+ except OSError as e: |
|
| 1734 |
+ err('Cannot connect to SSH agent: %s', e.strerror)
|
|
| 1735 |
+ |
|
| 1706 | 1736 |
def get_config() -> _types.VaultConfig: |
| 1707 | 1737 |
try: |
| 1708 | 1738 |
return _load_config() |
| ... | ... |
@@ -2047,13 +2077,6 @@ def derivepassphrase_vault( # noqa: C901,PLR0912,PLR0913,PLR0914,PLR0915 |
| 2047 | 2077 |
if k in service_keys and v is not None |
| 2048 | 2078 |
} |
| 2049 | 2079 |
|
| 2050 |
- def key_to_phrase( |
|
| 2051 |
- key: str | bytes | bytearray, |
|
| 2052 |
- ) -> bytes | bytearray: |
|
| 2053 |
- return vault.Vault.phrase_from_key( |
|
| 2054 |
- base64.standard_b64decode(key) |
|
| 2055 |
- ) |
|
| 2056 |
- |
|
| 2057 | 2080 |
if use_phrase: |
| 2058 | 2081 |
form = cast( |
| 2059 | 2082 |
Literal['NFC', 'NFD', 'NFKC', 'NFKD'], |
| ... | ... |
@@ -30,6 +30,7 @@ from derivepassphrase import _types, cli, ssh_agent, vault |
| 30 | 30 |
__all__ = () |
| 31 | 31 |
|
| 32 | 32 |
if TYPE_CHECKING: |
| 33 |
+ import socket |
|
| 33 | 34 |
from collections.abc import Callable, Iterator, Mapping, Sequence |
| 34 | 35 |
|
| 35 | 36 |
import click.testing |
| ... | ... |
@@ -1412,7 +1413,13 @@ def suitable_ssh_keys(conn: Any) -> Iterator[_types.KeyCommentPair]: |
| 1412 | 1413 |
] |
| 1413 | 1414 |
|
| 1414 | 1415 |
|
| 1415 |
-def phrase_from_key(key: bytes) -> bytes: |
|
| 1416 |
+def phrase_from_key( |
|
| 1417 |
+ key: bytes, |
|
| 1418 |
+ /, |
|
| 1419 |
+ *, |
|
| 1420 |
+ conn: ssh_agent.SSHAgentClient | socket.socket | None = None, |
|
| 1421 |
+) -> bytes: |
|
| 1422 |
+ del conn |
|
| 1416 | 1423 |
if key == DUMMY_KEY1: # pragma: no branch |
| 1417 | 1424 |
return DUMMY_PHRASE_FROM_KEY1 |
| 1418 | 1425 |
raise KeyError(key) # pragma: no cover |
| 1419 | 1426 |