From 96b177a197fad3bec1332f2e140cdf3863970cce Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Tue, 2 Dec 2008 23:42:21 +0100 Subject: Enhanced the access control by introducing access levels --- database/eurephiadb_driver.h | 4 +- database/sqlite/edb-sqlite.c | 96 +++++++++++++++++++++++++++++------------- database/sqlite/sql-schema.sql | 8 +++- eurephiadm/commands.h | 33 +++++++++++---- eurephiadm/eurephiadm.c | 10 ++--- 5 files changed, 105 insertions(+), 46 deletions(-) diff --git a/database/eurephiadb_driver.h b/database/eurephiadb_driver.h index 00c2ba4..e59f2ba 100644 --- a/database/eurephiadb_driver.h +++ b/database/eurephiadb_driver.h @@ -86,8 +86,8 @@ int (*eDBstore_session_value) (eurephiaCTX *ctx, eurephiaSESSION *skey, int mode const char *key, const char *val); /* API version 2 functions */ -int (*eDBadminAuth) (eurephiaCTX *ctx, const char *uname, const char *pwd); -int (*eDBadminValidateSession) (eurephiaCTX *ctx, const char *sesskey); +int (*eDBadminAuth) (eurephiaCTX *ctx, const char *req_acc, const char *uname, const char *pwd); +int (*eDBadminValidateSession) (eurephiaCTX *ctx, const char *sesskey, const char *req_acc); int (*eDBadminRegisterLogin) (eurephiaCTX *ctx, eurephiaSESSION *session); int (*eDBadminLogout) (eurephiaCTX *ctx, eurephiaSESSION *session); diff --git a/database/sqlite/edb-sqlite.c b/database/sqlite/edb-sqlite.c index 4227234..220d9f7 100644 --- a/database/sqlite/edb-sqlite.c +++ b/database/sqlite/edb-sqlite.c @@ -931,16 +931,23 @@ eurephiaVALUES *eDBget_blacklisted_ip(eurephiaCTX *ctx) { */ // Authenticate admin user against user database -int eDBadminAuth(eurephiaCTX *ctx, const char *uname, const char *pwd) { +int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, const char *pwd) { dbresult *res = NULL; char *crpwd = NULL; char *activated = NULL, *deactivated = NULL, *blid = NULL; - int uid = -1, admacc = 0, pwok = 0; + int uid = -1, pwok = 0; + char interface, *access = NULL; assert(ctx != NULL); - if( (ctx->context_type != ECTX_ADMIN_CONSOLE) - && (ctx->context_type != ECTX_ADMIN_WEB) ) { + 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; } @@ -957,7 +964,7 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *uname, const char *pwd) { assert(crpwd != NULL); res = sqlite_query(ctx, "SELECT activated, deactivated, bl.blid, " - " (password = '%q') AS pwok, acc_admin, uid" + " (password = '%q') AS pwok, uid " " FROM openvpn_users ou" " LEFT JOIN openvpn_blacklist bl USING (username)" " WHERE ou.username = '%q'", @@ -965,7 +972,7 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *uname, const char *pwd) { memset(crpwd, 0, strlen_nullsafe(crpwd)); free_nullsafe(crpwd); - if( !res ) { + if( res == NULL ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not authenticate user against the database"); return 0; } @@ -975,8 +982,8 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *uname, const char *pwd) { deactivated = sqlite_get_value(res, 0, 1); blid = sqlite_get_value(res, 0, 2); pwok = atoi_nullsafe(sqlite_get_value(res, 0, 3)); - admacc = atoi_nullsafe(sqlite_get_value(res, 0, 4)); - uid = atoi_nullsafe(sqlite_get_value(res, 0, 5)); + uid = atoi_nullsafe(sqlite_get_value(res, 0, 4)); + sqlite_free_results(res); if( blid != NULL ) { eurephia_log(ctx, LOG_WARNING, 0, @@ -997,57 +1004,83 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *uname, const char *pwd) { return 0; } - if( admacc != 1 ) { - eurephia_log(ctx, LOG_WARNING, 0, "Your user account is lacking privileges"); + if( pwok != 1 ) { + eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed,"); sqlite_free_results(res); return 0; } - if( pwok != 1 ) { - eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed,"); - 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. Too many records found."); + eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed. No unique records found."); sqlite_free_results(res); return 0; } - sqlite_free_results(res); // If we reach this place, authentication was successful. Return users uid return uid; } -int eDBadminValidateSession(eurephiaCTX *ctx, char *sesskey) { +int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *req_access) { dbresult *res = NULL; - int valid = 0; + int valid = 0, access = 0, expire_time = 0; + char interface; assert( (ctx != NULL) && (sesskey != NULL) ); - if( (ctx->context_type != ECTX_ADMIN_CONSOLE) - && (ctx->context_type != ECTX_ADMIN_WEB) ) { + 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. + // 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" + "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'", - (60 * atoi_nullsafe(defaultValue(eGet_value(ctx->dbc->config, - "eurephiadmin_autologout"), - "10") - )), - sesskey); + " AND sessionkey = '%q'" + " AND access = '%q'", + expire_time, sesskey, req_access); + if( (res == NULL) || (sqlite_get_numtuples(res) != 1) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not validate session"); return 0; } - valid = (atoi_nullsafe(sqlite_get_value(res, 0, 0)) == 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 @@ -1060,6 +1093,10 @@ int eDBadminValidateSession(eurephiaCTX *ctx, char *sesskey) { eurephia_log(ctx, LOG_ERROR, 0, "Could not register session activity"); } sqlite_free_results(res); + + if( !access ) { + eurephia_log(ctx, LOG_WARNING, 0, "Your user account is lacking privileges"); + } } else { // If not valid, register session as auto-logged out res = sqlite_query(ctx, @@ -1081,8 +1118,7 @@ int eDBadminValidateSession(eurephiaCTX *ctx, char *sesskey) { } sqlite_free_results(res); } - - return valid; + return (valid && access); } int eDBadminRegisterLogin(eurephiaCTX *ctx, eurephiaSESSION *session) { diff --git a/database/sqlite/sql-schema.sql b/database/sqlite/sql-schema.sql index 7fb6769..7f0d1af 100644 --- a/database/sqlite/sql-schema.sql +++ b/database/sqlite/sql-schema.sql @@ -15,7 +15,6 @@ CREATE TABLE openvpn_users ( activated timestamp , deactivated timestamp , last_accessed timestamp , - acc_admin boolean , uid integer PRIMARY KEY AUTOINCREMENT ); CREATE UNIQUE INDEX openvpn_users_uname ON openvpn_users(username); @@ -128,3 +127,10 @@ CREATE TABLE eurephia_adminlog ( CREATE INDEX eurephia_adminlog_uid ON eurephia_adminlog(uid); CREATE INDEX eurephia_adminlog_sesskey ON eurephia_adminlog(sessionkey); +CREATE TABLE eurephia_adminaccess ( + uid integer NOT NULL, + interface char NOT NULL, -- C-onsole, W-eb + access varchar(64) NOT NULL +); +CREATE INDEX eurephia_adminacc_uid ON eurephia_adminaccess (uid); +CREATE INDEX eurephia_adminacc_uid_intf ON eurephia_adminaccess (uid,interface); diff --git a/eurephiadm/commands.h b/eurephiadm/commands.h index 242a5c8..3b78710 100644 --- a/eurephiadm/commands.h +++ b/eurephiadm/commands.h @@ -27,6 +27,7 @@ typedef struct { char *command; int need_session; + char *accesslvl; char *arghint; char *helpinfo; char *helpdescr; @@ -46,14 +47,30 @@ int cmd_EditConfig(eurephiaCTX *, eurephiaSESSION *, eurephiaVALUES *cfg, int ar /* Declaration of all commands */ static const eurephiadm_functions cmdline_functions[] = { - // command, need_session, arghints, helpinfo, helpdescr, function - {"help", 0, NULL, "This help screen", NULL, cmd_Help}, - {"logout", 1, NULL, "Logout from an open session", NULL, cmd_Logout}, - {"listusers", 1, NULL, "List all registered users", NULL, cmd_ListUsers}, - {"show-config", 1, NULL, "List all config settings", NULL, cmd_ShowCfg}, - {"show-configfile", 0, NULL, "List only config file settings", NULL, cmd_ShowCfg}, - {"config", 1, "[-s|-d] ", "Add, delete or show one config setting", NULL, cmd_EditConfig}, - {NULL, 0, NULL, NULL, NULL, NULL} + // {command, need_session, acclvl, arghints, + // helpinfo, helpdescr, function} + + {"help", 0, NULL, NULL, + "This help screen", NULL, cmd_Help}, + + {"logout", 1, "login", NULL, + "Logout from an open session", NULL, cmd_Logout}, + + {"listusers", 1, "useradmin", NULL, + "List all registered users", NULL, cmd_ListUsers}, + + {"show-config", 1, "config", NULL, + "List all config settings", NULL, cmd_ShowCfg}, + + {"show-configfile", 0, NULL, NULL, + "List only config file settings", NULL, cmd_ShowCfg}, + + {"config", 1, "config", "[-s|-d] ", + "Add, delete or show one config setting", NULL, cmd_EditConfig}, + + // End of records marker + {NULL, 0, NULL, NULL, + NULL, NULL, NULL} }; #endif /* !COMMANDS_H_ */ diff --git a/eurephiadm/eurephiadm.c b/eurephiadm/eurephiadm.c index 8eac0a6..3d9d71c 100644 --- a/eurephiadm/eurephiadm.c +++ b/eurephiadm/eurephiadm.c @@ -147,7 +147,7 @@ int eurephia_ConnectDB(eurephiaCTX *ctx, const char *argstr) { return 1; } -eurephiaSESSION *do_login(eurephiaCTX *ctx) { +eurephiaSESSION *do_login(eurephiaCTX *ctx, const char *req_access) { eurephiaSESSION *session = NULL; char username[33], password[33]; int uid = 0; @@ -157,7 +157,7 @@ eurephiaSESSION *do_login(eurephiaCTX *ctx) { get_console_input(username, 32, "User:", 0); get_console_input(password, 32, "Password:", 1); - if( (uid = eDBadminAuth(ctx, username, password)) < 1 ) { + if( (uid = eDBadminAuth(ctx, req_access, username, password)) < 1 ) { // Register failure memset(username, 0, 33); memset(password, 0, 33); @@ -312,10 +312,10 @@ int main(int argc, char **argv) { rc = 0; goto exit; } - session = do_login(ctx); + session = do_login(ctx, call_fnc->accesslvl); } else { // Session file found, check if it still is a valid session - if( eDBadminValidateSession(ctx, sesskey_file) ) {; + if( eDBadminValidateSession(ctx, sesskey_file, call_fnc->accesslvl) ) {; // If valid, load this session session = create_session(ctx, sesskey_file); } else { @@ -326,7 +326,7 @@ int main(int argc, char **argv) { rc = 0; goto exit; } - session = do_login(ctx); + session = do_login(ctx, call_fnc->accesslvl); } } free_nullsafe(sesskey_file); -- cgit