12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- #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) {
- char *service_name;
- if (argc > 1) {
- service_name = argv[1];
- } else {
- service_name = "test";
- }
- char *user;
- if (argc > 2) {
- user = argv[2];
- } else {
- user = NULL; // ask later
- }
- 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, user, &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 {
- 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;
- }
- }
|