제공된 사용자 이름을 추가하여 ssh를 통해 호출되는 프로세스에 데이터를 가져오려고 합니다.
ssh user@smuggledata@host
나는 PAM 모듈을 작성했지만
- sshd는 PAM을 호출하기 전에 사용자가 나쁜 사용자임을 확인했습니다.
- PAM_USER를 변경했지만 후속 모듈은 여전히 제출된 사용자 이름을 기반으로 인증합니다.
auth requisite mymodule.so
먼저 및 의 코드를 사용하여 코드를 실행 해 보았습니다 pam_sm_authenticate()
. 코드가 트리거되었지만 작동하지 않습니다.
May 1 22:40:30 animal sshd[3827]: Invalid user colin@example from 127.0.0.1
May 1 22:40:30 animal sshd[3827]: input_userauth_request: invalid user colin@example [preauth]
May 1 22:40:35 animal pam_pat[3827]: Retrieved username colin@example
May 1 22:40:35 animal pam_pat[3827]: checking char c against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char o against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char l against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char i against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char n against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char @ against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: Found divider @
May 1 22:40:35 animal pam_pat[3827]: user=colin, data=example
May 1 22:40:35 animal sshd[3827]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=127.0.0.1 user=colin
May 1 22:40:37 animal sshd[3827]: Failed password for invalid user colin@example from 127.0.0.1 port 43998 ssh2
May 1 22:41:28 animal sshd[3827]: Connection closed by 127.0.0.1 port 43998 [preauth]
실행이 pam_unix에 도달하면 인증이 실패하지만 사용자는 PAM_USER에 변환된 값으로 보고됩니다. 비밀번호가 정확하므로 pam_unix가 PAM_USER에 대해 인증하지 않을 수 있습니다.
account requisite mymodule.so
또한 코드를 시도했지만 pam_sm_acct_mgmt()
코드가 호출되지 않았습니다.
May 1 22:57:10 animal sshd[4105]: Invalid user colin@exmple from 127.0.0.1
May 1 22:57:10 animal sshd[4105]: input_userauth_request: invalid user colin@exmple [preauth]
May 1 22:57:16 animal sshd[4105]: pam_unix(sshd:auth): check pass; user unknown
May 1 22:57:16 animal sshd[4105]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=127.0.0.1
May 1 22:57:18 animal sshd[4105]: Failed password for invalid user colin@exmple from 127.0.0.1 port 44118 ssh2
May 1 22:57:27 animal sshd[4105]: Connection closed by 127.0.0.1 port 44118 [preauth]
보고 있다pam_unix의 소스 코드검색된 사용자 이름은 pam_get_user()
분명히 PAM_USER가 아닌 다른 이름을 가리킵니다.
이후에 인증에 사용되는 사용자 값을 어떻게 변경합니까?
- 사용자 이름을 다른 방식으로 처리하기 전에 이런 일이 발생하는지 어떻게 확인할 수 있나요?
- pam_get_user()가 반환한 포인터를 다시 쓰는 것보다 더 좋은 방법이 있습니까?
고쳐 쓰다 코드(pam_get_user() 추가됨):
char *submitted_name;
char work_bufr[PAT_BUFR];
char log_entry[PAT_BUFR];
int an_int;
char dividers[]="@%+";
int num_dividers;
char *cursor;
char divider_found[]="0";
const char *debug_user;
openlog("pam_pat", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_AUTH);
/* retrieve a copy of the submitted username */
if (PAM_SUCCESS != pam_get_item(pamh, PAM_USER, (void *) &submitted_name) || !(submitted_name)) {
syslog (LOG_ERR, "Failed to retrieve username from pam");
closelog();
return(PAM_IGNORE);
}
syslog (LOG_ERR, "Retrieved username %s", submitted_name);
strncpy(work_bufr, submitted_name, PAT_BUFR);
submitted_name=work_bufr;
/* search for dividers and split string */
cursor=submitted_name;
an_int=PAT_BUFR;
num_dividers=(int)strlen(dividers);
while (--an_int && '\0'!=*cursor) {
syslog(LOG_ERR, "checking char %c against %d dividers", (int)*cursor, num_dividers);
for (int x=0; x<num_dividers; x++) {
if (*cursor==dividers[x]) {
syslog(LOG_ERR, "Found divider %c", *cursor);
an_int=0;
*divider_found=*cursor;
*cursor='\0';
if (PAM_SUCCESS==pam_set_item(pamh, PAM_USER, submitted_name)) {
++cursor;
syslog (LOG_ERR, "user=%s, data=%s",submitted_name,cursor);
setenv("PAM_PAT_DIVDR", divider_found, 1);
setenv("PAM_PAT_DATA", cursor, 1);
if (PAM_SUCCESS == pam_get_user(pamh, &debug_user, NULL)) {
syslog (LOG_ERR, "pam_get_user() found %s", debug_user);
}
closelog();
return(PAM_IGNORE);
} else {
syslog (LOG_ERR, "Failed to update username");
}
}
}
cursor++;
}
syslog (LOG_ERR, "Extended username not found.");
closelog();
return(PAM_IGNORE);
}
답변1
input_userauth_request()는 사용자 이름을 묻는 sshd의 함수입니다.
다음에 대해 앞뒤로 읽으십시오.pam_ldap(로컬 시스템은 인증되는 사용자 이름을 반드시 알 수는 없습니다.) LDAP NSS 라이브러리가 설치 또는 구성되지 않은 경우 "sshd[xxx]: input_userauth_request: 잘못된 사용자 ..." 메시지가 나타납니다. 이것으로부터 나는 sshd가 PAM(WTF?)에 넘겨주기 전에 먼저 사용자 이름을 확인하려고 시도한다고 추론합니다. 따라서 이 초기 오류를 방지하려면 NSS 모듈을 작성해야 합니다(아마도 getpwnam()을 구현하지만 작동 방식을 알아보려면 sshd를 분리해야 할 것으로 예상됩니다).
잘!
(아직도 이것이 문제를 해결할 수 있을지 확신하지 못합니다)
답변2
오래된 스레드이지만 완전한 답변을 정리하고 싶었습니다.
나도 비슷한 요구 사항이 있었고 여기에 언급된 내용을 거의 사용하여 솔루션을 함께 엮었습니다.
libnss-ato
- 존재하지 않는 사용자를 계속 허용하기 위해 필요합니다. (이전에도 이 방법을 사용한 적이 있습니다.)PAM_SUCCESS
다음을 제외하고 간단한 PAM 모듈(주로 반환된 가상 함수)을 만들었습니다 .
static char*
_find_base_user (const char *user)
{
char *p = NULL;
static char user_base[64] = {0};
if ((p = strchr(user, '@'))) {
memset(user_base, 0, 64);
strncpy(user_base, user, (int)(p - user));
return user_base;
}
return NULL;
}
int
pam_sm_authenticate (pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int ret = 0;
const char *user;
char *user_pfx = NULL;
ret = pam_get_user(pamh, &user, NULL);
if (ret != PAM_SUCCESS || user == NULL) {
pam_syslog(pamh, LOG_ERR, "no user specified");
} else {
pam_syslog(pamh, LOG_DEBUG, "user = %s", user);
}
user_pfx = _find_base_user(user);
if (user_pfx) {
pam_syslog(pamh, LOG_DEBUG, "user base name: %s", user_pfx);
} else {
pam_syslog(pamh, LOG_ERR, "no separator in user name found");
return PAM_SUCCESS;
}
ret = pam_set_item(pamh, PAM_USER, (const void *)user_pfx);
if (ret!= PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR, "user resetting failed");
return PAM_USER_UNKNOWN;
}
return PAM_SUCCESS;
}
이것을 호출 pam_changeuser.so
하고 이제 PAM 스택(첫 번째 모듈)의 맨 위에 추가합니다.
auth required pam_changeuser.so
이것으로 나는 할 수 있다밀수일부추가 자료사용자 이름으로!
이것이 누군가에게 도움이 되기를 바랍니다.
--
답변3
의 매뉴얼 페이지에는 pam_get_user(3)
사용자로부터 값을 얻는다고 나와 있습니다 pam_start(3)
. 이 함수는 해당 구조의 요소를 설정하는 데 사용될 수 있습니다 pam_set_item(3)
. 세 번째 기능에 대한 매뉴얼 페이지는 인증이 테스트되는 사용자 이름을 변경하기 위한 명확한 참조를 제공합니다.
이
pam_set_item
기능을 사용하면 애플리케이션과 PAM 서비스 모듈이 에 액세스하고 업데이트할 수 있습니다item_type
. 이를 수행하려면 항목 매개변수가 가리키는 개체의 복사본을 만듭니다. 다음 item_types이 지원됩니다 [...]PAM_user ID 서비스를 제공할 엔터티의 사용자 이름입니다. 즉, 인증 후 PAM_USER는 서비스 사용을 시작하는 로컬 엔터티를 식별합니다. 이 값은 PAM 스택의 모든 모듈에 의해 무언가(예: "anonymous")에서 다른 값(예: "guest119")으로 매핑될 수 있습니다. 따라서 애플리케이션은 PAM 함수를 호출할 때마다 PAM_USER 값을 참조해야 합니다.