diff options
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | device-functions.c | 94 |
2 files changed, 89 insertions, 13 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 68f91f2..ad641cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,16 @@ cmake_minimum_required(VERSION 2.8) project(Instrument) - +include(FindPkgConfig) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) find_package(Glib) find_package(GIO) find_package(Mhash) + +pkg_check_modules(LIBUSER REQUIRED libuser) +add_definitions(${LIBUSER_CFLAGS}) +link_libraries(${LIBUSER_LDFLAGS}) +link_libraries(-lpam) + include_directories(${GLIB_PKG_INCLUDE_DIRS}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -funsigned-char -Wall") add_executable(instr-daemon instr-daemon.c diff --git a/device-functions.c b/device-functions.c index f96cfef..30fac09 100644 --- a/device-functions.c +++ b/device-functions.c @@ -9,7 +9,10 @@ #include "menus.h" #include <math.h> #include <glib.h> - +#include <libuser/user.h> +#include <libuser/config.h> +#include <security/pam_appl.h> +#include <security/pam_misc.h> void idn_string(gchar** response) { @@ -4566,27 +4569,94 @@ int IO_Setup_RS232(int baud, char hardhand, gboolean update_flash) return OK; } -int change_password (gchar *old_password, gchar *new_password) -{ +// this is a conversation handler for pam, it basically sends the password when pam asks for it + +static int conversation(int num_msg, const struct pam_message **msgs, struct pam_response **resp, void *appdata_ptr) { + + struct pam_response* responses = calloc(num_msg, sizeof(struct pam_response)); + if (!responses) { + return PAM_CONV_ERR; + } + + int i; // not compiling in gnu99 mode? + for (i = 0; i < num_msg; i++) { + const struct pam_message *msg = msgs[i]; + struct pam_response* response = &(responses[i]); + switch (msg->msg_style) { + case PAM_PROMPT_ECHO_OFF: + response->resp = strdup((char*) appdata_ptr); + if (!response->resp) + return PAM_CONV_ERR; + break; + + default: + return PAM_CONV_ERR; + } + response->resp_retcode = 0; + } + + *resp = responses; + + return PAM_SUCCESS; +} + +static gboolean checkpassword(const char* username, char* password) { + struct pam_conv pam_conversation = { conversation, password }; + pam_handle_t* pamh; + + if (pam_start("passwd", username, &pam_conversation, &pamh) != PAM_SUCCESS) + return FALSE; + + if (pam_authenticate(pamh, 0) != PAM_SUCCESS) + return FALSE; + + // we only want to check the password and not actually start a session, so get out of here + + pam_end(pamh, 0); + + return TRUE; +} + +int change_password(gchar *old_password, gchar *new_password) { gboolean old_valid = TRUE; - // user = admin - // (always) + char* user = "admin"; // Skip password check if the supplied old_password is NULL. This // only happens when resetting the password to the default. - if (old_password != NULL) { - printf ("verifying old password: %s\n", old_password); //FIXME with real function - // check, and set old_valid = FALSE if the password check fails + if (old_password != NULL ) { + printf("verifying old password: %s\n", old_password); //FIXME with real function + old_valid = checkpassword(user,old_password); } if (old_valid == TRUE) { - printf ("setting new password: %s\n" ,new_password); //FIXME with real function - // is a success test required? + printf("setting new password: %s\n", new_password); //FIXME with real function + struct lu_context *ctx; + struct lu_error *error = NULL; + struct lu_ent *ent; + + ctx = lu_start(user, lu_user, NULL, NULL, lu_prompt_console_quiet, NULL, &error); + + if (ctx == NULL ) { + return password_change_error; + } + + ent = lu_ent_new(); + + if (lu_user_lookup_name(ctx, user, ent, &error) == FALSE) { + return password_change_error; // user doesn't exist + } + + if (lu_user_setpass(ctx, ent, new_password, FALSE, &error) == FALSE) { + return password_change_error; + } + + lu_end(ctx); + return OK; - } else { + } + else { return password_change_error; } } - |