目前我有一个图形应用程序,它有两个访问级别,操作员和管理员。登录和身份验证都是自制的,我想将应用程序切换为使用 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;
}
正如所写的那样,这个演示程序重复“密码:”提示。我不希望它问两次!