diff options
-rw-r--r-- | database/eurephiadb.c | 7 | ||||
-rw-r--r-- | database/eurephiadb_driver.h | 88 | ||||
-rw-r--r-- | database/sqlite/administration/authentication.c | 254 | ||||
-rw-r--r-- | eurephiadm/eurephiadm.c | 147 |
4 files changed, 362 insertions, 134 deletions
diff --git a/database/eurephiadb.c b/database/eurephiadb.c index 7fcdfae..05187af 100644 --- a/database/eurephiadb.c +++ b/database/eurephiadb.c @@ -108,12 +108,7 @@ int eDBlink_init(eurephiaCTX *ctx, const char *dbdriver, const int minver) "to upgrade eurephia to take advantage of newer features in the eurephiaDB driver."); case 2: #ifdef ENABLE_EUREPHIADM - eDBadminAuth = eGetSym(ctx, ctx->eurephia_driver, "eDBadminAuth"); - eDBadminValidateSession = eGetSym(ctx, ctx->eurephia_driver, - "eDBadminValidateSession"); - eDBadminRegisterLogin = eGetSym(ctx, ctx->eurephia_driver, "eDBadminRegisterLogin"); - eDBadminLogout = eGetSym(ctx, ctx->eurephia_driver, "eDBadminLogout"); - + eDBadminAuthenticate = eGetSym(ctx, ctx->eurephia_driver, "eDBadminAuthenticate"); eDBadminConfiguration = eGetSym(ctx, ctx->eurephia_driver, "eDBadminConfiguration"); eDBadminUserAccount = eGetSym(ctx, ctx->eurephia_driver, "eDBadminUserAccount"); eDBadminCertificate = eGetSym(ctx, ctx->eurephia_driver, "eDBadminCertificate"); diff --git a/database/eurephiadb_driver.h b/database/eurephiadb_driver.h index 2c8d3b5..ababa06 100644 --- a/database/eurephiadb_driver.h +++ b/database/eurephiadb_driver.h @@ -354,66 +354,58 @@ int (*eDBstore_session_value)(eurephiaCTX *ctx, eurephiaSESSION *session, int mo /* * functions which needs to exists in the API level 2 */ +#ifdef HAVE_LIBXML2 /** - * 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. + * Authenticate users and sessions for the administration interface. The OpenVPN plug-in + * should never use this API. * * @version API version level 2 - * @param ctx eurephiaCTX - context used for administration task - * @param req_access String (char *) containing the requested administration access level - * @param uname username of the user being authenticated - * @param pwd password from the user - * - * @return Returns users ID (uid) on success, otherwise 0 - */ -int (*eDBadminAuth) (eurephiaCTX *ctx, const char *req_access, const char *uname, const char *pwd); - - -/** - * 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 qryxml eurephia XML document describing the operation to be done * - * @version API version level 2 - * @param ctx eurephiaCTX - * @param sesskey String (char *) containing the session key to validate - * @param req_access String (char *) containing the required administration access level + * XML document describing authentication of a user account + * @code + * <eurephia format="1"> + * <Authenticate mode="user"> + * <username>{username}</username> + * <password>{password}</password> + * <accesslevel>{accesslevel}</password> + * </Authenticate> + * </eurephia> + * @endcode * - * @return Returns 1 if the session is valid and the user have the needed privileges, - * otherwise 0 is returned. - */ -int (*eDBadminValidateSession) (eurephiaCTX *ctx, const char *sesskey, const char *req_access); - - -/** - * Registers the user as logged in after a successful authentication. The user must - * be registered as logged in to have a valid session. + * XML document for authenticating and validating a user session to a specific access level + * @code + * <eurephia format="1"> + * <Authenticate mode="session"> + * <sessionkey>{session key}</sessionkey> + * <accesslevel>{accesslevel}</password> + * </Authenticate> + * </eurephia> + * @endcode * - * @version API version level 2 - * @param ctx eurephiaCTX - * @param session eurephiaSESSION + * XML docuument to register the user as logged in + * @code + * <eurephia format="1"> + * <Register mode="login" uid="{uid}">{session key}</Register> + * </eurephia> + * @endcode * - * @return Returns 1 on success, otherwise 0 - */ -int (*eDBadminRegisterLogin) (eurephiaCTX *ctx, eurephiaSESSION *session); - - -/** - * Registers a session as logged out. This will require the user to do a new authentication - * on next access via the administration interface + * XML docuument to register the user as logged out + * @code + * <eurephia format="1"> + * <Register mode="logout">{session key}</Register> + * </eurephia> + * @endcode * - * @version API version level 2 - * @param ctx eurephiaCTX - * @param sessionkey String (char *) containing the session key + * @return Returns a valid eurephia ResultMsg XML document with the result. On fatal errors, + * NULL is returned. When a username/password authentication is done, the user id of the + * user will be returned in the details part of the ResultMsg. * - * @return Returns 1 on success, otherwise 0 */ -int (*eDBadminLogout) (eurephiaCTX *ctx, const char *sessionkey); +xmlDoc *(*eDBadminAuthenticate) (eurephiaCTX *ctx, xmlDoc *qryxml); -#ifdef HAVE_LIBXML2 /** * Set or delete configuration parameters in the database. This operation will * also update the in-memory copy of the configuration 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 diff --git a/eurephiadm/eurephiadm.c b/eurephiadm/eurephiadm.c index 518f8a5..203b7e2 100644 --- a/eurephiadm/eurephiadm.c +++ b/eurephiadm/eurephiadm.c @@ -35,10 +35,13 @@ #include <assert.h> #include <libgen.h> +#include <libxml/tree.h> + #include <eurephia_nullsafe.h> #include <eurephia_context.h> #include <eurephia_log.h> #include <eurephia_values.h> +#include <eurephia_xml.h> #include <eurephiadb_driver.h> #include <eurephiadb_session_common.h> #include <eurephiadb.h> @@ -153,10 +156,34 @@ int cmd_Help(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int a * @return returns 0 on success, otherwise 1. */ int cmd_Logout(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { + xmlDoc *logoutxml = NULL, *resxml = NULL; + xmlNode *logout_n = NULL; + eurephiaRESULT *res = NULL; int rc = 0; - rc = eDBadminLogout(ctx, argv[0]); - fprintf(stdout, "%s\n", (rc == 1 ? "Logged out successfully" : "Logout failed.")); - return (rc == 0); + + eurephiaXML_CreateDoc(ctx, 1, "Register", &logoutxml, &logout_n); + assert( (logoutxml != NULL) && (logout_n != NULL) ); + xmlNewProp(logout_n, (xmlChar *) "mode", (xmlChar *) "logout"); + xmlAddChild(logout_n, xmlNewText((xmlChar *) argv[0])); // A dirty hack, but the sesskey is here + + resxml = eDBadminAuthenticate(ctx, logoutxml); + xmlFreeDoc(logoutxml); + if( !eurephiaXML_IsResultMsg(ctx, resxml) ) { + eurephia_log(ctx, LOG_FATAL, 0, "Failed to logout session"); + rc = 1; + } else { + res = eurephiaXML_ParseResultMsg(ctx, resxml); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + rc = 1; + } else { + fprintf(stdout, "%s: %s\n", MODULE, res->message); + rc = 0; + } + } + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); + return rc; } @@ -248,10 +275,12 @@ int eurephia_ConnectDB(eurephiaCTX *ctx, const char *argstr) { * * @return Returns a eurephiaSESSION pointer to the authenticated user session on success, otherwise NULL. */ -eurephiaSESSION *do_login(eurephiaCTX *ctx, eurephiaVALUES *cfg, const char *req_access) { +static eurephiaSESSION *do_login(eurephiaCTX *ctx, eurephiaVALUES *cfg, const char *req_access) { + xmlDoc *loginxml = NULL, *resxml = NULL; + xmlNode *login_n = NULL; + eurephiaRESULT *res = NULL; eurephiaSESSION *session = NULL; char username[33], password[33], *tmp = NULL; - int uid = 0; memset(&username, 0, 33); memset(&password, 0, 33); @@ -263,17 +292,36 @@ eurephiaSESSION *do_login(eurephiaCTX *ctx, eurephiaVALUES *cfg, const char *req } get_console_input(password, 32, "Password:", 1); - if( (uid = eDBadminAuth(ctx, req_access, username, password)) < 1 ) { - // Register failure - memset(username, 0, 33); - memset(password, 0, 33); - return NULL; - } + eurephiaXML_CreateDoc(ctx, 1, "Authenticate", &loginxml, &login_n); + assert( (loginxml != NULL) && (login_n != NULL) ); + xmlNewProp(login_n, (xmlChar *) "mode", (xmlChar *) "user"); + + xmlNewChild(login_n, NULL, (xmlChar *) "username", (xmlChar *) username); + xmlNewChild(login_n, NULL, (xmlChar *) "password", (xmlChar *) password); + xmlNewChild(login_n, NULL, (xmlChar *) "accesslevel", (xmlChar *) req_access); + resxml = eDBadminAuthenticate(ctx, loginxml); + xmlFreeDoc(loginxml); memset(username, 0, 33); memset(password, 0, 33); + if( !eurephiaXML_IsResultMsg(ctx, resxml) ) { + return NULL; + } + + res = eurephiaXML_ParseResultMsg(ctx, resxml); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + free_nullsafe(ctx, res); + xmlFreeDoc(resxml); + return NULL; + } session = create_session(ctx, NULL); - snprintf(username, 30, "%i", uid); // Borrow username for converting uid to a string + login_n = xmlFindNode(res->details, "UserAccount"); + + // Borrow username for converting uid to a string + snprintf(username, 30, "%s", xmlGetAttrValue(login_n->properties, "uid")); + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); if( !eDBset_session_value(ctx, session, "uid", username) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not update session variables (uid)"); @@ -281,17 +329,82 @@ eurephiaSESSION *do_login(eurephiaCTX *ctx, eurephiaVALUES *cfg, const char *req return NULL; }; - if( !eDBadminRegisterLogin(ctx, session) ) { + + // Register the session as logged in + eurephiaXML_CreateDoc(ctx, 1, "Register", &loginxml, &login_n); + assert( (loginxml != NULL) && (login_n != NULL) ); + xmlNewProp(login_n, (xmlChar *) "mode", (xmlChar *) "login"); + xmlNewProp(login_n, (xmlChar *) "uid", (xmlChar *) username); + xmlAddChild(login_n, xmlNewText((xmlChar *) session->sessionkey)); + + resxml = eDBadminAuthenticate(ctx, loginxml); + xmlFreeDoc(loginxml); + if( !eurephiaXML_IsResultMsg(ctx, resxml) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not register login"); eDBfree_session(ctx, session); + xmlFreeDoc(resxml); + return NULL; + } + + res = eurephiaXML_ParseResultMsg(ctx, resxml); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + free_nullsafe(ctx, res); + xmlFreeDoc(resxml); + eDBfree_session(ctx, session); return NULL; } + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); return session; } /** + * Validates an exisiting session key against a requested access level + * + * @param ctx eurephiaCTX + * @param sesskey String containing the session key + * @param accesslvl String containing the requested access level + * + * @return Returns 1 if session is valid and access level is granted to the session, otherwise 0 + */ +static int validate_session(eurephiaCTX *ctx, const char *sesskey, const char *accesslvl) { + xmlDoc *sessxml = NULL, *resxml = NULL; + xmlNode *sess_n = NULL; + int ret = 0; + + eurephiaXML_CreateDoc(ctx, 1, "Authenticate", &sessxml, &sess_n); + assert( (sessxml != NULL) && (sess_n != NULL) ); + xmlNewProp(sess_n, (xmlChar *) "mode", (xmlChar *) "session"); + + xmlNewChild(sess_n, NULL, (xmlChar *) "sessionkey", (xmlChar *) sesskey); + xmlNewChild(sess_n, NULL, (xmlChar *) "accesslevel", (xmlChar *) accesslvl); + + resxml = eDBadminAuthenticate(ctx, sessxml); + xmlFreeDoc(sessxml); + if( !eurephiaXML_IsResultMsg(ctx, resxml) ) { + ret = 0; + } else { + eurephiaRESULT *res = NULL; + + res = eurephiaXML_ParseResultMsg(ctx, resxml); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + ret = 0; + } else { + ret = 1; + } + free_nullsafe(ctx, res); + } + if( resxml ) { + xmlFreeDoc(resxml); + } + return ret; +} + +/** * Converts a argument table (char **) into a space separated string (char *) * * @param argc argument counter @@ -458,9 +571,6 @@ int main(int argc, char **argv) { goto exit; } session = do_login(ctx, cfg, call_fnc->accesslvl); - if( session == NULL ) { - fprintf(stderr, "Login failed\n"); - } } else { // If we are logging out, do so here - without checking the session if( strcmp(call_fnc->command, "logout") == 0) { @@ -472,16 +582,13 @@ int main(int argc, char **argv) { } // Session file found, check if it still is a valid session - if( eDBadminValidateSession(ctx, sesskey_file, call_fnc->accesslvl) ) {; + if( validate_session(ctx, sesskey_file, call_fnc->accesslvl) ) {; // If valid, load this session session = create_session(ctx, sesskey_file); } else { // If not valid, remove session file and go to login remove_session_file(ctx); session = do_login(ctx, cfg, call_fnc->accesslvl); - if( session == NULL ) { - fprintf(stderr, "Login failed\n"); - } } } free_nullsafe(ctx, sesskey_file); |