PAM是在MacOS上验证用户身份的合适方法吗

PAM是在MacOS上验证用户身份的合适方法吗,macos,pam,Macos,Pam,我正在尝试使用PAM对MacOS上的用户进行身份验证,代码如下: #include <security/pam_appl.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> static int PamCallbackFn( int num_msg,

我正在尝试使用PAM对MacOS上的用户进行身份验证,代码如下:

#include <security/pam_appl.h>

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

static int PamCallbackFn( int num_msg,
            const struct pam_message **msg,
            struct pam_response **resp,
            void *appdata_ptr )
{
    printf("PamCallbackFn num_msg=%d:\n", num_msg );
    for ( int idx = 0; idx < num_msg; ++ idx )
    {
        printf(
            "\tPrompt type %d for '%s'\n", 
            msg[idx]->msg_style,
            msg[idx]->msg );
    }

    assert( num_msg == 1 );
    struct pam_response *response = 
        (struct pam_response *)malloc( sizeof( struct pam_response ) );
    response->resp = strdup( "fhtest" );
    response->resp_retcode = 0;

    *resp = response;
    return PAM_SUCCESS;
}

int main( int argc, char **argv )
{
    struct pam_conv Callback;
    Callback.conv = PamCallbackFn;
    Callback.appdata_ptr = 0;

    printf("Calling pam_start()...\n");

    pam_handle_t *AuthHandle = 0;
    int Result = 
        pam_start(
            "test",     // Client program name
            "fhtest",   // User name
            &Callback,
            &AuthHandle );
    if ( Result != PAM_SUCCESS )
    {
        printf(
            "pam_start() returned %d (%s)\n",
            Result,
            pam_strerror( AuthHandle, Result ) );
        return EXIT_FAILURE;
    }

    printf("Calling pam_authenticate()...\n");
    Result = pam_authenticate( AuthHandle, PAM_SILENT );
    if ( Result != PAM_SUCCESS )
    {
        printf(
            "pam_authenticate() returned %d (%s)\n",
            Result,
            pam_strerror( AuthHandle, Result ) );
        return EXIT_FAILURE;
    }

    printf("Calling pam_acct_mgmt()...\n");
    Result = pam_acct_mgmt( AuthHandle, 0 );
    if ( Result != PAM_SUCCESS )
    {
        printf(
            "pam_acct_mgmt() returned %d (%s)\n",
            Result,
            pam_strerror( AuthHandle, Result ) );
        return EXIT_FAILURE;
    }

    printf("Success !\n");
    pam_end( AuthHandle, Result );
    return EXIT_SUCCESS;
}
但是,在MacOS上运行代码时,输出为:

Calling pam_start()…
Calling pam_authenticate()…
pam_authenticate() returned 9 (authentication error)
pam没有试图调用PamCallbackFn()来提供密码

如果在Ubuntu上编译并运行相同的代码,则身份验证成功,我得到以下输出:

Calling pam_start()…
Calling pam_authenticate()…
PamCallbackFn num_msg=1
    Prompt type 1 for 'Password: '
Calling pam_acct_mgmt()…
Success !
用户帐户fhtest存在于MacOSUbuntu上。我可以使用此帐户手动登录两台计算机

/etc/pam.d
中没有用于“test”的特定pam服务文件(调用
pam\u start
的第一个参数)。在这种情况下,pam应该退回到使用
/etc/pam.conf
。Ubuntu计算机上存在文件
/etc/pam.conf
,但只包含注释。MacOS计算机上不存在文件
/etc/pam.conf
。在MacOS计算机上创建与Ubuntu计算机上类似的文件
/etc/pam/conf
,并不能解决问题


我要找的是一个如何在MacOS上使用用户名和密码验证用户身份的工作示例。该解决方案应该可以从后台服务或后台程序使用。

PAM是身份验证任务的接口,它本身不进行身份验证(例如,它可以将身份验证委托给远程Kerberos或LDAP服务器,或委托给本地登录系统)

必须在
/etc/pam.d
/etc/pam.conf
中的系统级完成配置。您应该验证您的配置是否正确。例如,由于您的服务名为“test”,您可能需要一个文件
/etc/pam.d/test


或者您可以尝试在
pam\u start()
调用中选择另一个服务名称。例如,
“login”

在这种情况下,一种可能是使用调试器并单步执行pam_uu.函数,这样您就可以看到库所做的决定。另一个是看PAM库的源代码,我快速地看了一下applepam_modules的源代码(),但没有什么明显的突出之处。但是,这给了我一些进一步研究的建议。PAM是身份验证任务的接口,它本身不进行身份验证(例如,它可以将身份验证委托给远程Kerberos或LDAP服务器,或者委托给本地登录系统)。系统级别的配置决定了必须如何对每个服务进行身份验证。您的服务“测试”可能在MacOS系统上配置错误。@user8034222-谢谢您的评论。我得到一个事实,PAM是身份验证系统的接口。MacOS安装是一个干净的安装,自安装以来,PAM堆栈一直没有更改。我有理由相信我们可以排除配置错误的PAM堆栈。您能解释一下“系统级别的配置决定每个服务必须如何进行身份验证”是什么意思吗?例如,在我的系统上,我有配置文件/etc/pam.d/(服务是cups、ppp等),这些文件指示pam应该如何重定向每个服务的身份验证。
Calling pam_start()…
Calling pam_authenticate()…
PamCallbackFn num_msg=1
    Prompt type 1 for 'Password: '
Calling pam_acct_mgmt()…
Success !