Linux의 PAM: 원격/외부 인증 DB가 부정적인 응답을 반환하는 경우 로컬 인증을 건너뛸 수 있는 방법이 있습니까?

Linux의 PAM: 원격/외부 인증 DB가 부정적인 응답을 반환하는 경우 로컬 인증을 건너뛸 수 있는 방법이 있습니까?

친애하는 시스템 전문가 여러분,

관리자 친구가 나에게 다음과 같은 질문을 했습니다.

그는 여러 네트워크 요소와 서버에서 TACACS+ 서버에 대한 원격 인증을 사용하고 있습니다. 일부 독점 어플라이언스에서는 원격 메서드가 "인증 서버를 사용할 수 없음"(접근할 수 없음, 시간 초과)을 반환하는 경우에만 인증이 로컬 인증 DB에 묻습니다. 원격 인증 서버인 경우~이다사용 가능하고 부정적인 응답을 반환하는 경우 문제의 상자는 이를 액면 그대로 받아들이고 로컬 사용자 데이터베이스에 대해 인증을 시도하지 않습니다.

이제... Linux 기반 상자에서 그는 동일한 동작을 달성하고 싶습니다. 그리고 그는 그렇게 할 수 없을 것 같습니다. Linux OS는 먼저 원격 인증을 시도하지만 명백히 부정적인 응답(서버가 "인증 실패, 유효한 자격 증명이 아닙니다"라고 응답)이 나타나면 계속해서 로컬 데이터베이스도 시도합니다.

나는 원격 TACACS+ 인증이 pam_tacplus라는 멋진 PAM 모듈에 의해 정렬된다는 것을 이해하게 되었습니다. 일반적으로 PAM에 대해 읽으면서 pam_tacplus가 책임이 없다는 생각이 들었습니다. 오히려 관찰된 동작은 PAM 전체가 작동하는 방식입니다. 그렇다면 직접적인 해결책은 PAM 코드베이스에 구성 가능한 전역 옵션을 추가하고 특정 PAM 구성 파일 키워드/구문을 추가하여 원하는 방향으로 동작을 수정해야 할 것입니다.

이 주제에 대한 추가 메모를 환영합니다 :-)

답변1

...추가 내용을 토대로 답변을 제안하겠습니다. 어떤 추가나 수정이라도 명백하고 따뜻하게 환영합니다.

우선 나는 이것이 오래되었다는 것을 알았습니다.PAM 소개. 아마도 지난 몇 년 동안 날카로운 재치를 잃지 않았을 것입니다.

내부를 살펴보면 인증 모듈 반환 값은 다음과 같습니다.공식 linux-pam 문서에 문서화되어 있습니다..

목록에서 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(;;) 루프 내부에 선언된 로컬 변수일 뿐입니다. 여기서 블록 로컬은 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로 설정하세요. 개별 "강점 키워드"는 개별 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 구성 파일 구문을 사용하여 동일한 효과를 얻을 수 있다면 확실히 좋을 것입니다.

관련 정보