2009-07-22 3 views
2

В настоящее время у меня есть графическое приложение с двумя уровнями доступа, оператором и администратором. Логин и аутентификация все доморощенные, и я хотел бы переключить приложение на использование PAM. Я не уверен, как правильно это сделать.Различные уровни доступа с PAM

Исправьте меня, если я ошибаюсь, но кажется, что PAM сводится к проверке «да» или «нет» - да, вы можете получить доступ к этой службе, или нет, вы не можете. Нет никакого положения о том, чтобы иметь различные уровни доступа, основанные на том, какой пользователь входит в систему. Мне нужно знать, кто является оператором и кто является администратором, и я хочу, чтобы это было возможно строго через PAM, если это было возможно.

Так что моя мысль в том, что я создана две службы с двумя различными конфигурациями, /etc/pam.d/pamdemo для операторов и /etc/pam.d/pamdemo-admin для администраторов. Затем мое приложение попытается выполнить аутентификацию с pamdemo-admin, а если это произойдет, то pamdemo. Если оба отказались, доступ запрещен. Я нахожусь на правильном пути, или я полностью покинул рельсы?

Вот пример кода C, который я написал как доказательство концепции. Когда я делаю логин, я не хочу дважды запрашивать у пользователя его учетные данные. У меня есть так, что он запоминает имя пользователя в двух вызовах pam_start(), но я не могу получить доступ к pam_get_item(PAM_AUTHTOK) с уровня приложения, чтобы выполнить такое же кэширование для пароля. И это было в попытке сделать так, чтобы я понял, что может быть совершенно другой способ сделать это. Я хотел бы, чтобы это приложение работало независимо от того, какой метод аутентификации, будь то имя пользователя/пароль или билеты Kerberos или отпечатки пальцев, что угодно.

pam_handle_t *try_login(const char *service, int *retval) 
{ 
    static char * username = NULL; 
    struct pam_conv pam_conversation = { conv, NULL }; 
    pam_handle_t * pamh; 

    *retval = pam_start(service, username, &pam_conversation, &pamh); 

    if (*retval == PAM_SUCCESS) *retval = pam_authenticate(pamh, 0); 
    if (*retval == PAM_SUCCESS) *retval = pam_acct_mgmt (pamh, 0); 
    if (*retval == PAM_SUCCESS) *retval = pam_open_session(pamh, 0); 

    if (username == NULL) { 
     if (pam_get_item(pamh, PAM_USER, (const void **) &username) == PAM_SUCCESS) { 
      username = strdup(username); 
     } 
    } 

    if (*retval != PAM_SUCCESS) { 
     fprintf(stderr, "%s: %s\n", service, pam_strerror(pamh, *retval)); 
     pam_end(pamh, *retval); 
     pamh = NULL; 
    } 

    return pamh; 
} 

int main(void) 
{ 
    pam_handle_t *pamh = NULL; 
    int retval; 
    const char *service, *username; 

    if (!pamh) pamh = try_login("pamdemo-admin", &retval); 
    if (!pamh) pamh = try_login("pamdemo",  &retval); 

    if (!pamh) { 
     fprintf(stderr, "Access denied.\n"); 
     return 1; 
    } 

    pam_get_item(pamh, PAM_SERVICE, (const void **) &service); 
    pam_get_item(pamh, PAM_USER, (const void **) &username); 

    printf("Logged into %s as %s.\n", service, username); 

    pam_close_session(pamh, 0); 
    pam_end   (pamh, retval); 

    return 0; 
} 

Как написано, эта демонстрационная программа повторяет запрос «password:». Я не хочу, чтобы он дважды спрашивал!

ответ

2

Я считаю, что один правильный способ сделать это может быть:

  • Настройка службы «pamdemo», чтобы сделать счета, проверки подлинности и сеансового функции.
  • Настройте услугу «pamdemo-admin» до только выполните учетную запись (и, возможно, сессию). Нет аутентификации.
  • При входе в систему сначала попросите их пройти «pamdemo» (чтобы убедиться, что они такие, кем они говорят, что они есть) - если это не удастся, выпустите их.
  • Затем, после аутентификации, передайте их «pamdemo-admin». Это просто проверяет, разрешено ли им быть администратором - если это так, эта проверка завершается успешно, а если нет, это не так. Поскольку эта проверка не выполняет авторизационные модули, они не запрашивают пароль еще раз.
1

За предложение CAF, вот мое решение:

#define PAM_CALL(call)        \ 
    do {            \ 
     if ((retval = (call)) != PAM_SUCCESS) {  \ 
      goto pam_error;       \ 
     }           \ 
    } while (0) 

int check_admin_login(const char *user) 
{ 
    pam_handle_t * pamh = NULL; 
    struct pam_conv pam_conversation = { conv, NULL }; 
    int    retval; 

    PAM_CALL(pam_start ("pamdemo-admin", user, &pam_conversation, &pamh)); 
    PAM_CALL(pam_acct_mgmt(pamh, 0)); 
    PAM_CALL(pam_end  (pamh, retval)); 

    return 1; 

pam_error: 
    pam_end(pamh, retval); 
    return 0; 
} 

int main(void) 
{ 
    pam_handle_t * pamh = NULL; 
    struct pam_conv pam_conversation = { conv, NULL }; 
    int    retval; 

    const char * user; 
    int    is_admin; 

    PAM_CALL(pam_start  ("pamdemo", NULL, &pam_conversation, &pamh)); 
    PAM_CALL(pam_authenticate (pamh, 0)); 
    PAM_CALL(pam_acct_mgmt (pamh, 0)); 
    PAM_CALL(pam_open_session (pamh, 0)); 
    PAM_CALL(pam_get_item  (pamh, PAM_USER, (const void **) &user)); 

    is_admin = check_admin_login(user); 
    printf("Logged in as %s (%s).\n", user, is_admin ? "administrator" : "operator"); 

    PAM_CALL(pam_close_session(pamh, 0)); 
    pam_end (pamh, retval); 

    return 0; 

pam_error: 
    fprintf(stderr, "%s\n", pam_strerror(pamh, retval)); 
    pam_end(pamh, retval); 

    return 1; 
} 
0

вы можете просто использовать команду «группы» или «ID» и получить группы для пользователя, а затем Grep группы и если вы сначала нажмите «admin», затем пользователь admin, иначе это демонстрационный пользователь.

группирует/команды ID (проверено на Linux) получат группы для неместных пользователей, а также (например, PAM/LDAP)

Так, вместо проверки на службу, проверьте группу, в которой пользователь принадлежит.

Смежные вопросы