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

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

Дорогие коллеги-системные умельцы!

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

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

Теперь... на Linux-компьютере он хотел бы добиться того же поведения. И, похоже, не может. Linux OS сначала пытается удаленную аутентификацию, но после четкого отрицательного ответа (сервер отвечает "сбой аутентификации, это недействительные учетные данные") она продолжает и просто пробует локальную базу данных.

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

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

решение1

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

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

Если заглянуть под капот, то возвращаемые значения модуля аутентификации будут следующими:задокументировано в официальной документации 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()который на самом деле проходит по стеку зарегистрированных модулей аутентификации и действует на основе их возвращаемых значений. И, оказывается, что он не делает многого, основываясь на "retval" напрямую, возможно, содержащем PAM_AUTHINFO_UNAVAIL. Он действительно реагирует напрямую на некоторые конкретные значения "внутреннего специального использования" retval, но не имеет специальной обработки для PAM_AUTHINFO_UNAVAIL. retvalне является возвращаемым значением _pam_dispatch_aux()самого себя: скорее, retvalэто просто локальная переменная, объявленная внутри цикла for(;;), который проходит по стеку зарегистрированных модулей аутентификации, где block-local retvalсобирает возвращаемое значение конкретного модуля. Цикл обхода стека на самом деле принимает важные решения, основываясь на других переменных: одна из них производная, называется action, а другая является членом структуры, называемым impression"возвращаемым" модулями по ссылке. Так что, возможно, на него все-таки может повлиять собственный код модуля?

На самом деле оказывается, что это actionвзято из «таблицы соответствия действий», индексируется- ага retval!

action = h->actions[cached_retval];

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

Оказывается, таблица actions[] — этоинициализировано общим способомфункцией, вызываемой _pam_parse_conf_file()в libpam/pam_handlers.c, которая выполняетпрямое сравнение строк(сопоставление) по ключевым словам, таким как required, requisite, optional, sufficient.

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

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

} 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, без необходимости взлома исходного кода.

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