🦋🔑 PAM provider for ATProto
1/* pam_atpam.c – talk to the atpam Unix-socket daemon (DEBUG build) */
2#define PAM_SM_AUTH
3#include <security/pam_modules.h>
4#include <security/pam_ext.h>
5#include <stdio.h>
6#include <string.h>
7#include <unistd.h>
8#include <sys/socket.h>
9#include <sys/un.h>
10
11#define SOCK "/run/atpam.sock"
12
13PAM_EXTERN int
14pam_sm_authenticate(pam_handle_t *pamh, int flags,
15 int argc, const char **argv)
16{
17 const char *user = NULL, *pass = NULL;
18 pam_get_user(pamh, &user, NULL);
19 pam_get_authtok(pamh, PAM_AUTHTOK, &pass, NULL);
20
21 fprintf(stderr, "DEBUG pam_atpam: user=[%s] pass-len=%zu\n",
22 user ? user : "(null)", pass ? strlen(pass) : 0);
23
24 const char *field, *value;
25 if (strchr(user, ':')) {
26 field = "did"; value = user;
27 } else if (strncmp(user, "didplc-", 7) == 0 ||
28 strncmp(user, "didweb-", 7) == 0) {
29 field = "unix"; value = user;
30 } else {
31 field = "handle"; value = user;
32 }
33 fprintf(stderr, "DEBUG pam_atpam: chosen field=[%s] value=[%s]\n", field, value);
34
35 char json[512];
36 int n = snprintf(json, sizeof(json),
37 "{\"%s\":\"%s\",\"password\":\"%s\"}",
38 field, value, pass ? pass : "");
39 fprintf(stderr, "DEBUG pam_atpam: sending %.*s\n", n, json);
40
41 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
42 if (fd < 0) { perror("socket"); return PAM_AUTH_ERR; }
43
44 struct sockaddr_un addr = { .sun_family = AF_UNIX };
45 strncpy(addr.sun_path, SOCK, sizeof(addr.sun_path) - 1);
46
47 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
48 perror("connect");
49 close(fd);
50 return PAM_AUTH_ERR;
51 }
52 fprintf(stderr, "DEBUG pam_atpam: connected to %s\n", SOCK);
53
54 if (write(fd, json, n) != n) { perror("write"); close(fd); return PAM_AUTH_ERR; }
55
56 n = read(fd, json, sizeof(json) - 1);
57 close(fd);
58 if (n <= 0) { perror("read"); return PAM_AUTH_ERR; }
59 json[n] = '\0';
60
61 fprintf(stderr, "DEBUG pam_atpam: daemon replied [%s]\n", json);
62 return strstr(json, "\"ok\":true") ? PAM_SUCCESS : PAM_AUTH_ERR;
63}
64
65PAM_EXTERN int
66pam_sm_setcred(pam_handle_t *pamh, int flags,
67 int argc, const char **argv)
68{ return PAM_SUCCESS; }