Browse Source

authenticate user via libpam

Fabian Peter Hammerle 6 years ago
commit
3622b5a660
4 changed files with 62 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 2 0
      Makefile
  3. 3 0
      README.md
  4. 56 0
      main.c

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+app

+ 2 - 0
Makefile

@@ -0,0 +1,2 @@
+app : main.c
+	gcc -o $@ $^ -lpam 

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+```sh
+apt install libpam0g-dev
+```

+ 56 - 0
main.c

@@ -0,0 +1,56 @@
+#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;
+  }
+}