#include #include #include #include #include #include // 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; } }