사용자 정의 pam 모듈을 사용하여 사용자 이름의 데이터를 밀수할 수 없습니다. - input_userauth_request: 잘못된 사용자

사용자 정의 pam 모듈을 사용하여 사용자 이름의 데이터를 밀수할 수 없습니다. - input_userauth_request: 잘못된 사용자

제공된 사용자 이름을 추가하여 ssh를 통해 호출되는 프로세스에 데이터를 가져오려고 합니다.

ssh user@smuggledata@host

나는 PAM 모듈을 작성했지만

  1. sshd는 PAM을 호출하기 전에 사용자가 나쁜 사용자임을 확인했습니다.
  2. 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

오래된 스레드이지만 완전한 답변을 정리하고 싶었습니다.

나도 비슷한 요구 사항이 있었고 여기에 언급된 내용을 거의 사용하여 솔루션을 함께 엮었습니다.

  1. libnss-ato- 존재하지 않는 사용자를 계속 허용하기 위해 필요합니다. (이전에도 이 방법을 사용한 적이 있습니다.)

  2. 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 값을 참조해야 합니다.

관련 정보