9 #include <json-c/json.h>
12 #define PAM_SM_ACCOUNT
13 #define PAM_SM_SESSION
14 #define PAM_SM_PASSWORD
15 #include <security/pam_modules.h>
16 #include <security/pam_appl.h>
18 #define BLOCK_SIZE 4096
19 typedef struct header_
25 int is_valid_mn(const char* v)
27 return v && v[0] == 'I' && v[1] == 'D' && v[2] == 'K' && v[3] == 'Y';
30 void pam_putenv_ex(pam_handle_t* pamh, const char* name, const char* value)
35 int offset = strlen(name);
38 strcpy(result + offset + 1, value);
40 pam_putenv(pamh, result);
43 int check_device(pam_handle_t* pamh, const char* device)
45 printf("[PAM DEBUG]: check_device %s...\n", device);
46 int fd = open(device, O_RDONLY);
49 printf("[PAM DEBUG]: Failed to open the device %s!\n", device);
50 return PAM_SERVICE_ERR;
54 ssize_t sz = read(fd, &h, sizeof(header));
55 if (sz != sizeof(header) || !is_valid_mn(h.mn) || h.size < 1) { close(fd); printf("[PAM DEBUG]: bad header!\n"); return PAM_SERVICE_ERR; }
56 printf("[PAM DEBUG]: data size=%d\n", h.size);
58 char* idkey = (char*)malloc(h.size + 1);
59 if (!idkey) { close(fd); printf("[PAM DEBUG] Bad alloc!\n"); return PAM_SERVICE_ERR; }
61 memset(idkey, 0, h.size + 1);
62 size_t count = read(fd, idkey, h.size);
65 if (count != h.size) { free(idkey); printf("[PAM DEBUG] Bad data read!\n"); return PAM_SERVICE_ERR; }
66 printf("[PAM DEBUG] Data read:\n%s\n", idkey);
68 json_object* idkey_json = json_tokener_parse(idkey);
69 if (!idkey_json) { free(idkey); printf("[PAM DEBUG] Failed to parse json data!\n"); return PAM_SERVICE_ERR; }
71 json_object* uuid_json;
72 if(!json_object_object_get_ex(idkey_json, "uuid", &uuid_json)) { free(idkey); printf("[PAM DEBUG]: The json does not contains a valid uuid\n"); return PAM_SERVICE_ERR; }
74 const char* uuid = json_object_get_string(uuid_json);
75 printf("[PAM DEBUG] uuid: %s\n", uuid);
77 // TODO: Check if the uuid is accepted
78 const char* const ids[] = {
79 "4f29e9ea-600a-11e7-8331-c70192ecfa55",
80 "13126524-6256-11e7-be33-3f4e4481a8c9",
87 if (!strcmp(ids[i], uuid))
89 printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uuid);
90 pam_set_item(pamh, PAM_USER, uuid);
92 const char* pam_authtok;
93 if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok)
94 pam_set_item(pamh, PAM_AUTHTOK, uuid);
104 void log_pam(const char* fname, int flags, int argc, const char** argv, const char* device)
106 printf("[PAM DEBUG]: ---------- %s ----------\n", fname);
107 printf("[PAM DEBUG]: flags: %d\n", flags);
108 for(int i = 0; i < argc; ++i)
110 printf("[PAM DEBUG]: argv[%d]: %s\n", i, argv[i]);
112 printf("[PAM DEBUG]: device: %s\n", device);
113 printf("[PAM DEBUG]: ----------------------------------------\n");
117 @brief The pam_sm_authenticate function is the service module's implementation
118 of the pam_authenticate(3) interface.
119 This function performs the task of authenticating the user.
121 @param[in] pamh Unknown.
122 @param[in] flags PAM_SILENT and/or PAM_DISALLOW_NULL_AUTHTOK.
123 @return PAM_SUCCESS if ok.
125 PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv)
127 const char* device = pam_getenv(pamh, "DEVICE");
128 log_pam("pam_sm_authenticate", flags, argc, argv, device);
129 return check_device(pamh, device);
132 PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv)
134 log_pam("pam_sm_setcred", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
138 PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv)
140 log_pam("pam_sm_acct_mgmt", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
144 PAM_EXTERN int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
146 log_pam("pam_sm_open_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
150 PAM_EXTERN int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
152 log_pam("pam_sm_close_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
156 PAM_EXTERN int pam_sm_chauthtok(pam_handle_t* pamh, int flags, int argc, const char** argv)
158 log_pam("pam_sm_chauthtok", flags, argc, argv, pam_getenv(pamh, "DEVICE"));