summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <dazo@users.sourceforge.net>2013-05-29 13:15:46 +0200
committerDavid Sommerseth <dazo@users.sourceforge.net>2013-05-29 13:15:46 +0200
commit522e8fbd46334a4187c73c03bdd051bf2cc7c01b (patch)
tree71d7ae9e49df9671b81f2b0af1792335ce41eacb
parenta500eefb1ec9152bd1208c78675e5d8801a57787 (diff)
downloadeurephia-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.txt2
-rw-r--r--auth/flatfile/CMakeLists.txt35
-rw-r--r--auth/flatfile/flatfile-auth.c228
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;
+}
+