Вопрос или проблема
Я пытался использовать pam_exec.so на Ubuntu, чтобы вызвать скрипт, запросить ввод пользователя и позволить пользователю войти через SSH, если скрипт завершился с кодом 0. Мне не удалось это сделать. Поэтому я написал простой скрипт, чтобы протестировать pam_exec.so и выяснить, в чем была проблема с моим оригинальным скриптом. Однако я сталкиваюсь с теми же проблемами даже с этим простым скриптом.
/usr/local/bin/test.sh
#!/bin/bash
echo -n "Пожалуйста, введите ваше имя:"
read name
echo "Здравствуйте, $name"
Я вызвал его, добавив следующую строку после @include common-auth
в /etc/pam.d/sshd
auth required pam_exec.so stdout /usr/local/bin/test.sh
Но когда я подключаюсь по SSH к этой системе, как видно ниже, я не получаю запроса на ввод. Как только я ввожу пароль, я захожу в систему. Однако вывод скрипта виден.
Затем я изменил вышеуказанный скрипт следующим образом, чтобы он завершался с кодом 1, если ввод не был предоставлен.
#!/bin/bash
echo -n "Пожалуйста, введите ваше имя:"
read name
if [ -z "$name" ]
then
exit 1
else
echo "Здравствуйте, $name"
exit 0
fi
После этого я не смог подключиться по SSH к системе (скриншот ниже), даже когда вводил правильный пароль, и я не вижу никакого вывода скрипта.
Так что я хочу знать, как я могу исправить эту проблему и использовать pam_exec.so для запуска скрипта, получения ввода пользователя и разрешения авторизации по ssh только в том случае, если этот скрипт завершился с кодом 0?
Я не знаком с реализацией pam_exec.so
, но я сделал небольшой PAM, и я думаю, что это сложная задача для любого модуля, чтобы обрабатывать интерактивную сессию с внешним скриптом из-за того, как работает взаимодействие PAM (pam_conv_*
функции) и необходимости знать, когда внешний скрипт будет считывать из stdin
или нет (поскольку скрипт не просто exec
по модулю в фоновом режиме).
В зависимости от того, сколько усилий вы готовы предпринять, создание PAM не является сложным, и у вас есть примеры, которые легко читать, в python или golang.
Еще один (возможно, более быстрый) вариант – использовать опцию stdin
в pam_exec.so
.
Оставляя в стороне вопросы безопасности и в зависимости от вашего случая использования, этого может быть достаточно, так как это отправляет пароль в стандартный ввод скрипта.
Если для вас приемлемо, чтобы ввод вашего скрипта был объединен с паролем (как в некоторых реализациях 2FA, где вы вводите пароль + OTP в поле для пароля):
- Добавьте опцию
stdin
в свою строкуpam_exec.so
- В вашем скрипте разделите пароль и ваш второй ввод
- Обработайте аутентификацию пароля самостоятельно (так как
pam_unix
не сможет это сделать с дополнительным вводом) - Используйте ваш дополнительный ввод
Ответ или решение
Проблема запросов пользовательского ввода через скрипт, вызываемый pam_exec
Использование pam_exec.so
в системе Ubuntu для вызова скриптов может стать сложной задачей, особенно когда требуется взаимодействие с пользователем через терминал SSH. Давайте рассмотрим, почему ваш скрипт не работает как ожидалось, и как можно исправить эту ситуацию.
Суть проблемы
Вы пытаетесь вызвать скрипт, который запрашивает ввод пользователя и должен позволять SSH доступ только в том случае, если скрипт возвращает код завершения 0. Однако, скрипт, который вы написали, не вызывает ожидаемого взаимодействия через stdin
в контексте PAM, что и приводит к указанным вами проблемам.
Причины неудачи
-
PAM и взаимодействие с пользователем: PAM (Pluggable Authentication Modules) не предназначен для обработки интерактивных сеансов с помощью внешних скриптов в том виде, как вы это хотели сделать. Когда
pam_exec.so
запускает ваш скрипт, он не может правильно установить для него управление, чтобы позволить пользователю вводить данные. -
Конфигурация PAM: Ваша конфигурация (строка
auth required pam_exec.so stdout /usr/local/bin/test.sh
) не позволяет скрипту эффективно взаимодействовать с пользователем.pam_exec
запускает скрипт в контексте, где ввод из терминала может не направляться в скрипт.
Рекомендации по решению проблемы
Есть несколько способов обойти найденную вами проблему:
-
Использование параметра
stdin
: В случае, если вы хотите передать ввод пользователя, вы можете использовать параметрstdin
в конфигурации вашего вызоваpam_exec.so
. Это позволит отправить пароль пользователя в стандартный ввод вашего скрипта.Обновите вашу строку конфигурации в
/etc/pam.d/sshd
на следующую:auth required pam_exec.so stdin /usr/local/bin/test.sh
В этом случае вам потребуется модифицировать ваш скрипт, чтобы разобрать входящие данные. Например, вы можете ожидать, что первая часть ввода будет паролем, а вторая — именем пользователя.
-
Создание пользовательского модуля PAM: Создание собственного модуля PAM с использованием языка программирования, такого как Python или Go, может дать вам больший контроль над взаимодействием с пользователем. Это более сложный путь, который требует разработки, но позволит более гибко управлять авторизацией.
-
Реализация альтернативного метода ввода: Если два вышеописанных решения для вас не подходят, можно рассмотреть возможность использования сторонних средств, таких как SSH-ключи в сочетании с дополнительной аутентификацией (например, TOTP), что может исключить необходимость запрашивать ввод пользователя из PAM-скрипта.
Заключение
Работа с PAM и pam_exec.so
может быть непростой, особенно когда речь идет о вводе от пользователя. Однако, используя параметры stdin
или разрабатывая собственный модуль, вы сможете добиться желаемого взаимодействия и обеспечить корректную аутентификацию в вашей системе. Рекомендуется тестировать измененные конфигурации на тестовых машинах перед тем, как внедрять их в рабочую среду, чтобы избежать непредсказуемых последствий и обеспечить безопасность.