diff options
author | Loïc Collignon <loic.collignon@iot.bzh> | 2017-07-11 06:36:33 +0200 |
---|---|---|
committer | Loïc Collignon <loic.collignon@iot.bzh> | 2017-07-11 06:36:33 +0200 |
commit | 0455a7401f9f0f9bfad82c5ddf04f7dd70b0b852 (patch) | |
tree | 819bc150cb62c8eb344656086bbb52892f5288b8 /pam_agl | |
parent | 66b90d26cfd555b2aa5fef67d31e539a70256719 (diff) |
first somewhat working version.
Change-Id: I3101dc6b8add87eccac3bbf177b1320137f72463
Signed-off-by: Loïc Collignon <loic.collignon@iot.bzh>
Diffstat (limited to 'pam_agl')
-rw-r--r-- | pam_agl/CMakeLists.txt | 28 | ||||
-rw-r--r-- | pam_agl/pam_agl.c | 160 |
2 files changed, 188 insertions, 0 deletions
diff --git a/pam_agl/CMakeLists.txt b/pam_agl/CMakeLists.txt new file mode 100644 index 0000000..564a025 --- /dev/null +++ b/pam_agl/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.1) +project(pam_agl) + +include(FindPkgConfig) + +# Require PAM but there is no find_package +set(PAM_INCLUDE_DIR "/usr/include/") +set(PAM_LIBRARY "/lib64/libpam.so.0") +include_directories(${PAM_INCLUDE_DIR}) + +# Find json-c +pkg_check_modules(${JSON_C} REQUIRED json-c) +include_directories(${${JSON_C}_INCLUDE_DIRS}) +add_compile_options(${${JSON_C}_CFLAGS}) + +# Add the target +add_library(pam_agl SHARED pam_agl.c) +target_link_libraries(pam_agl ${PAM_LIBRARY} ${${JSON_C}_LIBRARIES}) +#list (APPEND link_libraries ${${JSON_C}_LDFLAGS}) +set_property(TARGET pam_agl PROPERTY POSITION_INDEPENDENT_CODE ON) +set_property(TARGET pam_agl PROPERTY PREFIX "") + +if (NOT DEFINED CMAKE_INSTALL_LIBDIR) + get_filename_component(CMAKE_INSTALL_LIBDIR ${PAM_LIBRARY} DIRECTORY) +endif() + +install(TARGETS pam_agl + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/security/") diff --git a/pam_agl/pam_agl.c b/pam_agl/pam_agl.c new file mode 100644 index 0000000..3e246e4 --- /dev/null +++ b/pam_agl/pam_agl.c @@ -0,0 +1,160 @@ +#include <fcntl.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <uuid/uuid.h> +#include <json-c/json.h> + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_SM_SESSION +#define PAM_SM_PASSWORD +#include <security/pam_modules.h> +#include <security/pam_appl.h> + +#define BLOCK_SIZE 4096 +typedef struct header_ +{ + char mn[4]; + size_t size; +} header; + +int is_valid_mn(const char* v) +{ + return v && v[0] == 'I' && v[1] == 'D' && v[2] == 'K' && v[3] == 'Y'; +} + +void pam_putenv_ex(pam_handle_t* pamh, const char* name, const char* value) +{ + char result[4096]; + strcpy(result, name); + + int offset = strlen(name); + result[offset] = '='; + + strcpy(result + offset + 1, value); + + pam_putenv(pamh, result); +} + +int check_device(pam_handle_t* pamh, const char* device) +{ + printf("[PAM DEBUG]: check_device %s...\n", device); + int fd = open(device, O_RDONLY); + if (fd == -1) + { + 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)); + 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); + + char* 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); + close(fd); + + 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); + + 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; } + + 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; } + + 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; +} + +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); + for(int i = 0; i < argc; ++i) + { + printf("[PAM DEBUG]: argv[%d]: %s\n", i, argv[i]); + } + printf("[PAM DEBUG]: device: %s\n", device); + printf("[PAM DEBUG]: ----------------------------------------\n"); +} + +/*! + @brief The pam_sm_authenticate function is the service module's implementation + of the pam_authenticate(3) interface. + This function performs the task of authenticating the user. + + @param[in] pamh Unknown. + @param[in] flags PAM_SILENT and/or PAM_DISALLOW_NULL_AUTHTOK. + @return PAM_SUCCESS if ok. +*/ +PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv) +{ + const char* device = pam_getenv(pamh, "DEVICE"); + log_pam("pam_sm_authenticate", flags, argc, argv, device); + return check_device(pamh, device); +} + +PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv) +{ + log_pam("pam_sm_setcred", flags, argc, argv, pam_getenv(pamh, "DEVICE")); + return PAM_SUCCESS; +} + +PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv) +{ + log_pam("pam_sm_acct_mgmt", flags, argc, argv, pam_getenv(pamh, "DEVICE")); + return PAM_SUCCESS; +} + +PAM_EXTERN int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char** argv) +{ + log_pam("pam_sm_open_session", flags, argc, argv, pam_getenv(pamh, "DEVICE")); + return PAM_SUCCESS; +} + +PAM_EXTERN int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char** argv) +{ + log_pam("pam_sm_close_session", flags, argc, argv, pam_getenv(pamh, "DEVICE")); + return PAM_SUCCESS; +} + +PAM_EXTERN int pam_sm_chauthtok(pam_handle_t* pamh, int flags, int argc, const char** argv) +{ + log_pam("pam_sm_chauthtok", flags, argc, argv, pam_getenv(pamh, "DEVICE")); + return PAM_SUCCESS; +} |