Skip to content

Instantly share code, notes, and snippets.

@miquels
Created December 7, 2018 10:22
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miquels/391811bd69c6382dad42f7de1e06d448 to your computer and use it in GitHub Desktop.
Save miquels/391811bd69c6382dad42f7de1e06d448 to your computer and use it in GitHub Desktop.
PAM authentication boilerplate.
/* cc -DTEST -Wall -o pamtest pam.c -lpam */
#include <security/pam_appl.h>
#include <sys/resource.h>
#include <string.h>
#include <stdlib.h>
struct creds {
char *user;
char *password;
};
static void add_reply(struct pam_response **reply, int count, char *txt)
{
*reply = realloc(*reply, (count + 1) * sizeof(struct pam_response));
(*reply)[count].resp_retcode = 0;
(*reply)[count].resp = strdup(txt ? txt: "");
}
static int pam_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata)
{
struct pam_response *reply = NULL;
struct creds *creds = (struct creds *)appdata;
int replies = 0;
for (int count = 0; count < num_msg; count++) {
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_ON:
add_reply(&reply, replies++, creds->user);
break;
case PAM_PROMPT_ECHO_OFF:
add_reply(&reply, replies++, creds->password);
break;
case PAM_TEXT_INFO:
break;
case PAM_ERROR_MSG:
default:
if (reply != NULL)
free(reply);
return PAM_CONV_ERR;
}
}
*resp = reply;
return PAM_SUCCESS;
}
int pam_auth(char *service, char *user, char *pass)
{
struct creds creds = {
user,
pass,
};
struct pam_conv conv = {
pam_conv,
&creds,
};
pam_handle_t *pamh = NULL;
int ret = pam_start(service, user, &conv, &pamh);
if (ret != PAM_SUCCESS)
return ret;
if (ret == PAM_SUCCESS)
ret = pam_authenticate(pamh, 0);
pam_end(pamh, 0);
return ret;
}
#ifdef TEST
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc < 3 || argv[1][0] == '-') {
fprintf(stderr, "Usage: pamtest <service> <username> <password>\n");
fprintf(stderr, " <service> is usually \"other\"\n");
return 1;
}
int r = pam_auth(argv[1], argv[2], argv[3]);
if (r == PAM_SUCCESS) {
printf("Ok\n");
} else {
printf("Fail, code = %d\n", r);
}
return r == PAM_SUCCESS ? 0 : 1;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment