Last active
April 22, 2024 08:03
-
-
Save rmohr/a131ae3b095095aff134 to your computer and use it in GitHub Desktop.
Absolutely minimalistic pam authentication example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <assert.h> | |
#include <string.h> | |
#include <unistd.h> /* getpass */ | |
#include <security/pam_appl.h> /* pam_start, pam_conv, pam_end, ... */ | |
#define TRY(x) ret = (x); printf("PAM: %s\n", pam_strerror(handle, ret)); if (ret != PAM_SUCCESS) goto finally | |
int test_conv(int num_msg, const struct pam_message **msg, | |
struct pam_response **resp, void *appdata_ptr){ | |
const struct pam_message* msg_ptr = *msg; | |
struct pam_response * resp_ptr = NULL; | |
int x = 0; | |
*resp = calloc(sizeof(struct pam_response), num_msg); | |
for (x = 0; x < num_msg; x++, msg_ptr++){ | |
char* resp_str; | |
switch (msg_ptr->msg_style){ | |
case PAM_PROMPT_ECHO_OFF: | |
case PAM_PROMPT_ECHO_ON: | |
resp_str = getpass(msg_ptr->msg); | |
resp[x]->resp= strdup(resp_str); | |
break; | |
case PAM_ERROR_MSG: | |
case PAM_TEXT_INFO: | |
printf("PAM: %s\n", msg_ptr->msg); | |
break; | |
default: | |
assert(0); | |
} | |
} | |
return PAM_SUCCESS; | |
} | |
int main(int argc, char** argv){ | |
int len = 1000; | |
const char service[] = "passwd"; | |
char user[len]; | |
const char *changed_username = NULL; | |
struct pam_conv conv; | |
char resp_str[len]; | |
conv.conv=test_conv; | |
pam_handle_t* handle; | |
int ret; | |
printf("Username: "); | |
fgets(user,len, stdin); | |
strtok(user, "\n"); | |
TRY( pam_start(service, user, &conv, &handle )); | |
TRY( pam_authenticate(handle, 0)); | |
TRY( pam_acct_mgmt(handle, 0)); | |
TRY( pam_get_item(handle, PAM_USER,(const void**) &changed_username )); | |
if (changed_username != NULL) { | |
printf("PAM: %s\n", changed_username); | |
} | |
finally: | |
pam_end(handle, ret); | |
return ret; | |
} |
It is the caller's responsibility to release both, this array and the responses themselves
"both" here means the pam_message's and pam_response's
"caller" is the pam module, this is the application code. So for example if you were implementing your own module side pam_sm_authenticate and you'd call pam_get_item(handle, PAM_CONV, &conv)
and then conv->conv( ... )
should't it be
(*resp)[idx].resp=strdup(...)
?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Doesn't the pam_conv man page say to release the resources pam_message and pam_response structures, where does that fit in this code ?