diff options
Diffstat (limited to 'database/sqlite/administration/authentication.c')
-rw-r--r-- | database/sqlite/administration/authentication.c | 254 |
1 files changed, 194 insertions, 60 deletions
diff --git a/database/sqlite/administration/authentication.c b/database/sqlite/administration/authentication.c index e8a30f0..75ad991 100644 --- a/database/sqlite/administration/authentication.c +++ b/database/sqlite/administration/authentication.c @@ -20,12 +20,11 @@ */ /** - * @file administration.c + * @file authentication.c * @author David Sommerseth <dazo@users.sourceforge.net> * @date 2008-12-03 * - * @brief Functions needed for the administration interface. This file - * primarily takes care of user authentication via the administration API + * @brief Functions used for authentication of administration sessions. * */ @@ -69,17 +68,30 @@ * */ + /** - * @copydoc eDBadminAuth() + * Authenticate a user for the administration interface. This interface do not + * require any certificate validation and is intended for administration utilities + * for eurephia. The eurephia context type must be either ECTX_ADMIN_CONSOLE or + * ECTX_ADMIN_WEB. + * + * @param ctx eurephiaCTX - context used for administration task + * @param req_access String containing the requested administration access level + * @param uname username of the user being authenticated + * @param pwd password from the user + * + * @return Returns an eurephia ResultMsg XML document with the result. On fatal errors, NULL is returned */ -int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, const char *pwd) { +static xmlDoc *auth_user(eurephiaCTX *ctx, const char *req_access, const char *uname, const char *pwd) { + xmlDoc *res_d = NULL; + xmlNode *info_n = NULL; dbresult *res = NULL; char *crpwd = NULL, *dbpwd = NULL; - char *activated = NULL, *deactivated = NULL, *blid = NULL; - int uid = -1, access = 0; + char *activated = NULL, *deactivated = NULL, *blid = NULL, *uid = NULL; + int access = 0; char interface; - DEBUG(ctx, 20, "Function call: eDBadminAuth(ctx, '%s, '%s', 'xxxxxxxx')", req_access, uname); + DEBUG(ctx, 21, "Function call: auth_user(ctx, '%s, '%s', 'xxxxxxxx')", req_access, uname); assert(ctx != NULL); @@ -92,12 +104,13 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, co break; default: eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type); - return 0; + return NULL; } 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; + eurephia_log(ctx, LOG_WARNING, 0, + "Username and/or password is either null or less than 4 bytes"); + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Username or password is too short"); } // @@ -113,7 +126,7 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, co if( res == NULL ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not authenticate user against the database"); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } if( sqlite_get_numtuples(res) == 1 ) { @@ -121,31 +134,31 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, co 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)); + uid = strdup_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."); + "User account '%s' is BLACKLISTED. You have no access.", uname); sqlite_free_results(res); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } if( activated == NULL ) { - eurephia_log(ctx, LOG_WARNING, 0, "Your user account is not yet activated."); + eurephia_log(ctx, LOG_WARNING, 0, "User account '%s' is not yet activated.", uname); sqlite_free_results(res); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } if( deactivated != NULL ) { - eurephia_log(ctx, LOG_WARNING, 0, "Your user account is deactivated."); + eurephia_log(ctx, LOG_WARNING, 0, "User account '%s' is deactivated.", uname); sqlite_free_results(res); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } if( dbpwd == NULL ) { eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed. DB error."); sqlite_free_results(res); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } else { int pwdok = 0; // Verify the password @@ -158,7 +171,7 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, co eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed."); sleep(2); sqlite_free_results(res); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } } sqlite_free_results(res); @@ -169,40 +182,56 @@ int eDBadminAuth(eurephiaCTX *ctx, const char *req_access, const char *uname, co res = sqlite_query(ctx, "SELECT (count(*) = 1) AS access " " FROM eurephia_adminaccess" - " WHERE uid = '%i' AND interface = '%c' AND access = '%q'", + " WHERE uid = '%q' 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; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL,"Failed to validate access level"); } 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; + eurephia_log(ctx, LOG_WARNING, 0, + "User account '%s' is lacking privileges for this operation", uname); + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } } else { eurephia_log(ctx, LOG_WARNING, 0, "Authentication failed. No unique records found."); sqlite_free_results(res); sleep(2); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Authentication failed"); } // If we reach this place, authentication was successful. Return users uid - return uid; + info_n = xmlNewNode(NULL, (xmlChar *) "UserAccount"); + assert( info_n != NULL ); + xmlNewProp(info_n, (xmlChar *) "uid", (xmlChar *) uid); + res_d = eurephiaXML_ResultMsg(ctx, exmlRESULT, info_n, "Successful authentication"); + xmlFreeNode(info_n); + free_nullsafe(ctx, uid); + return res_d; } /** - * @copydoc eDBadminValidateSession() + * Validates a session key, to see if it still is valid (not auto-logged out or invalid session key) + * and to check if they have access to a different access level. The eurephia context type must be + * either ECTX_ADMIN_CONSOLE or ECTX_ADMIN_WEB. + * + * @param ctx eurephiaCTX + * @param sesskey String containing the session key to validate + * @param req_access String containing the required administration access level + * + * @return Returns an eurephia ResultMsg XML document with the result. On fatal errors, NULL is returned */ -int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *req_access) { +static xmlDoc *auth_session(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); + DEBUG(ctx, 21, "Function call: auth_session(ctx, '%s, '%s')", sesskey, req_access); assert( (ctx != NULL) && (sesskey != NULL) ); switch( ctx->context_type ) { @@ -214,12 +243,13 @@ int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *r break; default: eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type); - return 0; + return NULL; } // 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"), + expire_time = (60 * atoi_nullsafe(defaultValue(eGet_value(ctx->dbc->config, + "eurephiadmin_autologout"), "10") ) ); @@ -236,7 +266,7 @@ int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *r if( (res == NULL) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not validate session"); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Session authentication failed"); } valid = (atoi_nullsafe(sqlite_get_value(res, 0, 0)) == 0); @@ -256,7 +286,6 @@ int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *r } else { // If not valid, register session as auto-logged out - res = sqlite_query(ctx, "UPDATE eurephia_adminlog" " SET logout = CURRENT_TIMESTAMP, status = %i" @@ -273,29 +302,41 @@ int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *r if( res == NULL ) { eurephia_log(ctx, LOG_ERROR, 0, "Could not delete session variables (%s))", sesskey); - return 0; + } else if( !access ) { + eurephia_log(ctx, LOG_WARNING, 0, "User account is lacking privileges"); } sqlite_free_results(res); + } - if( !access ) { - eurephia_log(ctx, LOG_WARNING, 0, "Your user account is lacking privileges"); - } + if (valid && access) { + return eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, "Session authenticated"); + } else { + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Session authentication failed"); } - return (valid && access); } /** - * @copydoc eDBadminRegisterLogin() + * Registers the user as logged in after a successful authentication. The user must + * be registered as logged in to have a valid session. + * + * @param ctx eurephiaCTX + * @param uid Numeric value if the user ID the session belongs to + * @param sesskey String containing the session key + * + * @return Returns an eurephia ResultMsg XML document with the result. On fatal errors, NULL is returned */ -int eDBadminRegisterLogin(eurephiaCTX *ctx, eurephiaSESSION *session) { +static xmlDoc *register_login(eurephiaCTX *ctx, const int uid, const char *sesskey) { dbresult *res = NULL; char interface; - int uid; - DEBUG(ctx, 20, "Function call: eDBadminRegisterLogin(ctx, {session}'%s')", session->sessionkey); - assert((ctx != NULL) && (session != NULL)); + DEBUG(ctx, 21, "Function call: register_login(ctx, %i, '%s')", uid, sesskey); + assert( ctx != NULL ); + + if( (sesskey == NULL) || (uid < 1) ) { + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Invalid data for login registration"); + } switch( ctx->context_type ) { case ECTX_ADMIN_CONSOLE: @@ -304,38 +345,44 @@ int eDBadminRegisterLogin(eurephiaCTX *ctx, eurephiaSESSION *session) { interface = 'W'; break; default: eurephia_log(ctx, LOG_ERROR, 0, "Wrong eurephia context type (0x%04x)", ctx->context_type); - return 0; + return NULL; } // 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); + uid, interface, sesskey); if( !res ) { - eurephia_log(ctx, LOG_FATAL, 0, "Could not manage to register the session in the database"); - return 0; + eurephia_log(ctx, LOG_FATAL, 0, "Failed to register the session in the database"); + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Failed to register the session in the database"); } sqlite_free_results(res); - return 1; + return eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, "Session is registered as logged in"); } /** - * @copydoc eDBadminLogout() + * Registers a session as logged out. This will require the user to do a new authentication + * on next access via the administration interface + * + * @param ctx eurephiaCTX + * @param sessionkey String containing the session key + * + * @return Returns an eurephia ResultMsg XML document with the result. On fatal errors, NULL is returned */ -int eDBadminLogout(eurephiaCTX *ctx, const char *sessionkey) { +static xmlDoc *register_logout(eurephiaCTX *ctx, const char *sessionkey) { dbresult *res = NULL; - DEBUG(ctx, 20, "Function call: eDBadminLogout(ctx, '%s')", sessionkey); + DEBUG(ctx, 21, "Function call: register_logout(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; + return NULL; } // Update session as logged out @@ -344,21 +391,108 @@ int eDBadminLogout(eurephiaCTX *ctx, const char *sessionkey) { " 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; + if( !res || (sqlite_get_affected_rows(res) == 0) ) { + eurephia_log(ctx, LOG_FATAL, 0, + "Failed to register the session as logged out (updated %i rows)", + sqlite_get_affected_rows(res)); + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Failed to register the session as logged out"); } sqlite_free_results(res); // Delete session variables res = sqlite_query(ctx, "DELETE FROM openvpn_sessions WHERE sessionkey = '%q'", sessionkey); - if( res == NULL ) { + if( !res || (sqlite_get_affected_rows(res) == 0) ) { eurephia_log(ctx, LOG_ERROR, 0, "Could not delete session variables (%s))", sessionkey); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Could not delete session variables (%s))", sessionkey); } sqlite_free_results(res); - return 1; + return eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, "Session is logged out"); +} + + +/** + * @copydoc eDBadminAuthenticate() + */ +xmlDoc *eDBadminAuthenticate(eurephiaCTX *ctx, xmlDoc *qryxml) { + xmlDoc *res_d = NULL; + xmlNode *qry_n = NULL; + char *mode = NULL; + int type = 0; + + DEBUG(ctx, 20, "Function call: eDBadminAuthenticate(ctx, xmlDoc)"); + assert( (ctx != NULL) && (qryxml != 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 NULL; + } + + qry_n = eurephiaXML_getRoot(ctx, qryxml, "Authenticate", 1); + if( qry_n != NULL ) { + type = 1; + goto accept; + } + + qry_n = eurephiaXML_getRoot(ctx, qryxml, "Register", 1); + if( qry_n != NULL ) { + type = 2; + goto accept; + } + + eurephia_log(ctx, LOG_ERROR, 0, "Could not find a valid XML request for eDBadminAuthenticate()"); + return NULL; + + accept: + mode = xmlGetAttrValue(qry_n->properties, "mode"); + if( mode == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, "Invalid authentication request"); + return NULL; + } + + switch( type ) { + case 1: // Authenticate tag + if( strcmp(mode, "user") == 0 ) { + // const char *req_access, const char *uname, const char *pwd + const char *reqacc = NULL, *uname = NULL, *pwd = NULL; + uname = xmlGetNodeContent(qry_n, "username"); + pwd = xmlGetNodeContent(qry_n, "password"); + reqacc = xmlGetNodeContent(qry_n, "accesslevel"); + res_d = auth_user(ctx, reqacc, uname, pwd); + } else if ( strcmp(mode, "session") == 0 ) { + const char *sesskey = NULL, *reqacc = NULL; + sesskey = xmlGetNodeContent(qry_n, "sessionkey"); + reqacc = xmlGetNodeContent(qry_n, "accesslevel"); + res_d = auth_session(ctx, sesskey, reqacc); + } + break; + + case 2: // Register tag + if( strcmp(mode, "login") == 0 ) { + const char *sesskey = NULL; + unsigned int uid = 0; + + uid = atoi_nullsafe(xmlGetAttrValue(qry_n->properties, "uid")); + sesskey = xmlExtractContent(qry_n); + res_d = register_login(ctx, uid, sesskey); + } else if( strcmp(mode, "logout") == 0 ) { + const char *sesskey = NULL; + + sesskey = xmlExtractContent(qry_n); + res_d = register_logout(ctx, sesskey); + } + break; + + default: + eurephia_log(ctx, LOG_FATAL, 0, "The unthinkable has just happened (type %i)", type); + res_d = NULL; + break; + } + return res_d; } + #endif |