From bd16e339c0132459d912a7fc01fd68194133c66d Mon Sep 17 00:00:00 2001 From: Stitch505 <–Gleb@stitch505.su> Date: Fri, 22 May 2026 23:48:58 +0400 Subject: [PATCH] fix: ssh-copy-id interactive (capture=False) so password prompt visible; encrypted keys just warned, not source-server passphrase confusion; clear auth choice menu for target --- transfer/ssh.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/transfer/ssh.py b/transfer/ssh.py index dc50c6a..51d40e9 100644 --- a/transfer/ssh.py +++ b/transfer/ssh.py @@ -105,20 +105,21 @@ def generate_temp_keypair(host_label): def ssh_copy_id(host, user, port, pubkey_path): - """Копирует публичный ключ на target через ssh-copy-id или вручную.""" + """Копирует публичный ключ на target через ssh-copy-id. Интерактивно, т.к. запрашивает пароль target.""" if exists("ssh-copy-id"): - info("Копируем публичный ключ через ssh-copy-id ...") - # Добавляем SSH опции чтобы избежать зависания + warn("⚠ Сейчас запустится ssh-copy-id — на target запросит ПАРОЛЬ. Введите его ниже ↓") + # Запускаем без capture_output, чтобы prompt пароля был виден пользователю r = run( - f"ssh-copy-id -p {port} -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -i '{pubkey_path}' {user}@{host}", + f"ssh-copy-id -p {port} -o ConnectTimeout=30 -o StrictHostKeyChecking=accept-new -i '{pubkey_path}' {user}@{host}", check=False, - timeout=60 + capture=False, + timeout=120 ) if r.returncode == 0: success("Ключ добавлен на target через ssh-copy-id") return True else: - warn(f"ssh-copy-id не удался: {r.stderr.strip()[:120]}") + warn(f"ssh-copy-id не удался (код: {r.returncode})") return False @@ -218,28 +219,21 @@ def pick_or_setup_ssh_key(host, user, port): if working_key: return working_key["private"] - # 3. Проверить ключи С passphrase (если пользователь знает) + # 3. Проверить ключи — если зашифрован и не подходит, просто сообщаем и идём дальше + encrypted_count = 0 for k in keys: label = os.path.basename(k["private"]) - # Проверим, не passphrase ли мешает ok, _, err = check_ssh_connectivity(host, user, port, key_path=k["private"]) if not ok and ("passphrase" in err.lower() or "password" in err.lower()): - if confirm(f"Ключ '{label}' зашифрован. Ввести passphrase и попробовать", default="y"): - from core.color import prompt_password - pw = prompt_password(f"Passphrase для {label}") - if pw and try_key_with_passphrase(k["private"], pw): - # После ssh-add ключ должен работать - ok2, _, _ = check_ssh_connectivity(host, user, port, key_path=k["private"]) - if ok2: - success(f"Ключ '{label}' разблокирован и работает!") - return k["private"] - else: - warn(f"Passphrase введён, но ключ всё равно не подходит для {host}") + warn(f" ! Ключ '{label}' зашифрован (passphrase). Пропускаем.") + encrypted_count += 1 + if encrypted_count and not working_key: + info(f"Все найденные ключи зашифрованы или не подходят для {host}.") # 4. Ничего не работает — выбор метода print() info("Выберите способ подключения к target:") - print(" 1 Пароль (sshpass) — ввести пароль прямо сейчас") + print(" 1 Пароль (sshpass) — ввести пароль от target прямо сейчас") print(" 2 Сгенерировать временный ed25519 ключ — скрипт сам сделает ssh-copy-id") print(" 0 Отмена — передать архив вручную") choice = prompt("Ваш выбор", default="1").strip()