Внешняя аутентификация пользователя в рамках сеанса PAM/сеанса PAM в рамках сеанса PAM

Внешняя аутентификация пользователя в рамках сеанса PAM/сеанса PAM в рамках сеанса PAM

Существует ли способ корректной аутентификации пользователя в рамках пользовательского сеанса PAM?

В настоящее время я пишу свой собственный модуль аутентификации PAM, который позволяет пользователю входить в систему через внешний токен. Этот токен должен быть сгенерирован до того, как пользователь сможет войти в систему с помощью моего модуля. Поэтому я хотел бы вернуться к аутентификации PAM по умолчанию, когда токена нет, и продолжить работу с моим кодом, как только пользователь аутентифицируется.

Возможно ли это как-то? В псевдокоде мой модуль выглядит так:

pam_sm_authenticate() {
  if (first_login) {
    code_copied_from_pam_unix_to_authenticate_user();
    // do something else here?
  } else {
    custom_auth();
  }
}

В качестве быстрого решения я скопировал код из модуля pam_unix Linux в свой собственный, и он работает. Однако это не очень удовлетворительно, так как требует много дополнительных библиотек и будет работать только до тех пор, пока pam_unix не изменится. Я бы предпочел открыть еще один сеанс PAM внутри своего сеанса, но у меня это не работает.

решение1

Не позволяйте вашему коду выполнять всю логику: сначала используйте PAM и его конфигурацию, чтобы убедиться, что ваш модуль работает в наилучших условиях (т. е. не требует копирования pam_unixкода).

Для начала позвольте мне предложить еще один псевдокод для вашего модуля:

pam_sm_authenticate() {
    if (first_login) return PAM_CRED_INSUFFICIENT;
    else custom_auth();
}

Здесь я считаю,первый входбыть случаем недостаточности учетных данных. Я сообщаю PAM, что модуль дает сбой, поскольку у него нет всего необходимого для полной аутентификации пользователя. Теперь, предположив, что ваш модуль называется my_module, возможная конфигурация будет такой:

auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1]      pam_unix.so
auth sufficient                  my_module.so
auth requisite                   pam_deny.so

Вот подробности:

  • Сначала запрос проходит через my_module. Здесь есть несколько возможностей:

    1. Первый вход: ваш модуль вернул PAM_CRED_INSUFFICIENT. Этот случайпойманныйс помощью PAM (через cred_insufficient), в этом случае он настроен на отметку цепочки как успешной ( ok), нопродолжать идти.
    2. Это был не первый вход, вы прошли custom_auth()и он был успешным (он вернулся PAM_SUCCESS). В этом случае мы ставим точку в цепочке ( done):доступ предоставлен.
    3. Это был не первый вход в систему, и custom_auth()он не завершился хорошо ( PAM_AUTH_ERRили другие внутренние ошибки). В этом случае пропустите следующие 2 строки ( default=2). Цепочка переходит прямо в pam_deny, что всегда приводит к ошибке:доступ запрещен.
  • В первом сценарии цепочка продолжается до pam_unix. Здесь есть две возможности:

    1. Аутентификация UNIX прошла успешно. Это отмечает цепочку как успешную ( ok) ипереходит к следующему модулю.
    2. Аутентификация UNIX не удалась. Следующий модуль пропускается ( default=1), и цепочка заканчивается на pam_deny:доступ запрещен.
  • Если вы достигли третьей строки, это означает, что my_moduleзакончилось с PAM_CRED_INSUFFICIENTпервым разом, и что это pam_unixудалось. Ваш модуль снова вызывается ( // do something else here?) как sufficient. Снова две возможности:

    1. На этот раз ваш модуль справился успешно:доступ предоставлен.
    2. Модуль снова дает сбой, но уже по другой причине, нежели недостаточность учетных данных:доступ запрещен.

Вы также можете захотеть выполнить пользовательский кодпосле аутентификации UNIX, даже если это не удалось. Чтобы сделать это, измените вторую строку на:

auth [success=ok default=bad]    pam_unix.so

Это заставит цепочку пройти my_moduleеще раз, несмотря ни на что, но цепочка будет отмечена какнеуспешный. Даже если ваш модуль завершится успешно, цепочка даст сбой.

Вы также можете захотеть, чтобы ваш модуль знал, сколько раз мы вызывали его в цепочке: отличайте первый вызов my_moduleот второго. Это можно легко сделать с помощью аргументов:

auth [cred_insufficient=ok success=done default=2] my_module.so
auth [success=ok default=1]      pam_unix.so
auth sufficient                  my_module.so second_time
auth requisite                   pam_deny.so

Здесь второму вызову pam_sm_authenticateбудет передан аргумент (через argvи argc), который должен вам помочьнайтиваш модуль в цепочке во время выполнения. Конечно, вашего firstLoginусловия должно быть достаточно, чтобы сделать такое различие.

Связанный контент