From e490f85b3ad29f3457d77cd3b2bdf31a76b22ac9 Mon Sep 17 00:00:00 2001 From: Loïc Collignon Date: Mon, 31 Jul 2017 23:33:53 +0200 Subject: authenticate keys against a json document. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I988ccef75bf3f1def40893aa506d169a3926e32a Signed-off-by: Loïc Collignon --- pam_agl/pam_agl.c | 166 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 45 deletions(-) diff --git a/pam_agl/pam_agl.c b/pam_agl/pam_agl.c index 3e246e4..0eea11a 100644 --- a/pam_agl/pam_agl.c +++ b/pam_agl/pam_agl.c @@ -15,6 +15,8 @@ #include #include +#define DATABASE_FILE "/etc/agl/keys.json" + #define BLOCK_SIZE 4096 typedef struct header_ { @@ -27,6 +29,37 @@ int is_valid_mn(const char* v) return v && v[0] == 'I' && v[1] == 'D' && v[2] == 'K' && v[3] == 'Y'; } +char* get_file_content(const char* path) +{ + char* buffer; + long length; + FILE* f; + + buffer = NULL; + length = 0; + + f = fopen(path, "rb"); + if (f) + { + fseek(f, 0, SEEK_END); + length = ftell(f); + fseek(f, 0, SEEK_SET); + buffer = malloc(length + 1); + if (buffer) + { + if (fread (buffer, 1, length, f) != length) + { + free(buffer); + buffer = NULL; + } + else buffer[length] = 0; + } + fclose (f); + } + + return buffer; +} + void pam_putenv_ex(pam_handle_t* pamh, const char* name, const char* value) { char result[4096]; @@ -40,77 +73,120 @@ void pam_putenv_ex(pam_handle_t* pamh, const char* name, const char* value) pam_putenv(pamh, result); } -int check_device(pam_handle_t* pamh, const char* device) +int read_device(const char* device, char** idkey) { - printf("[PAM DEBUG]: check_device %s...\n", device); - int fd = open(device, O_RDONLY); + int fd; + ssize_t sz; + header h; + + printf("[PAM DEBUG] check_device %s...\n", device); + fd = open(device, O_RDONLY); if (fd == -1) { - printf("[PAM DEBUG]: Failed to open the device %s!\n", device); + printf("[PAM DEBUG] Failed to open the device %s!\n", device); return PAM_SERVICE_ERR; } - header h; - ssize_t sz = read(fd, &h, sizeof(header)); + sz = read(fd, &h, sizeof(header)); if (sz != sizeof(header) || !is_valid_mn(h.mn) || h.size < 1) { close(fd); printf("[PAM DEBUG]: bad header!\n"); return PAM_SERVICE_ERR; } - printf("[PAM DEBUG]: data size=%d\n", h.size); + printf("[PAM DEBUG]: data size=%lu\n", h.size); - char* idkey = (char*)malloc(h.size + 1); - if (!idkey) { close(fd); printf("[PAM DEBUG] Bad alloc!\n"); return PAM_SERVICE_ERR; } + *idkey = (char*)malloc(h.size + 1); + if (!*idkey) { close(fd); printf("[PAM DEBUG] Bad alloc!\n"); return PAM_SERVICE_ERR; } - memset(idkey, 0, h.size + 1); - size_t count = read(fd, idkey, h.size); + memset(*idkey, 0, h.size + 1); + sz = read(fd, *idkey, h.size); close(fd); + if (sz != h.size) { free(idkey); printf("[PAM DEBUG] Bad data read!\n"); return PAM_SERVICE_ERR; } + return PAM_SUCCESS; +} - if (count != h.size) { free(idkey); printf("[PAM DEBUG] Bad data read!\n"); return PAM_SERVICE_ERR; } - printf("[PAM DEBUG] Data read:\n%s\n", idkey); +int authenticate(pam_handle_t* pamh, const char* uuid) +{ + char* file_content; + struct json_object* database; + struct json_object* key; + + file_content = get_file_content(DATABASE_FILE); + if (!file_content) + { + printf("[PAM DEBUG] Failed to read database file (%s)\n", DATABASE_FILE); + return PAM_SERVICE_ERR; + } + + database = json_tokener_parse(file_content); + if (!database) + { + printf("[PAM DEBUG] Failed to parse the database\n"); + return PAM_SERVICE_ERR; + } + + if (json_object_object_get_ex(database, uuid, &key)) + { + printf("[PAM] Key found!\n"); + printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uuid); + pam_set_item(pamh, PAM_USER, uuid); + + const char* pam_authtok; + if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok) + pam_set_item(pamh, PAM_AUTHTOK, uuid); + + json_object_put(database); + free(file_content); + return PAM_SUCCESS; + } + + printf("[PAM] Key not found!\n"); + free(file_content); + if (database) json_object_put(database); + return PAM_AUTH_ERR; +} +int check_device(pam_handle_t* pamh, const char* device) +{ + char* idkey; + int ret; + + ret = read_device(device, &idkey); + if (ret != PAM_SUCCESS) return ret; + + printf("[PAM DEBUG] Data read:\n%s\n", idkey); + json_object* idkey_json = json_tokener_parse(idkey); - if (!idkey_json) { free(idkey); printf("[PAM DEBUG] Failed to parse json data!\n"); return PAM_SERVICE_ERR; } + if (!idkey_json) + { + free(idkey); + printf("[PAM DEBUG] Failed to parse json data!\n"); + return PAM_SERVICE_ERR; + } json_object* uuid_json; - 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; } + 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; + } const char* uuid = json_object_get_string(uuid_json); printf("[PAM DEBUG] uuid: %s\n", uuid); - - // TODO: Check if the uuid is accepted - const char* const ids[] = { - "4f29e9ea-600a-11e7-8331-c70192ecfa55", - "13126524-6256-11e7-be33-3f4e4481a8c9", - NULL - }; - - int i = 0; - while(ids[i]) - { - if (!strcmp(ids[i], uuid)) - { - printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uuid); - pam_set_item(pamh, PAM_USER, uuid); - - const char* pam_authtok; - if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok) - pam_set_item(pamh, PAM_AUTHTOK, uuid); - - return PAM_SUCCESS; - } - ++i; - } - return PAM_AUTH_ERR; + ret = authenticate(pamh, uuid); + free(idkey); + json_object_put(idkey_json); + return ret; } void log_pam(const char* fname, int flags, int argc, const char** argv, const char* device) { - printf("[PAM DEBUG]: ---------- %s ----------\n", fname); - printf("[PAM DEBUG]: flags: %d\n", flags); + printf("[PAM DEBUG] ---------- %s ----------\n", fname); + printf("[PAM DEBUG] flags: %d\n", flags); for(int i = 0; i < argc; ++i) { - printf("[PAM DEBUG]: argv[%d]: %s\n", i, argv[i]); + printf("[PAM DEBUG] argv[%d]: %s\n", i, argv[i]); } - printf("[PAM DEBUG]: device: %s\n", device); - printf("[PAM DEBUG]: ----------------------------------------\n"); + printf("[PAM DEBUG] device: %s\n", device); + printf("[PAM DEBUG] ----------------------------------------\n"); } /*! -- cgit 1.2.3-korg