PAM в Linux:есть ли способ пропустить локальную аутентификацию, если удаленная / внешняя база данных аутентификации возвращает отрицательный ответ?

Дорогие коллеги по системным работам,

друг-администратор задал мне следующий вопрос:

На ряде сетевых элементов и серверов он использует удаленную аутентификацию на сервере TACACS +. На некоторых таких проприетарных устройствах аутентификация запрашивает локальную базу данных аутентификации только в том случае, если удаленный метод возвращает «сервер аутентификации недоступен» (недоступен, истекло время ожидания). Если удаленный сервер аутентификации доступен и возвращает отрицательный ответ, рассматриваемый ящик принимает это за чистую монету и не пытается выполнить аутентификацию в локальной базе данных пользователей.

Теперь ... Коробка на базе Linux, он хотел бы добиться такого же поведения. А он, похоже, не может. ОС Linux сначала пытается выполнить удаленную аутентификацию, но при явном отрицательном ответе (сервер отвечает «ошибка аутентификации, это недействительные учетные данные») она продолжает и просто пытается также локальную базу данных.

Я понял, что удаленный TACACS + auth организован красивым модулем PAM, называемым pam_tacplus. Читая о PAM в целом, я, кажется, понял, что pam_tacplus не виноват. Скорее наблюдаемое поведение - это просто способ работы PAM в целом. В этом случае прямое решение, вероятно, должно будет включать добавление настраиваемой глобальной опции в базу кода PAM и, возможно, определенных ключевых слов / синтаксиса файла конфигурации PAM, чтобы изменить поведение в желаемом направлении.

Любые дальнейшие примечания по приветствуются в этой теме: -)

0
задан 4 December 2020 в 21:33
1 ответ

... исходя из дальнейшего чтения, позвольте мне предложить ответ. Любые дополнения или исправления приветствуются.

Во-первых, я нашел это старое введение в PAM. Вероятно, за эти годы он не потерял ни капли остроты своего ума.

Если я загляну внутрь, то узнаю, что возвращаемые значения модуля auth задокументированы в официальной документации linux-pam.

В списке я вижу многообещающий retval под названием PAM_AUTHINFO_UNAVAIL.

Фактически определено в libpam/include/security/_pam_types.h .

#define PAM_SUCCESS 0
#define PAM_AUTHINFO_UNAVAIL 9
#define _PAM_RETURN_VALUES 32 

По-видимому, существует конфликтующее определение PAM_AUTHINFO_UNAVAIL в libpam/include/security/_pam_compat.h

# define PAM_AUTHINFO_UNAVAIL     12

— вероятно, его можно игнорировать.

Исходный файл libpam/pam_dispatch.c содержит ключевую функцию с именем _pam_dispatch_aux(), который фактически проходит по стеку зарегистрированных модулей аутентификации и действует в соответствии с их возвращаемыми значениями. И, оказывается, на основе "ретваля" напрямую он мало что делает, возможно, содержит PAM_AUTHINFO_UNAVAIL. Он напрямую реагирует на некоторые конкретные значения «внутреннего специального использования» retval, но не имеет специальной обработки для PAM_AUTHINFO_UNAVAIL. retval не является возвращаемым значением самого _pam_dispatch_aux(): скорее retval — это просто локальная переменная, объявленная внутри цикла for(;;), которая проходит стек зарегистрированных модулей аутентификации, где локальный блок retval собирает возвращаемое значение конкретного модуля. Цикл обхода стека на самом деле принимает важные решения на основе других переменных: одна из них является производной, называемой action, а другая является членом структуры, называемой impression, «возвращаемой» модулями по ссылке. .Так может на это все-таки повлиял собственный код модуля?

На самом деле получается, что действие берется из "справочной таблицы действий", проиндексировано the retval - ага!

action = h->actions[cached_retval];

Таблица действий определяется модулем? Но как, если макросы _PAM_ACTION_* определены в libpam/pam_private.h ?

Получается, что таблица action[] инициализирована универсальным образом функция с именем _pam_parse_conf_file() в libpam/pam_handlers.c, который выполняет прямое сравнение строк (сопоставление) по ключевым словам, таким как обязательно,обязательно,необязательно,достаточно.

И вся таблица в настоящее время имеет 32 позиции (см. приведенное выше определение макроса), которые оптом инициализируются в _PAM_ACTION_UNDEF перед синтаксическим анализом записи конфигурации для конкретного модуля. Затем отдельные «ключевые слова силы» переназначают отдельные retval на конкретные желаемые действия.

Итак: кажется довольно очевидным, например, вдохновитесь этим:

} else if (!strcasecmp("required", tok)) {
    D(("*PAM_F_REQUIRED*"));
    actions[PAM_SUCCESS] = _PAM_ACTION_OK;
    actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;
    actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
    _pam_set_default_control(actions, _PAM_ACTION_BAD);
} else if (!strcasecmp("sufficient", tok)) {
    D(("*PAM_F_SUFFICIENT*"));
    actions[PAM_SUCCESS] = _PAM_ACTION_DONE;
    actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_DONE;
    _pam_set_default_control(actions, _PAM_ACTION_IGNORE);
}

и добавьте что-то вроде

} else if (!strcasecmp("reqd_if_avail", tok)) {
    D(("*PAM_F_REQD_IF_AVAIL*"));
    actions[PAM_SUCCESS] = _PAM_ACTION_OK;
    actions[PAM_AUTHINFO_UNAVAIL] = _PAM_ACTION_IGNORE; // !!!!!!!!!!
    actions[PAM_NEW_AUTHTOK_REQD] = _PAM_ACTION_OK;     // ?
    actions[PAM_IGNORE] = _PAM_ACTION_IGNORE;
    _pam_set_default_control(actions, _PAM_ACTION_BAD); // !!!
}

И, видимо, pam_tacplus помогает нам на этом пути.

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

0
ответ дан 5 December 2020 в 06:59

Теги

Похожие вопросы