1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- #include <assert.h>
- #include <security/pam_appl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h> // getpass
- // apt install libpam0g-dev
- // compile with flag -lpam
- char *pam_get_str(const pam_handle_t *pamh, int item_type) {
- char *str;
- assert(pam_get_item(pamh, item_type, (const void **)&str) == PAM_SUCCESS);
- return str;
- }
- int conv(int num_msg, const struct pam_message **msg,
- struct pam_response **resp, void *appdata_ptr) {
- // [...] *resp is a struct pam_response array [...]
- *resp = calloc(num_msg, sizeof(struct pam_response));
- assert(*resp != NULL);
- for (int i = 0; i < num_msg; i++) {
- // getpass returns a statically allocated string
- (*resp)[i].resp = strdup(getpass(msg[i]->msg));
- }
- return PAM_SUCCESS;
- }
- int main(int argc, char **argv) {
- const char *user = NULL;
- const char *service_name;
- if (argc > 1) {
- service_name = argv[1];
- } else {
- service_name = "test";
- }
- const struct pam_conv pam_conversation = {conv, NULL};
- pam_handle_t *pamh; // blind structure, see security/_pam_types.h
- int status = pam_start(service_name, NULL, &pam_conversation, &pamh);
- if (status != PAM_SUCCESS) {
- fprintf(stderr, "pam_start: %s\n", pam_strerror(pamh, PAM_SYSTEM_ERR));
- return 1;
- } else {
- printf("PAM service name \"%s\"\n", pam_get_str(pamh, PAM_SERVICE));
- int status = pam_authenticate(pamh, 0);
- if (status != PAM_SUCCESS) {
- fprintf(stderr, "pam_authenticate: %s\n", pam_strerror(pamh, status));
- } else {
- char *user = pam_get_str(pamh, PAM_USER);
- fprintf(stderr, "Successfully authenticated user \"%s\".\n", user);
- fprintf(stdout, "%s\n", user);
- }
- assert(pam_end(pamh, status) == PAM_SUCCESS);
- return status == PAM_SUCCESS ? 0 : 2;
- }
- }
|