aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Collignon <loic.collignon@iot.bzh>2017-10-26 16:27:49 +0200
committerLoïc Collignon <loic.collignon@iot.bzh>2017-10-26 16:28:29 +0200
commitf8b3ccaa4edd4836885dc3e22062b69e80883f36 (patch)
treef3278c3046acdb884fcb1bce89219cf862fcdd6b
parentf014ffc2223d1b3bd80a14df7698a6b19a08df35 (diff)
add nfc pam module
Change-Id: Icc42361f64948e2c2ab082fa973793f19737df2d Signed-off-by: Loïc Collignon <loic.collignon@iot.bzh>
-rw-r--r--pam_agl/CMakeLists.txt27
-rw-r--r--pam_agl/pam_agl_nfc.c152
-rw-r--r--pam_agl/pam_agl_usb.c (renamed from pam_agl/pam_agl.c)69
3 files changed, 185 insertions, 63 deletions
diff --git a/pam_agl/CMakeLists.txt b/pam_agl/CMakeLists.txt
index 17c85be..7cd39cc 100644
--- a/pam_agl/CMakeLists.txt
+++ b/pam_agl/CMakeLists.txt
@@ -25,22 +25,29 @@ include(FindPkgConfig)
set(PAM_INCLUDE_DIR "/usr/include/")
set(PAM_LIBRARY "/lib64/libpam.so.0")
include_directories(${PAM_INCLUDE_DIR})
+if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
+ get_filename_component(CMAKE_INSTALL_LIBDIR ${PAM_LIBRARY} DIRECTORY)
+endif()
# 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 "")
+# Add the pam_agl_usb target
+add_library(pam_agl_usb SHARED pam_agl_usb.c)
+target_link_libraries(pam_agl_usb ${PAM_LIBRARY} ${${JSON_C}_LIBRARIES})
+set_property(TARGET pam_agl_usb PROPERTY POSITION_INDEPENDENT_CODE ON)
+set_property(TARGET pam_agl_usb PROPERTY PREFIX "")
-if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
- get_filename_component(CMAKE_INSTALL_LIBDIR ${PAM_LIBRARY} DIRECTORY)
-endif()
+install(TARGETS pam_agl_usb
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/security/")
+
+# Add the pam_agl_nfc target
+add_library(pam_agl_nfc SHARED pam_agl_nfc.c)
+target_link_libraries(pam_agl_nfc ${PAM_LIBRARY} ${${JSON_C}_LIBRARIES})
+set_property(TARGET pam_agl_nfc PROPERTY POSITION_INDEPENDENT_CODE ON)
+set_property(TARGET pam_agl_nfc PROPERTY PREFIX "")
-install(TARGETS pam_agl
+install(TARGETS pam_agl_nfc
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/security/")
diff --git a/pam_agl/pam_agl_nfc.c b/pam_agl/pam_agl_nfc.c
new file mode 100644
index 0000000..b25ba5c
--- /dev/null
+++ b/pam_agl/pam_agl_nfc.c
@@ -0,0 +1,152 @@
+#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>
+
+#include <security/pam_client.h>
+#include <security/pam_ext.h>
+#include <security/pam_filter.h>
+#include <security/pam_misc.h>
+#include <security/pam_modutil.h>
+
+#define DATABASE_FILE "/etc/agl/keys.json"
+
+int authenticate(pam_handle_t* pamh, const char* uid)
+{
+ struct json_object* database;
+ struct json_object* nfc;
+ struct json_object* key;
+
+ database = json_object_from_file(DATABASE_FILE);
+ if (!database)
+ {
+ printf("[PAM DEBUG] Failed to parse the database\n");
+ return PAM_SERVICE_ERR;
+ }
+
+ if (json_object_object_get_ex(database, "nfc", &nfc))
+ {
+ if (json_object_object_get_ex(nfc, uid, &key))
+ {
+ printf("[PAM] Key found!\n");
+ printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uid);
+ pam_set_item(pamh, PAM_USER, uid);
+
+ 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, uid);
+
+ json_object_put(database);
+ return PAM_SUCCESS;
+ }
+ }
+
+ printf("[PAM] Key not found!\n");
+ 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;
+ }
+
+ 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);
+
+ 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);
+ 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* uid = pam_getenv(pamh, "UID");
+ log_pam("pam_sm_authenticate", flags, argc, argv, uid);
+ return authenticate(pamh, uid);
+}
+
+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;
+}
diff --git a/pam_agl/pam_agl.c b/pam_agl/pam_agl_usb.c
index c85979d..7afe73d 100644
--- a/pam_agl/pam_agl.c
+++ b/pam_agl/pam_agl_usb.c
@@ -29,37 +29,6 @@ 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;
-}
-
int read_device(const char* device, char** idkey)
{
int fd;
@@ -90,41 +59,35 @@ int read_device(const char* device, char** idkey)
int authenticate(pam_handle_t* pamh, const char* uuid)
{
- char* file_content;
struct json_object* database;
+ struct json_object* usb;
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);
+ database = json_object_from_file(DATABASE_FILE);
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);
+ if (json_object_object_get_ex(database, "usb", &usb))
+ {
+ if (json_object_object_get_ex(usb, 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);
- 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;
+ json_object_put(database);
+ return PAM_SUCCESS;
+ }
}
printf("[PAM] Key not found!\n");
- free(file_content);
if (database) json_object_put(database);
return PAM_AUTH_ERR;
}