В настоящее время у меня есть графическое приложение с двумя уровнями доступа, оператором и администратором. Логин и аутентификация все доморощенные, и я хотел бы переключить приложение на использование 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:». Я не хочу, чтобы он дважды спрашивал!