From c99768d395f378ab73f1fbd96381b90a51cf6fac Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Sun, 27 Sep 2009 16:53:54 +0200 Subject: Moved the remainings of administration.c into administration/authentication.c --- database/sqlite/administration/authentication.c | 364 ++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 database/sqlite/administration/authentication.c (limited to 'database/sqlite/administration') diff --git a/database/sqlite/administration/authentication.c b/database/sqlite/administration/authentication.c new file mode 100644 index 0000000..e8a30f0 --- /dev/null +++ b/database/sqlite/administration/authentication.c @@ -0,0 +1,364 @@ +/* administration.c -- Functions needed for administration tasks + * + * GPLv2 only - Copyright (C) 2008, 2009 + * David Sommerseth + * + * 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. + * + */ + +/** + * @file administration.c + * @author David Sommerseth + * @date 2008-12-03 + * + * @brief Functions needed for the administration interface. This file + * primarily takes care of user authentication via the administration API + * + */ + +#include +#include +#include + +#include + +/** + * @{ + */ +#ifndef DRIVERAPIVERSION +# define DRIVERAPIVERSION 2 +#endif +/** + * @} + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef DRIVER_MODE +#define DRIVER_MODE +#endif +#include + +#include "../sqlite.h" + +#if (DRIVERAPIVERSION > 1) || defined(DOXYGEN) +/* + * API Version 2 functions + * + */ + +/** + * @copydoc eDBadminAuth() + */ +int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, const char *pwd) { + dbresult *res = NULL; + char *crpwd = NULL, *dbpwd = NULL; + char *activated = NULL, *deactivated = NULL, *blid = NULL; + int uid = -1, access = 0; + char interface; + + DEBUG(ctx, 20, "Function call: eDBadminAuth(ctx, '%s, '%s', 'xxxxxxxx')", req_access, uname); + + assert(ctx != NULL); + + switch( ctx->context_type ) { + case ECTX_ADMIN_CONSOLE: + interface = 'C'; + break; + case ECTX_ADMIN_WEB: + interface = 'W'; + break; + default: + eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type); + return 0; + } + + if( (strlen_nullsafe(uname) < 4) || (strlen_nullsafe(pwd) < 4) ) { + eurephia_log(ctx, LOG_WARNING, 0, "User name and/or password is either null or less than 4 bytes"); + return 0; + } + + // + // Authenticate user and password + // + res = sqlite_query(ctx, + "SELECT activated, deactivated, bl.blid, " + " password, uid " + " FROM openvpn_users ou" + " LEFT JOIN openvpn_blacklist bl USING (username)" + " WHERE ou.username = '%q'", + uname); + + if( res == NULL ) { + eurephia_log(ctx, LOG_FATAL, 0, "Could not authenticate user against the database"); + return 0; + } + + if( sqlite_get_numtuples(res) == 1 ) { + activated = sqlite_get_value(res, 0, 0); + deactivated = sqlite_get_value(res, 0, 1); + blid = sqlite_get_value(res, 0, 2); + dbpwd = sqlite_get_value(res, 0, 3); + uid = atoi_nullsafe(sqlite_get_value(res, 0, 4)); + + if( blid != NULL ) { + eurephia_log(ctx, LOG_WARNING, 0, + "Your user account is BLACKLISTED. You have no access."); + sqlite_free_results(res); + return 0; + } + + if( activated == NULL ) { + eurephia_log(ctx, LOG_WARNING, 0, "Your user account is not yet activated."); + sqlite_free_results(res); + return 0; + } + + if( deactivated != NULL ) { + eurephia_log(ctx, LOG_WARNING, 0, "Your user account is deactivated."); + sqlite_free_results(res); + return 0; + } + + if( dbpwd == NULL ) { + eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed. DB error."); + sqlite_free_results(res); + return 0; + } else { + int pwdok = 0; + // Verify the password + crpwd = eurephia_pwd_crypt(ctx, pwd, dbpwd); + pwdok = ((crpwd != NULL) && (strcmp(crpwd, dbpwd) == 0) ? 1 : 0); + memset(crpwd, 0, strlen_nullsafe(crpwd)); + memset(dbpwd, 0, strlen_nullsafe(dbpwd)); + free_nullsafe(ctx, crpwd); + if( pwdok == 0 ) { + eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed."); + sleep(2); + sqlite_free_results(res); + return 0; + } + } + sqlite_free_results(res); + + // Check if access level is granted + // (SQLite do not handle advanced joins so well, so we need to + // do this check with an extra query) + res = sqlite_query(ctx, + "SELECT (count(*) = 1) AS access " + " FROM eurephia_adminaccess" + " WHERE uid = '%i' AND interface = '%c' AND access = '%q'", + uid, interface, req_access); + if( res == NULL ) { + eurephia_log(ctx, LOG_FATAL, 0, "Could not check access level"); + return 0; + } + access = atoi_nullsafe(sqlite_get_value(res, 0, 0)); + sqlite_free_results(res); + + if( access == 0 ) { + eurephia_log(ctx, LOG_WARNING, 0, "Your account is lacking privileges for this operation"); + return 0; + } + } else { + eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed. No unique records found."); + sqlite_free_results(res); + sleep(2); + return 0; + } + + // If we reach this place, authentication was successful. Return users uid + return uid; +} + + +/** + * @copydoc eDBadminValidateSession() + */ +int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *req_access) { + dbresult *res = NULL; + int valid = 0, access = 0, expire_time = 0; + char interface; + + DEBUG(ctx, 20, "Function call: eDBadminValidateSession(ctx, '%s, '%s')", sesskey, req_access); + assert( (ctx != NULL) && (sesskey != NULL) ); + + switch( ctx->context_type ) { + case ECTX_ADMIN_CONSOLE: + interface = 'C'; + break; + case ECTX_ADMIN_WEB: + interface = 'W'; + break; + default: + eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type); + return 0; + } + + // Check if the session is still valid (not expired) and that this session are allowed to access + // the requested access level. + expire_time = (60 * atoi_nullsafe(defaultValue(eGet_value(ctx->dbc->config, "eurephiadmin_autologout"), + "10") + ) + ); + res = sqlite_query(ctx, + "SELECT (strftime('%%s',CURRENT_TIMESTAMP)-strftime('%%s',last_action)) > %i AS exp," + " (access IS NOT NULL) AS access" + " FROM eurephia_adminlog" + " LEFT JOIN eurephia_adminaccess USING(uid,interface)" + " WHERE status IN (1,2)" + " AND sessionkey = '%q'" + " AND access = '%q'" + " AND interface = '%c'", + expire_time, sesskey, req_access, interface); + + if( (res == NULL) ) { + eurephia_log(ctx, LOG_FATAL, 0, "Could not validate session"); + return 0; + } + + valid = (atoi_nullsafe(sqlite_get_value(res, 0, 0)) == 0); + access = (atoi_nullsafe(sqlite_get_value(res, 0, 1)) == 1); + sqlite_free_results(res); + + // If still valid, update last_action + if( valid && access ) { + res = sqlite_query(ctx, + "UPDATE eurephia_adminlog" + " SET last_action = CURRENT_TIMESTAMP, status = 2" + " WHERE sessionkey = '%q'", sesskey); + if( res == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, "Could not register session activity"); + } + sqlite_free_results(res); + + } else { + // If not valid, register session as auto-logged out + + res = sqlite_query(ctx, + "UPDATE eurephia_adminlog" + " SET logout = CURRENT_TIMESTAMP, status = %i" + " WHERE sessionkey = '%q'", + (access ? 4 : 5), sesskey); + if( res == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, "Could not register old session as logged out"); + } + sqlite_free_results(res); + + // Delete session variables + res = sqlite_query(ctx, "DELETE FROM openvpn_sessions WHERE sessionkey = '%q'", + sesskey); + if( res == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, + "Could not delete session variables (%s))", sesskey); + return 0; + } + sqlite_free_results(res); + + if( !access ) { + eurephia_log(ctx, LOG_WARNING, 0, "Your user account is lacking privileges"); + } + + } + return (valid && access); +} + + +/** + * @copydoc eDBadminRegisterLogin() + */ +int eDBadminRegisterLogin(eurephiaCTX *ctx, eurephiaSESSION *session) { + dbresult *res = NULL; + char interface; + int uid; + + DEBUG(ctx, 20, "Function call: eDBadminRegisterLogin(ctx, {session}'%s')", session->sessionkey); + assert((ctx != NULL) && (session != NULL)); + + switch( ctx->context_type ) { + case ECTX_ADMIN_CONSOLE: + interface = 'C'; break; + case ECTX_ADMIN_WEB: + interface = 'W'; break; + default: + eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type); + return 0; + } + + // Register login into eurephia_adminlog ... uid, login, interface, sessionkey + uid = atoi_nullsafe(eGet_value(session->sessvals, "uid")); + res = sqlite_query(ctx, + "INSERT INTO eurephia_adminlog " + " (uid, interface, status, login, last_action, sessionkey) " + "VALUES ('%i','%c',1,CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '%q')", + uid, interface, session->sessionkey); + if( !res ) { + eurephia_log(ctx, LOG_FATAL, 0, "Could not manage to register the session in the database"); + return 0; + } + sqlite_free_results(res); + return 1; +} + + +/** + * @copydoc eDBadminLogout() + */ +int eDBadminLogout(eurephiaCTX *ctx, const char *sessionkey) { + dbresult *res = NULL; + + DEBUG(ctx, 20, "Function call: eDBadminLogout(ctx, '%s')", sessionkey); + assert((ctx != NULL) && (sessionkey != NULL)); + + if( (ctx->context_type != ECTX_ADMIN_CONSOLE) && (ctx->context_type != ECTX_ADMIN_WEB) ) { + eurephia_log(ctx, LOG_CRITICAL, 0, + "eurephia admin function call attempted with wrong context type"); + return 0; + } + + // Update session as logged out + res = sqlite_query(ctx, + "UPDATE eurephia_adminlog " + " SET logout = CURRENT_TIMESTAMP, status = 3" + " WHERE sessionkey = '%q'", + sessionkey); + if( !res ) { + eurephia_log(ctx, LOG_FATAL, 0, "Could not manage to register the session as logged out"); + return 0; + } + sqlite_free_results(res); + + // Delete session variables + res = sqlite_query(ctx, "DELETE FROM openvpn_sessions WHERE sessionkey = '%q'", sessionkey); + if( res == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, + "Could not delete session variables (%s))", sessionkey); + return 0; + } + sqlite_free_results(res); + + return 1; +} +#endif -- cgit