diff options
author | David Sommerseth <dazo@users.sourceforge.net> | 2013-05-29 13:15:46 +0200 |
---|---|---|
committer | David Sommerseth <dazo@users.sourceforge.net> | 2013-05-29 13:15:46 +0200 |
commit | 522e8fbd46334a4187c73c03bdd051bf2cc7c01b (patch) | |
tree | 71d7ae9e49df9671b81f2b0af1792335ce41eacb | |
parent | a500eefb1ec9152bd1208c78675e5d8801a57787 (diff) | |
download | eurephia-522e8fbd46334a4187c73c03bdd051bf2cc7c01b.tar.gz eurephia-522e8fbd46334a4187c73c03bdd051bf2cc7c01b.tar.xz eurephia-522e8fbd46334a4187c73c03bdd051bf2cc7c01b.zip |
auth-plugin: Added a simple flat-file authentication example
This auth-plugin will authenticate users against a simple
text file containing username and password hashes, separated
by a '|' (pipe).
Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | auth/flatfile/CMakeLists.txt | 35 | ||||
-rw-r--r-- | auth/flatfile/flatfile-auth.c | 228 |
3 files changed, 264 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e516767..1297b7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,7 +181,7 @@ SET_PROPERTY(TARGET common PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/common # Start the building. First build the common library, and then the requested eurephia modules IF(DATABASE OR PLUGIN OR FIREWALL OR EUREPHIADM) - SUBDIRS(common auth/dummy ${subdirs}) + SUBDIRS(common auth/dummy auth/flatfile ${subdirs}) ENDIF(DATABASE OR PLUGIN OR FIREWALL OR EUREPHIADM) # Compile Doxygen docs at the end if requested diff --git a/auth/flatfile/CMakeLists.txt b/auth/flatfile/CMakeLists.txt new file mode 100644 index 0000000..ef1a677 --- /dev/null +++ b/auth/flatfile/CMakeLists.txt @@ -0,0 +1,35 @@ +# cmake rules for eurephia - dummy-auth plug-in +# +# This module is only for testing purpose. +# DO NO USE THIS PLUG-IN IN A PRODUCTION ENVIRONMENT +# +# GPLv2 only - Copyright (C) 2008 - 2012 +# David Sommerseth <dazo@users.sourceforge.net> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +PROJECT(eAuth-flatfile C) +cmake_minimum_required(VERSION 2.6) + +# Compiler settigns +INCLUDE_DIRECTORIES(. ../../common .. ../../database) + +ADD_LIBRARY(flatfile-auth SHARED + flatfile-auth.c +) +TARGET_LINK_LIBRARIES(flatfile-auth common) +SET_TARGET_PROPERTIES(flatfile-auth PROPERTIES COMPILE_FLAGS -fPIC) +SET_TARGET_PROPERTIES(flatfile-auth PROPERTIES OUTPUT_NAME flatfile-auth PREFIX "") + diff --git a/auth/flatfile/flatfile-auth.c b/auth/flatfile/flatfile-auth.c new file mode 100644 index 0000000..141fcd3 --- /dev/null +++ b/auth/flatfile/flatfile-auth.c @@ -0,0 +1,228 @@ +/* flatfile-auth.c -- Simple authentication plug-in demonstrating its use case + * + * Copyright (C) 2013 David Sommerseth <dazo@users.sourceforge.net> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * @file flatfile-auth.c + * @author David Sommerseth <dazo@users.sourceforge.net> + * @date 2013-05-29 + * + * @brief Simple example plug-in authenticating user passwords + * against a simple flat file "database" + */ + +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <eurephia_nullsafe.h> +#include <eurephia_context.h> +#include <eurephia_log.h> +#include <eurephia_values.h> +#include <eurephia_authplugin_driver.h> +#include <passwd.h> + +static ePluginInfo pluginfo = { .name = "flatfile authentication", + .version = "1.0", + .copyright = "2013 (C) David Sommerseth <dazo@users.sourceforge.net>", + .pluginType = eptAUTH, + .APIversion = 1 }; + + +static eurephiaVALUES *config = NULL; +static eurephiaVALUES *passdb = NULL; + +/** + * @copydoc PluginInfo() + */ +ePluginInfo * PluginInfo() +{ + return &pluginfo; +} + +/** + * @copydoc PluginInit() + */ +int PluginInit(eurephiaCTX *ctx, const char *args) +{ + FILE *fp = NULL; + char line[4098]; + + config = eCreate_value_space(ctx, 80); + if( config == NULL ) { + eurephia_log(ctx, LOG_FATAL, 0, "Failed to initialise flatfile auth"); + return 0; + } + eAdd_value(ctx, config, "password_file", args); + + + // Load all username/password hashes into memory - *NOT RECOMMENDED* in real production environments + fp = fopen(args, "r"); + if( fp == NULL ) { + eFree_values(ctx, config); + eurephia_log(ctx, LOG_FATAL, 0, "flatfile-auth: Failed to open user/password file"); + return 0; + } + + passdb = eCreate_value_space(ctx, 81); + if( config == NULL ) { + eFree_values(ctx, config); + fclose(fp); + eurephia_log(ctx, LOG_FATAL, 0, + "flatfile-auth: Failed to allocate memory to " + "username/password database"); + return 0; + } + + memset(&line, 0, 4098); + while( fgets(line, 4096, fp) ) { + char *pw = strstr(line, "|"); + if( pw != NULL ) { + char *eol = strstr(pw, "\n"); + *eol = 0; // Simple strip of \n at end of records + *pw = 0; // Split the username and password using a NULL-terminator + pw++; + eAdd_value(ctx, passdb, line, pw); + } else { + eurephia_log(ctx, LOG_WARNING, 0, + "flatfile-auth: Failed to parse record (no delimiter): %s", line); + } + memset(&line, 0, 4098); + } + fclose(fp); + eurephia_log(ctx, LOG_INFO, 0, "flatfile auth initialised, using '%s' as user/password database", args); + return 1; +} + + +/** + * @copydoc PluginClose() + */ +void PluginClose(eurephiaCTX *ctx) +{ + eFree_values(ctx, config); + eurephia_log(ctx, LOG_INFO, 0, "flatfile auth stopped"); +} + + +/** + * @copydoc AuthenticateUser() + */ +eAuthResult * AuthenticateUser(eurephiaCTX *ctx, const char *username, const char *passwd) +{ + char *pwhash = NULL; + eAuthResult *res = NULL; + + DEBUG(ctx, 10, "flatfile-auth:AuthenticateUser('%s', 'xxxxxx')", username); + assert(passdb != NULL); + + // Allocate result buffer + res = malloc_nullsafe(ctx, sizeof(eAuthResult)+2); + if( res == NULL ) { + return NULL; + } + + // Look up password hash from in-memory password database + pwhash = eGet_value(passdb, username); + if( pwhash != NULL ) { // If found, verify the password + + char *crpwd = eurephia_pwd_crypt(ctx, passwd, pwhash); + res->status = ((crpwd != NULL) && (strcmp(crpwd, pwhash) == 0) ? eAUTH_SUCCESS : eAUTH_FAILED); + if( res->status == eAUTH_FAILED ) { + res->msg = strdup("Wrong password"); + } + free_nullsafe(ctx, crpwd); + } else { // If not found - fail + res->status = eAUTH_FAILED; + res->msg = malloc_nullsafe(ctx, strlen(username)+32); + snprintf(res->msg, strlen(username)+30, "flatfile username attempted: %s", username); + } + + return res; +} + + +/** + * @copydoc ChangePassword() + */ +eAuthResult * ChangePassword(eurephiaCTX *ctx, const char *username, + const char *oldpass, const char *newpass) +{ + eurephiaVALUES *pwentry = NULL, *rec = NULL; + char *crpwd = NULL; + eAuthResult *res = NULL; + FILE *fp = NULL; + + DEBUG(ctx, 10, "flatfile-auth:ChangePassword('%s', 'xxxOLDxxx', 'xxxNEWxxx')", username); + assert((passdb != NULL) && (config != NULL)); + + // Allocate result buffer + res = malloc_nullsafe(ctx, sizeof(eAuthResult)+2); + if( res == NULL ) { + return NULL; + } + + // Find the password entry + pwentry = eGet_valuestruct(passdb, username); + if( pwentry == NULL ) { // If not found --> assume new user. + eurephiaVALUES *newrec = eCreate_value_space(ctx, 81); + if( newrec == NULL ) { + res->status = eAUTH_PLGERROR; + res->msg = strdup("Internal failure when preparing new user entry"); + return res; + } + newrec->key = strdup(username); + newrec->val = eurephia_pwd_crypt(ctx, oldpass, NULL); + eAdd_valuestruct(ctx, passdb, newrec); + } else { + // Verify the password hash for the existing user + crpwd = eurephia_pwd_crypt(ctx, oldpass, pwentry->val); + if( (crpwd != NULL) && (strcmp(crpwd, pwentry->val) == 0) ) { // Password correct - update database + // Get a new password hash + free_nullsafe(ctx, crpwd); + crpwd = eurephia_pwd_crypt(ctx, newpass, NULL); + if( crpwd == NULL ) { + res->status = eAUTH_PLGERROR; + res->msg = strdup("Failed to generate new password hash"); + return res; + } + } + } + + // Open the database file with write access + fp = fopen(eGet_value(config, "password_file"), "w"); + if( fp == NULL ) { + res->status = eAUTH_PLGERROR; + res->msg = strdup("Failed to open password file with write access"); + return res; + } + + // Remove the old password hash from the memory database + // and replace it with the new one + free_nullsafe(ctx, pwentry->val); + pwentry->val = crpwd; + + // Update the database file + rewind(fp); + for( rec = passdb; rec != NULL; rec = rec->next ) { + fprintf(fp, "%s|%s\n", rec->key, rec->val); + } + fclose(fp); + + return res; +} + |