I am trying to authenticate a user on MacOS using PAM with the following code:
#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;
}
The compile and run commands on MacOS are:
clang pamtest.c -lpam
sudo ./a.out
However when the code is run on MacOS the output is:
Calling pam_start()…
Calling pam_authenticate()…
pam_authenticate() returned 9 (authentication error)
No attempt is made to by pam to call PamCallbackFn() to supply the password.
If the same code is compiled and run on Ubuntu, authentication is successful and I get the following output:
Calling pam_start()…
Calling pam_authenticate()…
PamCallbackFn num_msg=1
Prompt type 1 for 'Password: '
Calling pam_acct_mgmt()…
Success !
The user account fhtest exists on both MacOS and Ubuntu. I can login manually using this account to both computers.
There is no specific pam service file for "test" in /etc/pam.d
(first argument to the pam_start
call). In this case pam should fall back to using /etc/pam.conf
. The file /etc/pam.conf
exists on the Ubuntu computer, but consists only of comments. The file /etc/pam.conf
does not exist on the MacOS computer. Creating the file /etc/pam/conf
on the MacOS computer similar to the one on the Ubuntu computer does not fix the problem.
What I am looking for is a working example of how to authenticate a user with a UserName and Password on MacOS. The solution should be usable from a background service or daemon.
PAM is an interface for authentication tasks and it does not make the authentication by itself (for example it can delegate the authentication to a remote Kerberos or LDAP server, or to a local login system).
The configuration must be done at system level in /etc/pam.d
or /etc/pam.conf
. You should verify if your configuration is correct. For example, as your service name is "test", you probably need a file /etc/pam.d/test
.
Or you can try to chose another service name in the pam_start()
call. For example "login"
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With