diff options
Diffstat (limited to 'database')
-rw-r--r-- | database/eurephiadb_driver.h | 4 | ||||
-rw-r--r-- | database/sqlite/edb-sqlite.c | 96 | ||||
-rw-r--r-- | database/sqlite/sql-schema.sql | 8 |
3 files changed, 75 insertions, 33 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); |