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 DATABASE_FILE "/etc/agl/keys.json"
20 #define BLOCK_SIZE 4096
21 typedef struct header_
27 int is_valid_mn(const char* v)
29 return v && v[0] == 'I' && v[1] == 'D' && v[2] == 'K' && v[3] == 'Y';
32 char* get_file_content(const char* path)
41 f = fopen(path, "rb");
44 fseek(f, 0, SEEK_END);
46 fseek(f, 0, SEEK_SET);
47 buffer = malloc(length + 1);
50 if (fread (buffer, 1, length, f) != length)
55 else buffer[length] = 0;
63 void pam_putenv_ex(pam_handle_t* pamh, const char* name, const char* value)
68 int offset = strlen(name);
71 strcpy(result + offset + 1, value);
73 pam_putenv(pamh, result);
76 int read_device(const char* device, char** idkey)
82 printf("[PAM DEBUG] check_device %s...\n", device);
83 fd = open(device, O_RDONLY);
86 printf("[PAM DEBUG] Failed to open the device %s!\n", device);
87 return PAM_SERVICE_ERR;
90 sz = read(fd, &h, sizeof(header));
91 if (sz != sizeof(header) || !is_valid_mn(h.mn) || h.size < 1) { close(fd); printf("[PAM DEBUG]: bad header!\n"); return PAM_SERVICE_ERR; }
92 printf("[PAM DEBUG]: data size=%lu\n", h.size);
94 *idkey = (char*)malloc(h.size + 1);
95 if (!*idkey) { close(fd); printf("[PAM DEBUG] Bad alloc!\n"); return PAM_SERVICE_ERR; }
97 memset(*idkey, 0, h.size + 1);
98 sz = read(fd, *idkey, h.size);
100 if (sz != h.size) { free(idkey); printf("[PAM DEBUG] Bad data read!\n"); return PAM_SERVICE_ERR; }
104 int authenticate(pam_handle_t* pamh, const char* uuid)
107 struct json_object* database;
108 struct json_object* key;
110 file_content = get_file_content(DATABASE_FILE);
113 printf("[PAM DEBUG] Failed to read database file (%s)\n", DATABASE_FILE);
114 return PAM_SERVICE_ERR;
117 database = json_tokener_parse(file_content);
120 printf("[PAM DEBUG] Failed to parse the database\n");
121 return PAM_SERVICE_ERR;
124 if (json_object_object_get_ex(database, uuid, &key))
126 printf("[PAM] Key found!\n");
127 printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uuid);
128 pam_set_item(pamh, PAM_USER, uuid);
130 const char* pam_authtok;
131 if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok)
132 pam_set_item(pamh, PAM_AUTHTOK, uuid);
134 json_object_put(database);
139 printf("[PAM] Key not found!\n");
141 if (database) json_object_put(database);
145 int check_device(pam_handle_t* pamh, const char* device)
150 ret = read_device(device, &idkey);
151 if (ret != PAM_SUCCESS) return ret;
153 printf("[PAM DEBUG] Data read:\n%s\n", idkey);
155 json_object* idkey_json = json_tokener_parse(idkey);
159 printf("[PAM DEBUG] Failed to parse json data!\n");
160 return PAM_SERVICE_ERR;
163 json_object* uuid_json;
164 if(!json_object_object_get_ex(idkey_json, "uuid", &uuid_json))
167 printf("[PAM DEBUG] The json does not contains a valid uuid\n");
168 return PAM_SERVICE_ERR;
171 const char* uuid = json_object_get_string(uuid_json);
172 printf("[PAM DEBUG] uuid: %s\n", uuid);
174 ret = authenticate(pamh, uuid);
176 json_object_put(idkey_json);
180 void log_pam(const char* fname, int flags, int argc, const char** argv, const char* device)
182 printf("[PAM DEBUG] ---------- %s ----------\n", fname);
183 printf("[PAM DEBUG] flags: %d\n", flags);
184 for(int i = 0; i < argc; ++i)
186 printf("[PAM DEBUG] argv[%d]: %s\n", i, argv[i]);
188 printf("[PAM DEBUG] device: %s\n", device);
189 printf("[PAM DEBUG] ----------------------------------------\n");
193 @brief The pam_sm_authenticate function is the service module's implementation
194 of the pam_authenticate(3) interface.
195 This function performs the task of authenticating the user.
197 @param[in] pamh Unknown.
198 @param[in] flags PAM_SILENT and/or PAM_DISALLOW_NULL_AUTHTOK.
199 @return PAM_SUCCESS if ok.
201 PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv)
203 const char* device = pam_getenv(pamh, "DEVICE");
204 log_pam("pam_sm_authenticate", flags, argc, argv, device);
205 return check_device(pamh, device);
208 PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv)
210 log_pam("pam_sm_setcred", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
214 PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv)
216 log_pam("pam_sm_acct_mgmt", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
220 PAM_EXTERN int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
222 log_pam("pam_sm_open_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
226 PAM_EXTERN int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
228 log_pam("pam_sm_close_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
232 PAM_EXTERN int pam_sm_chauthtok(pam_handle_t* pamh, int flags, int argc, const char** argv)
234 log_pam("pam_sm_chauthtok", flags, argc, argv, pam_getenv(pamh, "DEVICE"));