首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用PAM的不同访问级别

问使用PAM的不同访问级别
EN

Stack Overflow用户
提问于 2009-07-22 22:03:52
回答 3查看 799关注 0票数 2

目前,我有一个图形应用程序,有两个级别的访问,操作员和管理员。登录和身份验证都是自制的,我希望将应用程序改为使用PAM。我不知道该怎么做才是对的。

如果我错了,请纠正我,但PAM似乎可以归结为“是”或“否”检查--是的,您可以访问该服务,或者不能访问。没有关于拥有不同级别的访问权限的规定。不过,我需要能够分辨出谁是操作员,谁是管理员,如果可能的话,我希望能够通过PAM严格地做到这一点。

因此,我的想法是设置两个服务,具有两种不同的配置--、用于操作员的/etc/pam.d/pamdemo和用于管理员的/etc/pam.d/pamdemo-admin。然后,我的应用程序将尝试首先对pamdemo-admin进行身份验证,如果这一方法失败,则pamdemo。如果两者都失败,则拒绝访问。我是在正确的轨道上还是我完全偏离轨道了?

下面是我编写的一些示例C代码,作为概念的证明。当我登录时,我不想两次提示用户提供他的凭据。我得到了它,所以它会记住两个pam_start()调用的用户名,但是我不能从应用程序级别访问pam_get_item(PAM_AUTHTOK)来对密码执行相同的缓存。在尝试这样做的过程中,我意识到可能有一种完全不同的方法来做到这一点。我希望这个应用程序能够工作,不管是什么身份验证方法,不管是用户名/密码,还是Kerberos票证或指纹等等。

代码语言:javascript
复制
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;
}

正如所写的,这个演示程序重复了“密码:”提示。我不想让它问两次!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-07-23 04:58:43

我相信一个正确的方法可能是:

  • 设置了用于帐户、身份验证和会话功能的"pamdemo“服务,
  • 则将”admin“服务设置为只执行帐户(可能还包括会话)功能。没有authentication.
  • When登录,首先让他们通过"pamdemo“(以确保他们说自己是谁)--如果失败了,就把他们踢出去。
  • ,一旦经过认证,就把他们交给”pamdemo“。这只是检查它们是否允许管理--如果允许,则此检查成功,如果不允许,则不会。因为此检查不执行所有模块,因此不会再次提示它们输入密码。
票数 2
EN

Stack Overflow用户

发布于 2009-07-23 17:51:04

根据咖啡馆的建议,这是我的解决方案:

代码语言:javascript
复制
#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;
}
票数 1
EN

Stack Overflow用户

发布于 2011-03-17 17:34:15

您只需使用命令“group”或"id“,然后为用户获取组,然后是grep组,如果您首先点击admin,那么它就是管理用户,否则它就是一个演示用户。

groups / id命令(在Linux上测试)也将为非本地用户获取组(例如PAM / LDAP)。

因此,不要对服务进行检查,而是检查用户所属的组。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1168552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档