目前,我有一个图形应用程序,具有两个访问级别,即运算符(operator)和管理员。登录名和身份验证都是自制的,我想将应用程序切换为使用PAM。我不确定这样做的正确方法是什么。

如果我错了,请纠正我,但是PAM似乎可以归结为"is"或“否”检查-是的,您可以访问此服务,否则不能。没有根据登录用户的级别来进行不同级别的访问的权限。但是,我需要能够分辨出谁是运算符(operator),谁是管理员,并且我希望能够通过PAM严格做到这一点。

所以我的想法是,我将使用两种不同的配置,运算符(operator)的/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:”提示。我不想问两次!

最佳答案

我相信这样做的正确方法可能是:

  • 设置“pamdemo”服务以执行帐户,身份验证和 session 功能。
  • 设置“pamdemo-admin”服务以仅执行帐户(可能还有 session )功能。没有身份验证。
  • 登录时,首先让他们通过“pamdemo”(以确保他们是他们所说的人)-如果失败,将他们赶出去。
  • 然后,通过身份验证后,将其交给“pamdemo-admin”。这只是检查是否允许他们成为管理员-如果允许,则此检查成功,如果不允许,则不成功。由于此检查不执行身份验证模块,因此不会再次提示他们输入密码。
  • 07-24 09:51