53 lines
1.7 KiB
C
53 lines
1.7 KiB
C
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
//
|
|
// Runs a PAM stack from a directory of its own, so the module can be tried
|
|
// against a development daemon without root and without touching /etc/pam.d:
|
|
//
|
|
// pam_harness CONFDIR SERVICE USER
|
|
//
|
|
// Prints every message the stack sends, answers nothing, and exits 0 when
|
|
// the stack let the user in.
|
|
|
|
#include <security/pam_appl.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static int conversation(int n, const struct pam_message **msg, struct pam_response **resp, void *data)
|
|
{
|
|
(void)data;
|
|
*resp = calloc((size_t)n, sizeof(struct pam_response));
|
|
for (int i = 0; i < n; ++i) {
|
|
const char *kind = msg[i]->msg_style == PAM_TEXT_INFO ? "info"
|
|
: msg[i]->msg_style == PAM_ERROR_MSG ? "error"
|
|
: "prompt";
|
|
printf("%s: %s\n", kind, msg[i]->msg);
|
|
fflush(stdout);
|
|
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || msg[i]->msg_style == PAM_PROMPT_ECHO_ON) {
|
|
// Nobody is typing a password here.
|
|
return PAM_CONV_ERR;
|
|
}
|
|
}
|
|
return PAM_SUCCESS;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc != 4) {
|
|
fprintf(stderr, "usage: %s CONFDIR SERVICE USER\n", argv[0]);
|
|
return 2;
|
|
}
|
|
const struct pam_conv conv = {conversation, NULL};
|
|
pam_handle_t *pamh = NULL;
|
|
int rc = pam_start_confdir(argv[2], argv[3], &conv, argv[1], &pamh);
|
|
if (rc != PAM_SUCCESS) {
|
|
fprintf(stderr, "pam_start: %s\n", pam_strerror(pamh, rc));
|
|
return 2;
|
|
}
|
|
rc = pam_authenticate(pamh, 0);
|
|
printf("result: %s\n", pam_strerror(pamh, rc));
|
|
pam_end(pamh, rc);
|
|
return rc == PAM_SUCCESS ? 0 : 1;
|
|
}
|