diff options
25 files changed, 1032 insertions, 660 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f22271..ee53ad4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ PROJECT(eurephia C) cmake_minimum_required(VERSION 2.6) # Set the eurephia version -ADD_DEFINITIONS(-DEUREPHIAVERSION="0.9.4_beta") +ADD_DEFINITIONS(-DEUREPHIAVERSION="0.9.5_beta") # eurephia parameters - boolean values OPTION(DEBUG "Add more verbose debug information" OFF) @@ -43,7 +43,7 @@ SET(XSLTROOT "/usr/local/share/eurephia/xslt" CACHE STRING "Root path for the XS SET(CMAKE_INSTALL_PREFIX ${PREFIX}) # Default C compiler flags -SET(CMAKE_C_FLAGS "-fno-delete-null-pointer-checks -g -Wall") +SET(CMAKE_C_FLAGS "-fno-delete-null-pointer-checks -g -Wall -Wpointer-arith") IF(GCOV) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") ENDIF(GCOV) diff --git a/common/certinfo.c b/common/certinfo.c index 1a7d532..f63b783 100644 --- a/common/certinfo.c +++ b/common/certinfo.c @@ -61,7 +61,7 @@ certinfo *parse_tlsid(const char *input) { return NULL; ret = (certinfo *) malloc_nullsafe(NULL, sizeof(certinfo)+2); - bzero(&tmp, 130); + memset(&tmp, 0, 130); mainp = strdup(input); origptr = mainp; diff --git a/common/eurephia_nullsafe.c b/common/eurephia_nullsafe.c index f70b463..5f507c3 100644 --- a/common/eurephia_nullsafe.c +++ b/common/eurephia_nullsafe.c @@ -38,6 +38,12 @@ #include <eurephia_context.h> #include <eurephia_log.h> +#if __GNUC__ >= 3 +#define __malloc__ __attribute__((malloc)) +#else /* If not GCC 3 or newer, disable optimisations */ +#define __malloc__ +#endif + /** * Internal function, should be called via the malloc_nullsafe() macro. * This replaces the use of malloc() and memset(). This function uses calloc @@ -51,7 +57,7 @@ * * @return Returns a void pointer to the memory region on success, otherwise NULL */ -void *__malloc_nullsafe(eurephiaCTX *ctx, size_t sz, const char *file, int line) { +__malloc__ void *_malloc_nullsafe(eurephiaCTX *ctx, size_t sz, const char *file, int line) { void *buf = NULL; buf = calloc(1, sz); /* Using calloc, also gives a zero'd memory region */ @@ -88,7 +94,7 @@ void *__malloc_nullsafe(eurephiaCTX *ctx, size_t sz, const char *file, int line) * @param line debug info, which line in the file * */ -void inline __free_nullsafe(eurephiaCTX *ctx, void *ptr, const char *file, int line) { +void inline _free_nullsafe(eurephiaCTX *ctx, void *ptr, const char *file, int line) { if( ptr == NULL ) { return; } diff --git a/common/eurephia_nullsafe.h b/common/eurephia_nullsafe.h index 5f6b58c..5249c19 100644 --- a/common/eurephia_nullsafe.h +++ b/common/eurephia_nullsafe.h @@ -59,6 +59,17 @@ /** + * Wrapper macro, which appends a string to a destination string without exceeding the size + * of the destination buffer. + * + * @param dest Pointer to the destination buffer + * @param src Pointer to the value being concatenated to the destination string. + * @param size Size of the destination buffer + */ +#define append_str(dest, src, size) strncat(dest, src, (size - strlen_nullsafe(dest))) + + +/** * strlen() wrapper. Returns the length of a string * * @param str Input string @@ -69,10 +80,10 @@ -void *__malloc_nullsafe(eurephiaCTX *, size_t, const char *, int); +void *_malloc_nullsafe(eurephiaCTX *, size_t, const char *, int); /** - * Front-end macro for the __malloc_nullsafe() function. + * Front-end macro for the _malloc_nullsafe() function. * * @param ctx eurephiaCTX (used for debugg logging) * @param sz Size of the memory region wanted @@ -80,19 +91,19 @@ void *__malloc_nullsafe(eurephiaCTX *, size_t, const char *, int); * @return Returns a pointer to the memory region on success, otherwise NULL. * */ -#define malloc_nullsafe(ctx, sz) __malloc_nullsafe(ctx, sz, __FILE__, __LINE__) +#define malloc_nullsafe(ctx, sz) _malloc_nullsafe(ctx, sz, __FILE__, __LINE__) -void inline __free_nullsafe(eurephiaCTX *ctx, void *ptr, const char *file, int line); +void inline _free_nullsafe(eurephiaCTX *ctx, void *ptr, const char *file, int line); /** - * Front-end macro for the __free_nullsafe() function. + * Front-end macro for the __ree_nullsafe() function. * * @param ctx eurephiaCTX (used for debugg logging) * @param ptr Pointer to the memory region being freed. * */ -#define free_nullsafe(ctx, ptr) { __free_nullsafe(ctx, ptr, __FILE__, __LINE__); ptr = NULL; } +#define free_nullsafe(ctx, ptr) { _free_nullsafe(ctx, ptr, __FILE__, __LINE__); ptr = NULL; } /** diff --git a/common/eurephia_xml.c b/common/eurephia_xml.c index 91eacf4..dec397f 100644 --- a/common/eurephia_xml.c +++ b/common/eurephia_xml.c @@ -43,6 +43,27 @@ /** + * String replace in a xmlChar based string + * + * @param str xmlChar input string + * @param s search for this character + * @param r replace the character with this one + */ +void xmlReplaceChars(xmlChar *str, char s, char r) { + if( str != NULL ) { + xmlChar *ptr = str; + + while( *ptr != '\0' ) { + if( *ptr == s ) { + *ptr = r; + } + ptr++; + } + } +} + + +/** * Retrieves a given XML node attribute/property * * @param attr xmlAttr pointer from an xmlNode pointer. @@ -81,7 +102,7 @@ xmlNode *xmlFindNode(xmlNode *node, const char *key) { xmlNode *nptr = NULL; xmlChar *x_key = NULL; - if( node->children == NULL ) { + if( (node == NULL) || (node->children == NULL) ) { return NULL; } @@ -236,6 +257,25 @@ xmlNode *eurephiaXML_getRoot(eurephiaCTX *ctx, xmlDoc *doc, const char *nodeset, /** + * Checks if the given XML document is an eurephia ResultMsg XML document + * + * @param ctx eurephiaCTX + * @param resxml XML document to validate + * + * @return Returns 1 if the input XML document is a ResultMsg document. Otherwise 0 + */ +unsigned int eurephiaXML_IsResultMsg(eurephiaCTX *ctx, xmlDoc *resxml) { + xmlNode *node = NULL; + + assert( ctx != NULL ); + if( resxml == NULL ) { + return 0; + } + node = eurephiaXML_getRoot(ctx, resxml, "Result", 1); + return (node != NULL ? 1 : 0); +} + +/** * Parses an eurephia Result XML document * * @param ctx eurephiaCTX @@ -253,7 +293,10 @@ eurephiaRESULT *eurephiaXML_ParseResultMsg(eurephiaCTX *ctx, xmlDoc *resxml) { xmlNode *res_n = NULL; char *str = NULL; - assert( (ctx != NULL) && (resxml != NULL) ); + assert( ctx != NULL ); + if( resxml == NULL ) { + return NULL; + } res_n = eurephiaXML_getRoot(ctx, resxml, "Result", 1); if( res_n == NULL) { diff --git a/common/eurephia_xml.h b/common/eurephia_xml.h index 614394a..083a881 100644 --- a/common/eurephia_xml.h +++ b/common/eurephia_xml.h @@ -62,6 +62,8 @@ typedef struct _eurephiaRESULT { */ #define foreach_xmlnode(start, itn) for( itn = start; itn != NULL; itn = itn->next ) +void xmlReplaceChars(xmlChar *str, char s, char r); + char *xmlGetAttrValue(xmlAttr *properties, const char *key); xmlNode *xmlFindNode(xmlNode *node, const char *key); @@ -69,6 +71,7 @@ int eurephiaXML_CreateDoc(eurephiaCTX *ctx, int format, const char *rootname, xm xmlNode *eurephiaXML_getRoot(eurephiaCTX *ctx, xmlDoc *doc, const char *nodeset, int min_format); xmlDoc *eurephiaXML_ResultMsg(eurephiaCTX *ctx, exmlResultType type, xmlNode *info_n, const char *fmt, ... ); +unsigned int eurephiaXML_IsResultMsg(eurephiaCTX *ctx, xmlDoc *resxml); eurephiaRESULT *eurephiaXML_ParseResultMsg(eurephiaCTX *ctx, xmlDoc *resxml); inline char *xmlExtractContent(xmlNode *n); diff --git a/database/eurephiadb.c b/database/eurephiadb.c index 6a12aea..05187af 100644 --- a/database/eurephiadb.c +++ b/database/eurephiadb.c @@ -108,27 +108,14 @@ 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"); - - eDBadminGetUserList = eGetSym(ctx, ctx->eurephia_driver, "eDBadminGetUserList"); - eDBadminGetUserInfo = eGetSym(ctx, ctx->eurephia_driver, "eDBadminGetUserInfo"); - eDBadminAddUser = eGetSym(ctx, ctx->eurephia_driver, "eDBadminAddUser"); - eDBadminUpdateUser = eGetSym(ctx, ctx->eurephia_driver, "eDBadminUpdateUser"); - eDBadminDeleteUser = eGetSym(ctx, ctx->eurephia_driver, "eDBadminDeleteUser"); - + eDBadminUserAccount = eGetSym(ctx, ctx->eurephia_driver, "eDBadminUserAccount"); eDBadminCertificate = eGetSym(ctx, ctx->eurephia_driver, "eDBadminCertificate"); - eDBadminUserCertsLink = eGetSym(ctx, ctx->eurephia_driver, "eDBadminUserCertsLink"); - eDBadminAccessLevel = eGetSym(ctx, ctx->eurephia_driver, "eDBadminAccessLevel"); - - eDBadminFirewallProfiles = eGetSym(ctx, ctx->eurephia_driver, "eDBadminFirewallProfiles"); - + eDBadminFirewallProfiles = eGetSym(ctx, ctx->eurephia_driver, + "eDBadminFirewallProfiles"); eDBadminGetLastlog = eGetSym(ctx, ctx->eurephia_driver, "eDBadminGetLastlog"); eDBadminAttemptsLog = eGetSym(ctx, ctx->eurephia_driver, "eDBadminAttemptsLog"); eDBadminBlacklist = eGetSym(ctx, ctx->eurephia_driver, "eDBadminBlacklist"); diff --git a/database/eurephiadb_driver.h b/database/eurephiadb_driver.h index e9c757c..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 @@ -439,129 +431,47 @@ xmlDoc *(*eDBadminConfiguration)(eurephiaCTX *ctx, xmlDoc *cfgxml); /** - * Retrieve a list over all users in the database. - * - * @version API version level 2 - * @param ctx eurephiaCTX - * @param sortkeys String containing the sort order of the fields - * - * @return Returns an XML document on success with all users, otherwise NULL - * @see eurephiaXML_CreateDoc(), eurephiaXML_getRoot() - */ -xmlDoc *(*eDBadminGetUserList) (eurephiaCTX *ctx, const char *sortkeys); - - -/** - * This function will search up a user, based on information given in a fieldMapping structure. - * It will return an XML document containing the user information requested, controlled by the - * infoType flag. These flags are defined in eurephiadb_driver.h - * - * @version API version level 2 - * @param ctx eurephiaCTX - * @param infoType Flags of what information to extract. Valid flags are: USERINFO_user, - * USERINFO_certs, USERINFO_lastlog, USERINFO_attempts, USERINFO_blacklist. - * These flags can be bit-wise OR'ed together to extract more information - * at once. - * - * @param srch XML document describing the search criteria - * - * Skeleton of an XML search document - * @code - * <eurephia format="1"> - * <fieldMapping table="users"> - * <{search field}>{search value}</{search field}> - * </fieldMapping> - * </eurephia> - * @endcode - * - * @return Returns an XML document containing the requested user information on success, otherwise - * NULL is returned. - * @see eurephiaXML_CreateDoc(), eurephiaXML_getRoot() - * @see USERINFO_user, USERINFO_certs, USERINFO_lastlog, USERINFO_attempts, USERINFO_blacklist - */ -xmlDoc *(*eDBadminGetUserInfo) (eurephiaCTX *ctx, int infoType, xmlDoc *srch); - - -/** - * This function will add a user to the openvpn_users table, based on the - * XML document given. - * - * @version API version level 2 - * @param ctx eurephiaCTX - * @param userinfo XML document containing information about the new user - * - * Skeleton of an XML document for adding a new user - * @code - * <eurephia format="1"> - * <add_user> - * <fieldMapping table="users"> - * <username>{user name}</username> - * <password pwhash="{none|sha512}">{password}</password> - * </fieldMapping> - * </add_user> - * </eurephia> - * @endcode - * - * The password tag can use either a clear-text password (by setting pwhash="none") or a pre-hashed - * SHA512 password (by setting pwhash="sha512"). Beware that the SHA512 hash must be hashed with - * the eurephia_pwd_crypt() function. - * - * @return Returns the user ID (uid) of the new user account on success, otherwise -1 is returned. - * @see eurephiaXML_CreateDoc(), eurephia_pwd_crypt() - */ -int (*eDBadminAddUser) (eurephiaCTX *ctx, xmlDoc *userinfo); - - -/** - * This function will update a user account based on the XML document sent in as a parameter. - * The function will double check that the uid in the argument list and the uid in the XML - * document is coherent. + * Function for view, add, update or delete user accounts * - * @version API version level 2 * @param ctx eurephiaCTX - * @param uid Numeric user ID of the user account being updated - * @param userinfo XML document containing the new information for the user account + * @param qryxml XML document with information about the operation * - * Skeleton of an XML document updating a user * @code * <eurephia format="1"> - * <update_user uid="{uid}"> - * <fieldMapping table="users"> - * <{field name}>{new value}</{field name}> - * </fieldMapping> - * </update_user> + * <UserAccount mode="{view|add|update|delete}" [uid="{uid}"]> + * <fieldMapping table="users"> + * <{field name}>{field value}</{field name}> + * ... + * <{field name}>{field value}</{field name}> + * </fieldMapping> + * [<sortkeys>{field name}[, {field name}...]</sortkeys>] + * [<extractFlags>{extract value (int)}</extractFlags>] + * </UserAccount> * </eurephia> * @endcode - * @remarks Beware that the uid attribute in the update_user tag must be the same user ID given as - * argument to the function. + * Valid field names are: uid, username, password, activated, deactivated, lastaccess * - * @return Returns 1 on success, otherwise 0. - * @see eurephiaXML_CreateDoc() - */ -int (*eDBadminUpdateUser) (eurephiaCTX *ctx, const int uid, xmlDoc *userinfo); - - -/** - * This function will delete a user to the openvpn_users table, based on the - * XML document given. + * If no field names and values are given in "view" mode, all user accounts will be returned. Adding + * field name tags will narrow down the query. * - * @version API version level 2 - * @param ctx eurephiaCTX - * @param uid Numeric user ID of the user account being updated - * @param userinfo XML document containing information about the account which is going to be deleted + * For "add" mode, username and password tag is required. For the password tag, the attribute "pwhash" + * can be given to indicate what kind of hashing the value provided is using. If this is not set, the + * password value is expected to come in clear text and will be hashed automatically with a SHA512 + * algorithm. * - * @code - * <eurephia format="1"> - * <delete_user uid="{uid}"/> - * </eurephia> - * @endcode - * @remarks The uid of the account to be deleted must also be sent - * as a separate parameter, as a security feature + * For the "update" mode, the uid attribute in the UserAccount tag is required. This will be the + * key for which record to update. The values being updated need to be set in the fieldMapping tags. * - * @return Returns 1 on success, otherwise 0. - * @see eurephiaXML_CreateDoc() + * For "delete" mode, the "uid" attribute in the UserAccount tag is required. This mode will also ignore + * any fieldMapping tags. + * + * @return When mode is "view", it will return an XML document with user account information on success. + * On errors in "view" mode or the other modes in general, it will return an eurephia ResultMsg + * XML document with the result of the operation, or NULL on fatal errors. + * + * @see eurephiaXML_CreateDoc(), eurephiaXML_ParseResultMsg(), eurephiaXML_getRoot() */ -int (*eDBadminDeleteUser) (eurephiaCTX *ctx, const int uid, xmlDoc *userinfo); +xmlDoc *(*eDBadminUserAccount) (eurephiaCTX *ctx, xmlDoc *qryxml); /** @@ -569,7 +479,7 @@ int (*eDBadminDeleteUser) (eurephiaCTX *ctx, const int uid, xmlDoc *userinfo); * * @version API version level 2 * @param ctx eurephiaCTX - * @param qryxml XML document with the certificate information to be deleted + * @param qryxml XML document with information about the operation * * Skeleton of an XML document used for eDBadminCertificate() * @code @@ -580,13 +490,17 @@ int (*eDBadminDeleteUser) (eurephiaCTX *ctx, const int uid, xmlDoc *userinfo); * ... * <{field name}>{field value}</{field name}> * </fieldMapping> - * </certificate_info> + * [<sortkeys>{field name}[, {field name}...]</sortkeys>] + * </certificates> * </eurephia> * @endcode * Valid field names are: depth, digest, common_name, org, email and certid. * For list and delete mode, all field names can be used to narrow the search query. * In register mode all fields are required, except certid which must not be given. * + * The sortkeys tag will only be used in list mode, and it takes a list of comma separated + * field names. + * * @return When mode is "list", it will return an XML document with all found certificates, otherwise NULL. * If mode is "register" or "delete" an eurephia ResultMsg XML document will be returned with * the result of the operation, or NULL on fatal errors. diff --git a/database/eurephiadb_mapping.c b/database/eurephiadb_mapping.c index 3a2513a..26b9dd7 100644 --- a/database/eurephiadb_mapping.c +++ b/database/eurephiadb_mapping.c @@ -352,9 +352,8 @@ eDBfieldMap *eDBxmlMapping(eurephiaCTX *ctx, eDBfieldMap *dbmap, const char *tbl * @return Returns a comma separated string with translated field names on success, otherwise NULL. * @remark The resulting pointer is pointing at a static char pointer and should not be freed. */ -char *eDBmkSortKeyString(eDBfieldMap *tfmap, const char *skeys_str) { - eDBfieldMap *sk_map = NULL, *ptr1 = NULL; - int i; +const char *eDBmkSortKeyString(eDBfieldMap *tfmap, const char *skeys_str) { + eDBfieldMap *sk_map = NULL, *ptr1 = NULL, *tfmp = NULL; char *cp = NULL, *tok = NULL, *delims = ","; static char sortkeys[8194]; @@ -378,10 +377,14 @@ char *eDBmkSortKeyString(eDBfieldMap *tfmap, const char *skeys_str) { // If we find the the field in the unified mapping table ... if( strcmp(tok, ptr1->field_name) == 0 ) { // look up the proper field name for the current database - for( i = 0; tfmap[i].field_type != FIELD_NONE; i++ ) { - if( ptr1->field_id == tfmap[i].field_id ) { - strncat(sortkeys, tfmap[i].field_name, (8192-strlen(sortkeys)-2)); - strcat(sortkeys,","); + for( tfmp = tfmap; tfmp != NULL; tfmp = tfmp->next ) { + if( ptr1->field_id == tfmp->field_id ) { + if( tfmp->table_alias != NULL ) { + append_str(sortkeys, tfmp->table_alias, 8192); + append_str(sortkeys, ".", 8192); + } + append_str(sortkeys, tfmp->field_name, 8192); + append_str(sortkeys, ",", 8192); } } } @@ -392,7 +395,7 @@ char *eDBmkSortKeyString(eDBfieldMap *tfmap, const char *skeys_str) { sortkeys[strlen(sortkeys)-1] = '\0'; eDBfreeMapping(sk_map); - return sortkeys; + return (strlen_nullsafe(sortkeys) > 0 ? sortkeys : NULL); } diff --git a/database/eurephiadb_mapping.h b/database/eurephiadb_mapping.h index 262231e..37c9f44 100644 --- a/database/eurephiadb_mapping.h +++ b/database/eurephiadb_mapping.h @@ -262,7 +262,7 @@ static eDBfieldMap eTblMap_fwprofiles[] = { void eDBfreeMapping(eDBfieldMap *p); eDBfieldMap *eDBxmlMapping(eurephiaCTX *ctx, eDBfieldMap *dbmap, const char *tblalias, xmlNode *fmap_n); -char *eDBmkSortKeyString(eDBfieldMap *tfmap, const char *skeys_str); +const char *eDBmkSortKeyString(eDBfieldMap *tfmap, const char *skeys_str); long int eDBmappingFieldsPresent(eDBfieldMap *map); const char *eDBmappingGetValue(eDBfieldMap *map, long field_id); diff --git a/database/sqlite/CMakeLists.txt b/database/sqlite/CMakeLists.txt index 44f5c99..463aee7 100644 --- a/database/sqlite/CMakeLists.txt +++ b/database/sqlite/CMakeLists.txt @@ -47,7 +47,7 @@ SET(edb_sqlite_SRC IF(ADMIN_ENABLED) SET(edb_sqlite_SRC ${edb_sqlite_SRC} - administration.c + administration/authentication.c administration/firewalladmin.c administration/attempts.c administration/blacklist.c diff --git a/database/sqlite/administration.c b/database/sqlite/administration/authentication.c index 04dbe6e..75ad991 100644 --- a/database/sqlite/administration.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. * */ @@ -61,7 +60,7 @@ #endif #include <eurephiadb_driver.h> -#include "sqlite.h" +#include "../sqlite.h" #if (DRIVERAPIVERSION > 1) || defined(DOXYGEN) /* @@ -69,38 +68,30 @@ * */ -/** - * Internal function. String replace in a xmlChar based string - * - * @param str xmlChar input string - * @param s search for this character - * @param r replace the character with this one - */ -void xmlReplaceChars(xmlChar *str, char s, char r) { - if( str != NULL ) { - xmlChar *ptr = str; - - while( *ptr != '\0' ) { - if( *ptr == s ) { - *ptr = r; - } - ptr++; - } - } -} - /** - * @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); @@ -113,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"); } // @@ -134,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 ) { @@ -142,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 @@ -179,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); @@ -190,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 ) { @@ -235,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") ) ); @@ -251,12 +260,13 @@ int eDBadminValidateSession(eurephiaCTX *ctx, const char *sesskey, const char *r " LEFT JOIN eurephia_adminaccess USING(uid,interface)" " WHERE status IN (1,2)" " AND sessionkey = '%q'" - " AND access = '%q'", - expire_time, sesskey, req_access); + " 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; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Session authentication failed"); } valid = (atoi_nullsafe(sqlite_get_value(res, 0, 0)) == 0); @@ -276,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" @@ -293,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: @@ -324,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 @@ -364,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/database/sqlite/administration/certificates.c b/database/sqlite/administration/certificates.c index 53b50c2..b64aa07 100644 --- a/database/sqlite/administration/certificates.c +++ b/database/sqlite/administration/certificates.c @@ -55,7 +55,6 @@ #define FMAP_CERTS /**< fieldmapping.h: Include declaration of tbl_sqlite_certs */ #include "../fieldmapping.h" -void xmlReplaceChars(xmlChar *str, char s, char r); /** * Internal function. Retrieves info about one or more certificates @@ -267,8 +266,8 @@ xmlDoc *eDBadminCertificate(eurephiaCTX *ctx, xmlDoc *qryxml) { fmap = eDBxmlMapping(ctx, tbl_sqlite_certs, NULL, fieldmap_n); if( strcmp(mode, "list") == 0 ) { - char *sortkeys = xmlGetNodeContent(root_n, "sortkeys"); - resxml = certificate_list(ctx, fmap, eDBmkSortKeyString(tbl_sqlite_certs, sortkeys)); + char *sortkeys = xmlGetNodeContent(root_n, "sortkeys"); + resxml = certificate_list(ctx, fmap, eDBmkSortKeyString(fmap, sortkeys)); } else if( strcmp(mode, "register") == 0 ) { resxml = certificate_add(ctx, fmap); } else if( strcmp(mode, "delete") == 0 ) { diff --git a/database/sqlite/administration/firewalladmin.c b/database/sqlite/administration/firewalladmin.c index 6c6b91e..fdebccb 100644 --- a/database/sqlite/administration/firewalladmin.c +++ b/database/sqlite/administration/firewalladmin.c @@ -58,8 +58,6 @@ #define FMAP_OVPNACCESSES #include "../fieldmapping.h" -void xmlReplaceChars(xmlChar *str, char s, char r); - /** * Internal function. Queries the database for a list of user-certificate links diff --git a/database/sqlite/administration/lastlog.c b/database/sqlite/administration/lastlog.c index 15703ce..e850d94 100644 --- a/database/sqlite/administration/lastlog.c +++ b/database/sqlite/administration/lastlog.c @@ -54,8 +54,6 @@ #define FMAP_LASTLOG /**< fieldmapping.h: Include declaration of tbl_sqlite_lastlog */ #include "../fieldmapping.h" -void xmlReplaceChars(xmlChar *str, char s, char r); - /** * @copydoc eDBadminGetLastlog() diff --git a/database/sqlite/administration/useraccount.c b/database/sqlite/administration/useraccount.c index 4f44789..b0613a5 100644 --- a/database/sqlite/administration/useraccount.c +++ b/database/sqlite/administration/useraccount.c @@ -57,63 +57,6 @@ #include "../fieldmapping.h" -void xmlReplaceChars(xmlChar *str, char s, char r); - - -/** - * @copydoc eDBadminGetUserList() - */ -xmlDoc *eDBadminGetUserList(eurephiaCTX *ctx, const char *sortkeys) { - xmlDoc *userlist = NULL; - xmlNode *root_n = NULL, *user_n = NULL; - dbresult *res = NULL; - char *dbsort = NULL, tmp[34]; - int i = 0; - - DEBUG(ctx, 20, "Function call: eDBadminGetUserList(ctx, '%s')", sortkeys); - assert((ctx != NULL) && (ctx->dbc != 0)); - - 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; - } - - // Convert the input sort keys to the proper database field names - dbsort = eDBmkSortKeyString(tbl_sqlite_users, sortkeys); - - // Query database for all users - res = sqlite_query(ctx, - "SELECT username, activated, deactivated, last_accessed, uid" - " FROM openvpn_users " - "ORDER BY %s", (sortkeys != NULL ? dbsort : "uid")); - if( res == NULL ) { - eurephia_log(ctx, LOG_ERROR, 0, "Error querying the user database"); - return NULL; - } - - // Prepare a list with all users - memset(&tmp, 0, 34); - eurephiaXML_CreateDoc(ctx, 1, "userlist", &userlist, &root_n); - snprintf(tmp, 32, "%i", sqlite_get_numtuples(res)); - xmlNewProp(root_n, (xmlChar *)"usercount", (xmlChar *)tmp); - - // Register all records - for( i = 0; i < sqlite_get_numtuples(res); i++ ) { - user_n = xmlNewChild(root_n, NULL, (xmlChar *)"user", NULL); - sqlite_xml_value(user_n, XML_ATTR, "uid", res, i, 4); - sqlite_xml_value(user_n, XML_NODE, "username", res, i, 0); - sqlite_xml_value(user_n, XML_NODE, "activated", res, i, 1); - sqlite_xml_value(user_n, XML_NODE, "deactivated", res, i, 2); - sqlite_xml_value(user_n, XML_NODE, "last_accessed", res, i, 3); - } - sqlite_free_results(res); - - // Return a user list - return userlist; -} - - /** * Internal function. Adds a child node named \<flag\> to an xmlNode containing a flag value * @@ -123,7 +66,7 @@ xmlDoc *eDBadminGetUserList(eurephiaCTX *ctx, const char *sortkeys) { * * @return Returns the \c flagged value */ -inline int xml_set_flag(xmlNode *node, char *flagname, int flagged) { +static inline int xml_set_flag(xmlNode *node, char *flagname, int flagged) { if( flagged ) { xmlNewChild(node, NULL, (xmlChar *) "flag", (xmlChar *) flagname); } @@ -132,19 +75,27 @@ inline int xml_set_flag(xmlNode *node, char *flagname, int flagged) { /** - * @copydoc eDBadminGetUserInfo() + * Internal function. Retrieves information about user accounts + * + * @param ctx eurephiaCTX + * @param infoType Flags defining which information to be included in the result + * @param uinfo_map eDBfieldMap containing information needed for the new user account + * @param sortkeys String containing list of fields defining data sorting + * + * @return Returns an eurephia ResultMsg XML document with status of the operation. On fatal errors, + * NULL is returned. */ -xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { +static xmlDoc *useracc_view(eurephiaCTX *ctx, unsigned int infoType, + eDBfieldMap *uinfo_map, const char *sortkeys) +{ dbresult *uinf = NULL, *qres = NULL; - eDBfieldMap *uinfo_map = NULL; - int flag = 0, uid = 0; + unsigned int flag = 0, uid = 0, recid = 0; char *username = NULL; - xmlDoc *doc = NULL; - xmlNode *root_n = NULL, *info_n = NULL, *fieldmap = NULL; + xmlNode *root_n = NULL, *info_n = NULL; DEBUG(ctx, 20, "Function call: eDBadminGetUserUserInfo(ctx, %i, {xmlDoc})", infoType); - assert( (ctx != NULL) && (srch != NULL) ); + assert( ctx != NULL ); if( (ctx->context_type != ECTX_ADMIN_CONSOLE) && (ctx->context_type != ECTX_ADMIN_WEB) ) { eurephia_log(ctx, LOG_CRITICAL, 0, @@ -152,65 +103,63 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { return NULL; } - fieldmap = eurephiaXML_getRoot(ctx, srch, "fieldMapping", 1); - uinfo_map = eDBxmlMapping(ctx, tbl_sqlite_users, "u", fieldmap); - // Query the database, find the user defined in the user map uinf = sqlite_query_mapped(ctx, SQL_SELECT, - "SELECT u.username, u.activated, u.deactivated, u.last_accessed, u.uid," + "SELECT users.username, users.activated, users.deactivated," + " users.last_accessed, users.uid," " (bl.username IS NOT NULL), opensess, logincount," " (at.attempts > 0)" - " FROM openvpn_users u" + " FROM openvpn_users users" " LEFT JOIN openvpn_blacklist bl USING(username)" - " LEFT JOIN openvpn_attempts at ON(at.username = u.username)" + " LEFT JOIN openvpn_attempts at ON(at.username = users.username)" " LEFT JOIN (SELECT uid, count(*) AS logincount " " FROM openvpn_lastlog" " GROUP BY uid) lc" - " ON (lc.uid = u.uid)" + " ON (lc.uid = users.uid)" " LEFT JOIN (SELECT uid, count(*) > 0 AS opensess" " FROM openvpn_lastlog" " WHERE sessionstatus = 2" " GROUP BY uid) os" - " ON (os.uid = u.uid)", - NULL, uinfo_map, NULL); + " ON (os.uid = users.uid)", + NULL, uinfo_map, sortkeys); if( uinf == NULL ) { eurephia_log(ctx, LOG_ERROR, 0, "Error querying the database for a user"); - return 0; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Failed to query the user database"); } - eDBfreeMapping(uinfo_map); - switch( sqlite_get_numtuples(uinf) ) { - case 0: - sqlite_free_results(uinf); - return 0; // No user found + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &doc, &root_n); + xmlNewProp(root_n, (xmlChar *) "mode", (xmlChar *) "view"); + + for( recid = 0; recid < sqlite_get_numtuples(uinf); recid++ ) { + xmlNode *user_n = xmlNewChild(root_n, NULL, (xmlChar *) "Account", NULL); + assert( user_n != NULL ); - case 1: - uid = atoi_nullsafe(sqlite_get_value(uinf, 0, 4)); - username = sqlite_get_value(uinf, 0, 0); + sqlite_xml_value(user_n, XML_ATTR, "uid", uinf, recid, 4); + sqlite_xml_value(user_n, XML_NODE, "username", uinf, recid, 0); - eurephiaXML_CreateDoc(ctx, 1, "user", &doc, &root_n); - sqlite_xml_value(root_n, XML_NODE, "username", uinf, 0, 0); - sqlite_xml_value(root_n, XML_ATTR, "uid", uinf, 0, 4); + uid = atoi_nullsafe(sqlite_get_value(uinf, recid, 4)); + username = sqlite_get_value(uinf, recid, 0); - if( (infoType & USERINFO_user) == USERINFO_user ) { - info_n = xmlNewChild(root_n, NULL, (xmlChar *) "flags", NULL); + if( infoType & USERINFO_user ) { + info_n = xmlNewChild(user_n, NULL, (xmlChar *) "flags", NULL); + assert( info_n != NULL ); // set DEACTIVATED flag, if deactivated field is not NULL - xml_set_flag(info_n, "DEACTIVATED", (sqlite_get_value(uinf, 0, 2) != NULL)); + xml_set_flag(info_n, "DEACTIVATED", (sqlite_get_value(uinf, recid, 2) != NULL)); // set BLACKLISTED flag, if username is found in blacklist table - xml_set_flag(info_n, "BLACKLISTED", (atoi_nullsafe(sqlite_get_value(uinf, 0, 5))==1)); + xml_set_flag(info_n, "BLACKLISTED", (atoi_nullsafe(sqlite_get_value(uinf, recid, 5))==1)); // set OPENSESSION flag, if user has a lastlog entry with sessionstatus == 2 - xml_set_flag(info_n, "OPENSESSION", (atoi_nullsafe(sqlite_get_value(uinf, 0, 6))==1)); + xml_set_flag(info_n, "OPENSESSION", (atoi_nullsafe(sqlite_get_value(uinf, recid, 6))==1)); // set ERRATTEMPT flag, if user has an entry in attempts log with attemtps > 0 - xml_set_flag(info_n, "ERRATTEMPT", (atoi_nullsafe(sqlite_get_value(uinf, 0, 8))==1)); + xml_set_flag(info_n, "ERRATTEMPT", (atoi_nullsafe(sqlite_get_value(uinf, recid, 8))==1)); // set NEVERUSED flag, if login count == 0 and last_accessed == NULL flag = xml_set_flag(info_n, "NEVERUSED", ((atoi_nullsafe(sqlite_get_value(uinf,0, 7))==0) - && (sqlite_get_value(uinf, 0, 3) == NULL))); + && (sqlite_get_value(uinf, recid, 3) == NULL))); // set RSETLASTUSED flag, if login count == 0 and last_accessed == NULL xml_set_flag(info_n, "RSETLASTUSED", !flag && (sqlite_get_value(uinf,0,3)) == NULL); @@ -219,13 +168,13 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { xml_set_flag(info_n, "RSETLOGINCNT", ((atoi_nullsafe(sqlite_get_value(uinf,0, 7))==0) && (sqlite_get_value(uinf,0,3)) != NULL)); - sqlite_xml_value(root_n, XML_NODE, "activated", uinf, 0, 1); - sqlite_xml_value(root_n, XML_NODE, "deactivated", uinf, 0, 2); - info_n = sqlite_xml_value(root_n, XML_NODE, "last_accessed", uinf, 0, 3); - sqlite_xml_value(info_n, XML_ATTR, "logincount", uinf, 0, 7); + sqlite_xml_value(user_n, XML_NODE, "activated", uinf, recid, 1); + sqlite_xml_value(user_n, XML_NODE, "deactivated", uinf, recid, 2); + info_n = sqlite_xml_value(user_n, XML_NODE, "last_accessed", uinf, recid, 3); + sqlite_xml_value(user_n, XML_ATTR, "logincount", uinf, recid, 7); } - if( (infoType & USERINFO_certs) == USERINFO_certs ) { + if( infoType & USERINFO_certs ) { // Extract certificate info qres = sqlite_query(ctx, "SELECT depth, digest, common_name, organisation, email, " @@ -237,7 +186,8 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { " ON (uc.accessprofile = a.accessprofile)" " WHERE uid = '%i' ORDER BY c.certid DESC", uid); - info_n = xmlNewChild(root_n, NULL, (xmlChar *) "certificates", NULL); + info_n = xmlNewChild(user_n, NULL, (xmlChar *) "certificates", NULL); + assert( info_n != NULL ); if( (qres != NULL) && (sqlite_get_numtuples(qres) > 0) ) { int i; xmlNode *cert, *acpr; @@ -245,6 +195,7 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { for( i = 0; i < sqlite_get_numtuples(qres); i++ ) { cert = xmlNewChild(info_n, NULL, (xmlChar *) "certificate", NULL); + assert( cert != NULL ); sqlite_xml_value(cert, XML_ATTR, "certid", qres, 0, 6); sqlite_xml_value(cert, XML_ATTR, "depth", qres, 0, 0); @@ -266,19 +217,16 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { sqlite_xml_value(acpr, XML_ATTR, "fwdestination", qres, 0, 9); } } - - if( qres != NULL ) { - sqlite_free_results(qres); - } + sqlite_free_results(qres); } - if( (infoType & USERINFO_lastlog) == USERINFO_lastlog ) { + if( infoType & USERINFO_lastlog ) { int i = 0; xmlNode *lastl = NULL, *sess = NULL, *tmp1 = NULL, *tmp2 = NULL; xmlChar *tmp = NULL; qres = sqlite_query(ctx, - "SELECT llid, ll.certid, protocol, remotehost, remoteport, macaddr," + "SELECT llid, ll.certid,protocol,remotehost,remoteport,macaddr," " vpnipaddr, vpnipmask, sessionstatus, sessionkey," " login, logout, session_duration, session_deleted," " bytes_sent, bytes_received, uicid, accessprofile," @@ -287,19 +235,22 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { " FROM openvpn_lastlog ll" " LEFT JOIN openvpn_usercerts USING (uid, certid)" " LEFT JOIN openvpn_accesses USING (accessprofile)" - " LEFT JOIN openvpn_certificates cert ON (ll.certid = cert.certid)" + " LEFT JOIN openvpn_certificates cert ON(ll.certid=cert.certid)" " WHERE uid = '%i' ORDER BY login, logout", uid); if( qres == NULL ) { eurephia_log(ctx, LOG_ERROR, 0, "Quering the lastlog failed"); xmlFreeDoc(doc); - return NULL; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Failed to query the lastlog"); } - lastl = xmlNewChild(root_n, NULL, (xmlChar *) "lastlog", NULL); + lastl = xmlNewChild(user_n, NULL, (xmlChar *) "lastlog", NULL); for( i = 0; i < sqlite_get_numtuples(qres); i++ ) { sess = xmlNewChild(lastl, NULL, (xmlChar*) "session", NULL); + assert( sess != NULL ); + sqlite_xml_value(sess, XML_ATTR, "llid", qres, i, 0); xmlNewProp(sess, (xmlChar *) "session_status", (xmlChar *)SESSION_STATUS[atoi_nullsafe(sqlite_get_value(qres, i, 8))]); @@ -310,6 +261,7 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { sqlite_xml_value(sess, XML_NODE, "session_closed", qres, i, 13); tmp1 = xmlNewChild(sess, NULL, (xmlChar *) "connection", NULL); + assert( tmp1 != NULL ); sqlite_xml_value(tmp1, XML_ATTR, "bytes_sent", qres, i, 14); sqlite_xml_value(tmp1, XML_ATTR, "bytes_received", qres, i, 15); sqlite_xml_value(tmp1, XML_NODE, "protocol", qres, i, 2); @@ -320,6 +272,7 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { sqlite_xml_value(tmp1, XML_NODE, "vpn_netmask", qres, i, 7); tmp1 = xmlNewChild(sess, NULL, (xmlChar *) "certificate", NULL); + assert( tmp1 != NULL ); sqlite_xml_value(tmp1, XML_ATTR, "certid", qres, i, 1); sqlite_xml_value(tmp1, XML_ATTR, "uicid", qres, i, 16); sqlite_xml_value(tmp1, XML_ATTR, "depth", qres, i, 20); @@ -342,7 +295,7 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { sqlite_free_results(qres); } - if( (infoType & USERINFO_attempts) == USERINFO_attempts ) { + if( infoType & USERINFO_attempts ) { xmlNode *atmpt = NULL; qres = sqlite_query(ctx, @@ -354,10 +307,13 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { eurephia_log(ctx, LOG_ERROR, 0, "Quering for login attempts failed"); sqlite_free_results(qres); xmlFreeDoc(doc); - return NULL; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Failed to query the login attempts log"); } - atmpt = xmlNewChild(root_n, NULL, (xmlChar *) "attempts", NULL); + atmpt = xmlNewChild(user_n, NULL, (xmlChar *) "attempts", NULL); + assert( atmpt != NULL ); + if( sqlite_get_numtuples(qres) == 1 ) { sqlite_xml_value(atmpt, XML_ATTR, "atpid", qres, 0, 3); sqlite_xml_value(atmpt, XML_ATTR, "attempts", qres, 0, 0); @@ -367,7 +323,7 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { sqlite_free_results(qres); } - if( (infoType & USERINFO_blacklist) == USERINFO_blacklist ) { + if( infoType & USERINFO_blacklist ) { xmlNode *atmpt = NULL; qres = sqlite_query(ctx, @@ -379,10 +335,13 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { eurephia_log(ctx, LOG_ERROR, 0, "Quering blacklist log failed"); sqlite_free_results(qres); xmlFreeDoc(doc); - return NULL; + return eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Failed to query the blacklist log"); } - atmpt = xmlNewChild(root_n, NULL, (xmlChar *) "blacklist", NULL); + atmpt = xmlNewChild(user_n, NULL, (xmlChar *) "blacklist", NULL); + assert( atmpt != NULL ); + if( sqlite_get_numtuples(qres) == 1 ) { sqlite_xml_value(atmpt, XML_ATTR, "blid", qres, 0, 2); sqlite_xml_value(atmpt, XML_NODE, "blacklisted", qres, 0, 0); @@ -391,103 +350,92 @@ xmlDoc *eDBadminGetUserInfo(eurephiaCTX *ctx, int infoType, xmlDoc *srch) { sqlite_free_results(qres); } - sqlite_free_results(uinf); - return doc; - default: - sqlite_free_results(uinf); - eurephia_log(ctx, LOG_ERROR, 0, "Too many user records was found."); - return NULL; } + sqlite_free_results(uinf); + return doc; } /** - * @copydoc eDBadminAddUser() + * Internal function. Creates a new user account in the database. + * + * @param ctx eurephiaCTX + * @param usrinf_map eDBfieldMap containing information needed for the new user account + * + * @return Returns an eurephia ResultMsg XML document with status of the operation. On fatal errors, + * NULL is returned. */ -int eDBadminAddUser(eurephiaCTX *ctx, xmlDoc *userinfo) { +static xmlDoc *useracc_add(eurephiaCTX *ctx, eDBfieldMap *usrinf_map) { + xmlDoc *res_d = NULL; dbresult *res = NULL; - xmlNode *usrinf_n = NULL; - eDBfieldMap *usrinf_map = NULL; - int uid = 0; - DEBUG(ctx, 20, "Function call: eDBadminAddUser(ctx, xmlDoc)"); - assert( (ctx != NULL) && (userinfo != NULL) ); + DEBUG(ctx, 21, "Function call: useracc_add(ctx, eDBfieldMap)"); + assert( (ctx != NULL) && (usrinf_map != 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; - } - - // Get the add_user node, and then find the fieldMapping node - usrinf_n = eurephiaXML_getRoot(ctx, userinfo, "add_user", 1); - if( usrinf_n == NULL ) { - eurephia_log(ctx, LOG_ERROR, 0, "Could not find proper add user XML document"); - return 0; - } - usrinf_n = xmlFindNode(usrinf_n, "fieldMapping"); - if( usrinf_n == NULL ) { - eurephia_log(ctx, LOG_ERROR, 0, "Could not find proper add user XML document"); - return 0; + return NULL; } - // Get a proper field mapping to be used by the database - usrinf_map = eDBxmlMapping(ctx, tbl_sqlite_users, NULL, usrinf_n); - assert( usrinf_map != NULL ); - // Register the user res = sqlite_query_mapped(ctx, SQL_INSERT, "INSERT INTO openvpn_users", usrinf_map, NULL, NULL); - if( res == NULL ) { + if( (res == NULL) || (sqlite_get_affected_rows(res) == 0) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not register the new user account"); - uid = -1; + res_d = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Failed to register the user account"); } else { - uid = res->last_insert_id; + xmlChar *uid = malloc_nullsafe(ctx, 34); + xmlNode *info_n = NULL; + assert( uid != NULL ); + + // Prepare an information tag/node with the new uid value + xmlStrPrintf(uid, 32, (xmlChar *) "%ld", res->last_insert_id); + info_n = xmlNewNode(NULL, (xmlChar *)"UserAccount"); + xmlNewProp(info_n, (xmlChar *) "mode", (xmlChar *) "add"); + xmlNewProp(info_n, (xmlChar *) "uid", uid); + + eurephia_log(ctx, LOG_INFO, 1, "New user account created (uid %i)", res->last_insert_id); + res_d = eurephiaXML_ResultMsg(ctx, exmlRESULT, info_n, + "New user account created with uid %i", res->last_insert_id); + free_nullsafe(ctx, uid); + xmlFreeNode(info_n); } sqlite_free_results(res); - eDBfreeMapping(usrinf_map); - return uid; + return res_d; } /** - * @copydoc eDBadminUpdateUser() - */ -int eDBadminUpdateUser(eurephiaCTX *ctx, const int uid, xmlDoc *userinfo) { + * Internal function. Updates a user account + * + * @param ctx eurephiaCTX + * @param uid Numeric user id to be updated + * @param value_map eDBfieldMap containing new values + * + * @return Returns an eurephia ResultMsg XML document with status of the operation. On fatal errors, + * NULL is returned. +*/ +static xmlDoc *useracc_update(eurephiaCTX *ctx, const int uid, eDBfieldMap *value_map) { dbresult *uinf = NULL; - xmlDoc *srch_xml = NULL; - xmlNode *root_n = NULL, *srch_n = NULL, *values_n = NULL; - eDBfieldMap *value_map = NULL, *srch_map = NULL; - xmlChar *xmluid = 0; + xmlDoc *res_d = NULL, *srch_xml = NULL; + xmlNode *srch_n = NULL; + xmlChar *xmluid = NULL; + eDBfieldMap *srch_map = NULL; - DEBUG(ctx, 20, "Function call: eDBadminUpdateUser(ctx, %i, xmlDoc)", uid); - assert( (ctx != NULL) && (userinfo != NULL) ); + DEBUG(ctx, 21, "Function call: useracc_update(ctx, %i, eDBfieldMap)", uid); + assert( (ctx != NULL) && (value_map != 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; - } - - // Get the update_user node - root_n = eurephiaXML_getRoot(ctx, userinfo, "update_user", 1); - if( root_n == NULL ) { - eurephia_log(ctx, LOG_ERROR, 0, "Could not find proper XML element for user update"); - return 0; - } - - // Double check that we are going to update the right user - xmluid = (xmlChar *)xmlGetAttrValue(root_n->properties, "uid"); - if( atoi_nullsafe((char *)xmluid) != uid ) { - eurephia_log(ctx, LOG_ERROR, 0, "Mismatch between uid given as parameter and uid in XML"); - return 0; + return NULL; } - // Grab the fieldMapping node and create a eDBfieldMap structure for it - values_n = xmlFindNode(root_n, "fieldMapping"); - value_map = eDBxmlMapping(ctx, tbl_sqlite_users, NULL, values_n); - - // Create an eDBfieldMap structure for the srch_map (used for WHERE clause) + // Create an eDBfieldMap structure for the srch_map (to be used in the WHERE clause) + xmluid = (xmlChar *) malloc_nullsafe(ctx, 34); + xmlStrPrintf(xmluid, 32, (xmlChar *) "%ld", uid); eurephiaXML_CreateDoc(ctx, 1, "fieldMapping", &srch_xml, &srch_n); xmlNewProp(srch_n, (xmlChar *) "table", (xmlChar *) "users"); xmlNewChild(srch_n, NULL, (xmlChar *) "uid", xmluid); // Add uid as the only criteria @@ -499,59 +447,131 @@ int eDBadminUpdateUser(eurephiaCTX *ctx, const int uid, xmlDoc *userinfo) { if( uinf == NULL ) { eurephia_log(ctx, LOG_ERROR, 0, "Error querying the database for a user"); - return 0; + eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Failed to update user (uid %i)", uid); + } else if( sqlite_get_affected_rows(uinf) == 0 ) { + res_d = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Could not find any user account with uid %i", uid); + } else { + res_d = eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, + "User account with uid %i is updated", uid); } sqlite_free_results(uinf); - eDBfreeMapping(srch_map); - eDBfreeMapping(value_map); xmlFreeDoc(srch_xml); + free_nullsafe(ctx, xmluid); - return 1; + return res_d; } + /** - * @copydoc eDBadminDeleteUser() + * Internal function. Deletes a user account from the users table + * + * @param ctx eurephiaCTX + * @param uid Numeric user id of user to be deleted. + * + * @return Returns an eurephia ResultMsg XML document with status of the operation. On fatal errors, + * NULL is returned. */ -int eDBadminDeleteUser(eurephiaCTX *ctx, const int uid, xmlDoc *userinfo) { +static xmlDoc *useracc_delete(eurephiaCTX *ctx, const unsigned int uid) { + xmlDoc *res_d = NULL; dbresult *res = NULL; - xmlNode *usrinf_n = NULL; - char *uid_str = NULL; - int rc = 0; - DEBUG(ctx, 20, "Function call: eDBadminDeleteUser(ctx, %i, xmlDoc)", uid); - assert( (ctx != NULL) && (userinfo != NULL) ); + DEBUG(ctx, 21, "Function call: useracc_delete(ctx, %i)", uid); + assert( ctx != 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; - } - - // Get the delete_user node - usrinf_n = eurephiaXML_getRoot(ctx, userinfo, "delete_user", 1); - if( usrinf_n == NULL ) { - eurephia_log(ctx, LOG_ERROR, 0, "Could not find proper delete user XML document"); - return 0; - } - - // Get the uid from the XML and compare it with the uid in the function argument - uid_str = xmlGetAttrValue(usrinf_n->properties, "uid"); - if( (uid_str == NULL) || (atoi_nullsafe(uid_str) != uid) ) { - eurephia_log(ctx, LOG_ERROR, 0, "Could not find proper delete user XML document. (uid mismatch)"); - return 0; + return NULL; } // Delete the user res = sqlite_query(ctx, "DELETE FROM openvpn_users WHERE uid = '%i'", uid); if( res == NULL ) { - eurephia_log(ctx, LOG_FATAL, 0, "Could not delete the user account"); - rc = 0; + eurephia_log(ctx, LOG_FATAL, 0, "Could not delete the user account (uid %i)", uid); + res_d = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Failed to delete the user account (uid %i)", uid); + } else if( sqlite_get_affected_rows(res) == 0 ) { + res_d = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Could not find any user account with uid %i", uid); } else { - rc = 1; + res_d = eurephiaXML_ResultMsg(ctx, exmlRESULT, NULL, + "User account with uid %i is deleted", uid); } sqlite_free_results(res); - return rc; + return res_d; +} + + +/** + * @copydoc eDBadminUserAccount() + */ +xmlDoc *eDBadminUserAccount(eurephiaCTX *ctx, xmlDoc *qryxml) { + xmlDoc *res_d = NULL; + xmlNode *qry_n = NULL, *fmap_n = NULL; + eDBfieldMap *fmap_m = NULL; + char *mode = NULL; + int uid; + + DEBUG(ctx, 20, "Function call: eDBadminUserAccount(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, "UserAccount", 1); + if( qry_n == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, "Could not find a valid XML for the user account request"); + return NULL; + } + mode = xmlGetAttrValue(qry_n->properties, "mode"); + if( mode == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, "Invalid user account request (1)."); + return NULL; + } + + fmap_n = xmlFindNode(qry_n, "fieldMapping"); + if( fmap_n == NULL ) { + eurephia_log(ctx, LOG_ERROR, 0, "Invalid user account request (2)."); + return NULL; + } + fmap_m = eDBxmlMapping(ctx, tbl_sqlite_users, "users", fmap_n); + assert(fmap_m != NULL); + + // Extract the value of the uid attribute in the UserAccount tag. If not found, set value to -1. + uid = atoi_nullsafe(defaultValue(xmlGetAttrValue(qry_n->properties, "uid"), "-1")); + + if( strcmp(mode, "view") == 0 ) { + unsigned int flags = atoi_nullsafe(defaultValue(xmlGetNodeContent(qry_n,"extractFlags"),"0")); + const char *sortkeys = xmlGetNodeContent(qry_n, "sortkeys"); + res_d = useracc_view(ctx, flags, fmap_m, eDBmkSortKeyString(fmap_m, sortkeys)); + } else if( strcmp(mode, "add") == 0 ) { + res_d = useracc_add(ctx, fmap_m); + } else if( strcmp(mode, "update") == 0 ) { + if( uid == -1 ) { + res_d = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Can not update user account without an uid value"); + } else { + res_d = useracc_update(ctx, uid, fmap_m); + } + } else if( strcmp(mode, "delete") == 0 ) { + if( uid == -1 ) { + res_d = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, + "Can not delete user account without an uid value"); + } else { + res_d = useracc_delete(ctx, uid); + } + } else { + eurephia_log(ctx, LOG_ERROR, 0, "UserAccount - Unknown mode: '%s'", mode); + res_d = eurephiaXML_ResultMsg(ctx, exmlERROR, NULL, "Unknown mode '%s'", mode); + } + eDBfreeMapping(fmap_m); + + return res_d; } @@ -608,11 +628,11 @@ xmlDoc *adminacclvl_Get(eurephiaCTX *ctx, eDBfieldMap *fmap) { tmp_n = sqlite_xml_value(acl_n, XML_NODE, "access", res, i, 3); sqlite_xml_value(tmp_n, XML_ATTR, "interface", res, i, 2); } - sqlite_free_results(res); return doc; } + /** * @copydoc eDBadminAccessLevel() */ diff --git a/database/sqlite/administration/usercerts.c b/database/sqlite/administration/usercerts.c index 4387dcf..8e235c5 100644 --- a/database/sqlite/administration/usercerts.c +++ b/database/sqlite/administration/usercerts.c @@ -57,8 +57,6 @@ #define FMAP_USERCERTS #include "../fieldmapping.h" -void xmlReplaceChars(xmlChar *str, char s, char r); - /** * Internal function. Queries the database for a list of user-certificate links @@ -74,7 +72,7 @@ xmlDoc *usercerts_search(eurephiaCTX *ctx, eDBfieldMap *where_m, const char *sor xmlNode *link_root_n = NULL, *link_n = NULL, *tmp_n = NULL; dbresult *res = NULL; xmlChar tmp[2050]; - char *dbsort = NULL; + const char *dbsort = NULL; int i; DEBUG(ctx, 21, "Function call: usercerts_search(ctx, eDBfieldMap, '%s')", sortkeys); @@ -87,7 +85,7 @@ xmlDoc *usercerts_search(eurephiaCTX *ctx, eDBfieldMap *where_m, const char *sor } if( sortkeys != NULL ) { - dbsort = eDBmkSortKeyString(tbl_sqlite_usercerts, sortkeys); + dbsort = eDBmkSortKeyString(where_m, sortkeys); } res = sqlite_query_mapped(ctx, SQL_SELECT, diff --git a/database/sqlite/sqlite.c b/database/sqlite/sqlite.c index 71bd04a..6021462 100644 --- a/database/sqlite/sqlite.c +++ b/database/sqlite/sqlite.c @@ -262,6 +262,7 @@ dbresult *sqlite_query(eurephiaCTX *ctx, const char *fmt, ... ) { if( rc != SQLITE_OK ) { eurephia_log(ctx, LOG_ERROR, 0, "SQL Error: %s", errMsg); sqlite3_free(sql); sql = NULL; + sqlite3_free(errMsg); errMsg = NULL; free_nullsafe(ctx, dbres); return NULL; } @@ -345,17 +346,6 @@ char *_build_value_string(eDBfieldMap *ptr) { /** - * Wrapper macro, which appends a string to a destination string without exceeding the size - * of the destination buffer. - * - * @param dest Pointer to the destination buffer - * @param src Pointer to the value being concatenated to the destination string. - * @param size Size of the destination buffer - */ -#define append_str(dest, src, size) strncat(dest, src, (size - strlen_nullsafe(dest))) - - -/** * Internal function. Builds up a part of an SQL query, depending on the buildType. The values * are taken from a pointer to an eDBfieldMap keeping the values * @@ -399,7 +389,7 @@ char *_build_sqlpart(int btyp, eDBfieldMap *map) { // Put the pieces together and append it to the final result val = _build_value_string(ptr); - if( ptr->table_alias != NULL ) { + if( (btyp == btWHERE) && (ptr->table_alias != NULL) ) { append_str(buf, ptr->table_alias, 8192); append_str(buf, ".", 8192); } @@ -544,8 +534,9 @@ dbresult *sqlite_query_mapped(eurephiaCTX *ctx, SQLqueryType qType, const char * void sqlite_dump_result(FILE *dmp, dbresult *res) { _sqlite_tuples *row = NULL, *field = NULL; - if( res == NULL ) { - fprintf(dmp, "(No records found)"); + if( (res == NULL) || (res->tuples == NULL) ) { + fprintf(dmp, "(No records found)\n"); + return; } /* @@ -651,30 +642,6 @@ xmlNodePtr sqlite_xml_value(xmlNodePtr node, xmlFieldType xmltyp, char *inname, #endif -/** - * Retrieve number of tuples in a given dbresult structure - * - * @param res Pointer to a dbresult - * - * @return Returns number of rows/number of tuples in the result. - */ -int sqlite_get_numtuples(dbresult *res) { - return (res != NULL ? res->num_tuples : 0); -} - - -/** - * Retrieve number of affected tuples in current dbresult structure. This is only useful - * when called on a result from INSERT, UPDATE or DELETE queries. - * - * @param res Pointer to a dbresult - * - * @return Returns number of rows/tuples affected by the SQL query - */ -int sqlite_get_affected_rows(dbresult *res) { - return (res != NULL ? res->affected_rows : 0); -} - #ifdef SQLITE_DEBUG /* * Just a simple test program ... to debug this sqlite wrapper diff --git a/database/sqlite/sqlite.h b/database/sqlite/sqlite.h index ce482e4..3885e0c 100644 --- a/database/sqlite/sqlite.h +++ b/database/sqlite/sqlite.h @@ -126,7 +126,26 @@ char *sqlite_get_value(dbresult *res, int, int); xmlNodePtr sqlite_xml_value(xmlNodePtr node, xmlFieldType xmltyp, char *name, dbresult *res, int row, int col); #endif void sqlite_dump_result(FILE *, dbresult *); -int sqlite_get_numtuples(dbresult *); -int sqlite_get_affected_rows(dbresult *); + + +/** + * Retrieve number of tuples in a given dbresult structure + * + * @param dbres Pointer to a dbresult + * + * @return Returns number of rows/number of tuples in the result. + */ +#define sqlite_get_numtuples(dbres) (dbres != NULL ? dbres->num_tuples : 0) + + +/** + * Retrieve number of affected tuples in current dbresult structure. This is only useful + * when called on a result from INSERT, UPDATE or DELETE queries. + * + * @param dbres Pointer to a dbresult + * + * @return Returns number of rows/tuples affected by the SQL query + */ +#define sqlite_get_affected_rows(dbres) (dbres != NULL ? dbres->affected_rows : 0) #endif /* !SQLITE_H_ */ diff --git a/eurephiadm/commands/users.c b/eurephiadm/commands/users.c index e314dfe..3b84a5d 100644 --- a/eurephiadm/commands/users.c +++ b/eurephiadm/commands/users.c @@ -199,8 +199,9 @@ void help_Users() { * @return returns 0 on success, otherwise 1. */ int list_users(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { - xmlDoc *userlist = NULL; - int i = 0; + xmlDoc *qrydoc = NULL, *userlist = NULL; + xmlNode *qry_n = NULL, *fmap_n = NULL; + int i = 0, rc = 0; char *sortkeys = NULL; const char *xsltparams[] = {"view", "'userlist'", NULL}; @@ -229,12 +230,37 @@ int list_users(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int } } + // Create a query document + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &qrydoc, &qry_n); + assert( (qrydoc != NULL) && (qry_n != NULL) ); + + xmlNewProp(qry_n, (xmlChar *) "mode", (xmlChar *) "view"); + xmlNewChild(qry_n, NULL, (xmlChar *) "sortkeys", (xmlChar *)sortkeys); + xmlNewChild(qry_n, NULL, (xmlChar *) "extractFlags", (xmlChar *) "1"); + + fmap_n = xmlNewChild(qry_n, NULL, (xmlChar *) "fieldMapping", NULL); + assert( fmap_n != NULL ); + xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *) "users"); + // Retrieve the user list - and display it - userlist = eDBadminGetUserList(ctx, sortkeys); - xslt_print_xmldoc(stdout, cfg, userlist, "users.xsl", xsltparams); + userlist = eDBadminUserAccount(ctx, qrydoc); + if( eurephiaXML_IsResultMsg(ctx, userlist) ) { + eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, userlist); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + rc = 1; + } else { + rc = 2; + } + free_nullsafe(ctx, res); + } else { + xslt_print_xmldoc(stdout, cfg, userlist, "users.xsl", xsltparams); + rc = 0; + } xmlFreeDoc(userlist); + xmlFreeDoc(qrydoc); - return 0; + return rc; } @@ -253,7 +279,9 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int int i, crit_set = 0, lastlog_verb = 0; long int show_info = USERINFO_user | USERINFO_certs; xmlDoc *user_xml = NULL, *srch_xml = NULL; - xmlNode *srch_root = NULL; + xmlNode *srch_root = NULL, *fmap_n = NULL; + xmlChar flags[34]; + #ifdef FIREWALL const char *xsltparams[] = {"view", NULL, "firewall", "'1'", "view_digest", "'0'", NULL}; #else @@ -273,10 +301,14 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); - // Create a fieldMapping XML document, used for searching the user database - eurephiaXML_CreateDoc(ctx, 1, "fieldMapping", &srch_xml, &srch_root); - xmlNewProp(srch_root, (xmlChar *) "table", (xmlChar *)"users"); // Which table to search in + // Create a UserAccount query XML document + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &srch_xml, &srch_root); + xmlNewProp(srch_root, (xmlChar*) "mode", (xmlChar *) "view"); + + // Setup the fieldMapping - to narrow the search + fmap_n = xmlNewChild(srch_root, NULL, (xmlChar *) "fieldMapping", NULL); + xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *)"users"); // Argument parsing crit_set = 0; @@ -287,7 +319,7 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int fprintf(stderr, "%s: Invalid user id\n", MODULE); return 1; } - xmlNewChild(srch_root, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]); + xmlNewChild(fmap_n, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]); crit_set++; break; @@ -296,7 +328,7 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int fprintf(stderr, "%s: User name too short\n", MODULE); return 1; } - xmlNewChild(srch_root, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]); + xmlNewChild(fmap_n, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]); crit_set++; break; @@ -336,13 +368,32 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int return 1; } - // Search and find the user which was requested - if( (user_xml = eDBadminGetUserInfo(ctx, show_info, srch_xml)) == NULL ) { + xmlStrPrintf(flags, 32, (xmlChar *) "%ld%c", show_info, 0); + xmlNewChild(srch_root, NULL, (xmlChar *) "extractFlags", flags); + + // Do the query against the database + if( (user_xml = eDBadminUserAccount(ctx, srch_xml)) == NULL ) { + xmlFreeDoc(srch_xml); fprintf(stderr, "%s: User not found\n", MODULE); return 1; } xmlFreeDoc(srch_xml); + if( eurephiaXML_IsResultMsg(ctx, user_xml) ) { + eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, user_xml); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + free_nullsafe(ctx, res); + xmlFreeDoc(user_xml); + return 1; + } + free_nullsafe(ctx, res); + } else { + xmlFreeDoc(user_xml); + fprintf(stderr, "%s: Unknown error\n", MODULE); + return 2; + } + if( show_info & USERINFO_user ) { xsltparams[1] = "'userinfo'"; xslt_print_xmldoc(stdout, cfg, user_xml, "users.xsl", xsltparams); @@ -363,12 +414,14 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int xsltparams[1] = "'details'"; } - user_n = eurephiaXML_getRoot(ctx, user_xml, "user", 1); + user_n = eurephiaXML_getRoot(ctx, user_xml, "UserAccount", 1); + user_n = xmlFindNode(user_n, "Account"); if( user_n == NULL ) { fprintf(stderr, "Could not retrieve valid data\n"); xmlFreeDoc(user_xml); return 1; } + printf("** Lastlog entries for %s\n\n", xmlGetNodeContent(user_n, "username")); xslt_print_xmldoc(stdout, cfg, user_xml, "lastlog.xsl", xsltparams); @@ -387,8 +440,6 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int } - - /** * This function handles activation, deactivation and deletion of an account * @@ -401,11 +452,12 @@ int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int * @return returns 0 on success, otherwise 1. */ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { - xmlDoc *user_xml = NULL, *update_xml = NULL, *srch_xml = NULL, *tmp_xml = NULL; - xmlNode *user_n = NULL, *update_n = NULL, *srch_root = NULL, *tmp_n = NULL; + xmlDoc *user_xml = NULL, *update_xml = NULL, *srch_xml = NULL, *tmp_xml = NULL, *res_xml = NULL; + xmlNode *user_n = NULL, *update_n = NULL, *srch_root = NULL, *tmp_n = NULL, *fmap_n = NULL; eurephiaRESULT *res = NULL; char *uid_str = NULL, *activated = NULL, *deactivated = NULL, *actmode_str = NULL, *newpwd = NULL; int i, actmode = 0, rc = 0, crit_set = 0; + xmlChar flags[34]; e_options activargs[] = { {"--uid", "-i", 1}, @@ -434,9 +486,16 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * return 1; } - // Create a fieldMapping XML document, used for searching the user database - eurephiaXML_CreateDoc(ctx, 1, "fieldMapping", &srch_xml, &srch_root); - xmlNewProp(srch_root, (xmlChar *) "table", (xmlChar *)"users"); // Which table to search in + // Create a UserAccount query XML document + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &srch_xml, &srch_root); + xmlNewProp(srch_root, (xmlChar*) "mode", (xmlChar *) "view"); + + // Setup the fieldMapping - to narrow the search + fmap_n = xmlNewChild(srch_root, NULL, (xmlChar *) "fieldMapping", NULL); + xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *)"users"); + + xmlStrPrintf(flags, 32, (xmlChar *) "%ld%c", USERINFO_user, 0); + xmlNewChild(srch_root, NULL, (xmlChar *) "extractFlags", flags); // Argument parsing crit_set = 0; @@ -447,7 +506,7 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * fprintf(stderr, "%s: Invalid user id\n", MODULE); return 1; } - xmlNewChild(srch_root, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]); + xmlNewChild(fmap_n, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]); crit_set++; break; @@ -456,7 +515,7 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * fprintf(stderr, "%s: User name too short\n", MODULE); return 1; } - xmlNewChild(srch_root, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]); + xmlNewChild(fmap_n, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]); crit_set++; break; @@ -489,29 +548,40 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * return 1; } - // Search and find the user which was requested - if( (user_xml = eDBadminGetUserInfo(ctx, USERINFO_user, srch_xml)) == NULL ) { - fprintf(stderr, "%s: User not found\n", MODULE); + // Do the query against the database + if( (user_xml = eDBadminUserAccount(ctx, srch_xml)) == NULL ) { xmlFreeDoc(srch_xml); + fprintf(stderr, "%s: User not found\n", MODULE); return 1; } xmlFreeDoc(srch_xml); - // Parse the user information we received - user_n = eurephiaXML_getRoot(ctx, user_xml, "user", 1); + if( eurephiaXML_IsResultMsg(ctx, user_xml) ) { + eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, user_xml); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + free_nullsafe(ctx, res); + xmlFreeDoc(user_xml); + return 1; + } + free_nullsafe(ctx, res); + } + + user_n = eurephiaXML_getRoot(ctx, user_xml, "UserAccount", 1); + user_n = xmlFindNode(user_n, "Account"); if( user_n == NULL ) { - eurephia_log(ctx, LOG_ERROR, 0, "%s: Could not find user node in the XML document", MODULE); xmlFreeDoc(user_xml); + fprintf(stderr, "%s: No user account information found\n", MODULE); return 1; } - uid_str = xmlGetAttrValue(user_n->properties, "uid"); activated = defaultValue(xmlGetNodeContent(user_n, "activated"), NULL); deactivated = defaultValue(xmlGetNodeContent(user_n, "deactivated"), NULL); // Create a new XML document which will be used to update the user account - eurephiaXML_CreateDoc(ctx, 1, "update_user", &update_xml, &update_n); + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &update_xml, &update_n); assert( (update_xml != NULL) && (update_n != NULL) ); + xmlNewProp(update_n, (xmlChar *) "mode", (xmlChar *) "update"); xmlNewProp(update_n, (xmlChar *) "uid", (xmlChar *) uid_str); // Add fieldMapping - to correctly map eurephia fields into the database fields @@ -521,7 +591,7 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * switch( actmode ) { case 'a': // Activate a user account if( (activated != NULL) && (deactivated == NULL) ) { - printf("User account is already active\n"); + printf("%s: User account is already active\n", MODULE); goto exit; } else { // Set activated field to now() @@ -534,7 +604,7 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * } // Do the update of the user account - rc = eDBadminUpdateUser(ctx, atoi_nullsafe(uid_str), update_xml); + res_xml = eDBadminUserAccount(ctx, update_xml); break; case 'd': // Deactivate a user account @@ -552,7 +622,7 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * } // Do the update of the user account - rc = eDBadminUpdateUser(ctx, atoi_nullsafe(uid_str), update_xml); + res_xml = eDBadminUserAccount(ctx, update_xml); break; case 'p': // Change password for a user @@ -587,7 +657,7 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * // Update with new password tmp_n = xmlNewChild(update_n, NULL, (xmlChar *) "password", (xmlChar *)newpwd); xmlNewProp(tmp_n, (xmlChar *) "pwhash", (xmlChar *) "none"); - rc = eDBadminUpdateUser(ctx, atoi_nullsafe(uid_str), update_xml); + res_xml = eDBadminUserAccount(ctx, update_xml); free_nullsafe(ctx, newpwd); break; @@ -595,12 +665,27 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * case 'D': // Delete user account xmlFreeDoc(update_xml); // We need another XML doc to delete users - eurephiaXML_CreateDoc(ctx, 1, "delete_user", &update_xml, &update_n); + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &update_xml, &update_n); assert( (update_xml != NULL) && (update_n != NULL) ); + xmlNewProp(update_n, (xmlChar *) "mode", (xmlChar *) "delete"); xmlNewProp(update_n, (xmlChar *) "uid", (xmlChar *) uid_str); + update_n = xmlNewChild(update_n, NULL, (xmlChar *) "fieldMapping", NULL); + xmlNewProp(update_n, (xmlChar *) "table", (xmlChar *) "users"); - rc = eDBadminDeleteUser(ctx, atoi_nullsafe(uid_str), update_xml); + res_xml = eDBadminUserAccount(ctx, update_xml); + // Check if this update failed and abort further operations if it did + if( eurephiaXML_IsResultMsg(ctx, res_xml) ) { + res = eurephiaXML_ParseResultMsg(ctx, res_xml); + if( (res == NULL) || (res->resultType == exmlERROR) ) { + free_nullsafe(ctx, res); + break; + } + free_nullsafe(ctx, res); + } else { + // No ResultMsg document was returned, which is also wrong. + break; + } // Delete links between certificates associated to this user account xmlFreeDoc(update_xml); eurephiaXML_CreateDoc(ctx, 1, "usercerts", &update_xml, &update_n); @@ -612,31 +697,36 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * xmlNewChild(update_n, NULL, (xmlChar *) "uid", (xmlChar *) uid_str); tmp_xml = eDBadminUserCertsLink(ctx, update_xml); - if( tmp_xml == NULL ) { - fprintf(stderr, "%s: Failed to remove the user-certs link\n", MODULE); - } - res = eurephiaXML_ParseResultMsg(ctx, tmp_xml); if( res == NULL ) { fprintf(stderr, "%s: Failed to remove user <-> certificate link. " "No results received\n", MODULE); rc = 0; + } else if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); } else { - if( res->resultType == exmlERROR ) { - fprintf(stderr, "%s: %s\n", MODULE, res->message); - }; + fprintf(stdout, "%s: %s\n", MODULE, res->message); rc = 1; - free_nullsafe(ctx, res); } + free_nullsafe(ctx, res); xmlFreeDoc(tmp_xml); break; } - if( rc == 1 ) { - printf("%s: User account is %s\n", MODULE, actmode_str); + if( eurephiaXML_IsResultMsg(ctx, res_xml) ) { + eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, res_xml); + if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + rc = 0; + } else { + fprintf(stdout, "%s: %s\n", MODULE, res->message); + rc = 1; + } + free_nullsafe(ctx, res); } else { - fprintf(stderr, "%s: Operation failed\n", MODULE); + fprintf(stderr, "%s: Unknown error\n", MODULE); } + xmlFreeDoc(res_xml); exit: xmlFreeDoc(user_xml); @@ -657,8 +747,9 @@ int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES * * @return returns 0 on success, otherwise 1. */ int add_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { - xmlDoc *user_xml = NULL; + xmlDoc *user_xml = NULL, *resxml = NULL; xmlNode *node = NULL, *node2 = NULL; + eurephiaRESULT *res = NULL; struct stat cert_stat; int i = 0, certid = 0, uid = 0, certfile_format = CERTFILE_PEM; char *uname = NULL, *passwd = NULL, *certfile = NULL, *digest = NULL; @@ -783,9 +874,10 @@ int add_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int a free_nullsafe(ctx, chkpwd); } - // Prepare add user XML document with fieldMapping - eurephiaXML_CreateDoc(ctx, 1, "add_user", &user_xml, &node); + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &user_xml, &node); + xmlNewProp(node, (xmlChar *) "mode", (xmlChar *) "add"); + node = xmlNewChild(node, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(node, (xmlChar *) "table", (xmlChar *) "users"); @@ -794,15 +886,38 @@ int add_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int a xmlNewProp(node2, (xmlChar *) "pwhash", (xmlChar *) "none"); // Add the user - uid = eDBadminAddUser(ctx, user_xml); - if( uid > 0 ) { - fprintf(stdout, "%s: User registered successfully (user id %i)\n", MODULE, uid); - } else { - fprintf(stderr, "%s: Failed to register user\n", MODULE); - } + resxml = eDBadminUserAccount(ctx, user_xml); + xmlFreeDoc(user_xml); memset(passwd, 0, strlen_nullsafe(passwd)); free_nullsafe(ctx, passwd); - xmlFreeDoc(user_xml); + if( (resxml == NULL) || !eurephiaXML_IsResultMsg(ctx, resxml) ) { + fprintf(stderr, "%s: Failed to register the user. Unknown failure.\n", MODULE); + return 1; + } + + res = eurephiaXML_ParseResultMsg(ctx, resxml); + if( res == NULL ) { + fprintf(stderr, "%s: Failed to register the user. No results returned.\n", MODULE); + xmlFreeDoc(resxml); + return 1; + } else if( res->resultType == exmlERROR ) { + fprintf(stderr, "%s: %s\n", MODULE, res->message); + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); + return 1; + } + + if( xmlStrcmp(res->details->children->name, (xmlChar *) "UserAccount") != 0 ) { + fprintf(stderr, "%s: Invalid result value. User account might be registered\n", MODULE); + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); + return 1; + } + + fprintf(stdout, "%s: %s\n", MODULE, res->message); + uid = atoi_nullsafe(xmlGetAttrValue(res->details->properties, "uid")); + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); if( (digest != NULL) || (certfile != NULL) ) { if( digest != NULL ) { diff --git a/eurephiadm/eurephiadm.c b/eurephiadm/eurephiadm.c index 21d39e2..1429f24 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 @@ -454,9 +567,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) { @@ -468,16 +578,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); diff --git a/utils/eurephia_init.c b/utils/eurephia_init.c index 00f6404..06d13b8 100644 --- a/utils/eurephia_init.c +++ b/utils/eurephia_init.c @@ -209,7 +209,7 @@ static int config_set(eurephiaCTX *ctx, const char *key, const char *val) { * @return Returns 1 on success, otherwise 0. */ int setup_admin_account(eurephiaCTX *ctx) { - xmlDoc *xmldoc = NULL; + xmlDoc *xmldoc = NULL, *resxml = NULL; xmlNode *node = NULL, *node2 = NULL; int uid = 0, i; char uname[66], pwd1[66], pwd2[66]; @@ -219,20 +219,32 @@ int setup_admin_account(eurephiaCTX *ctx) { printf("------------------------------------------------------------------------------\n\n"); printf("Checking database for user accounts ... "); - xmldoc = eDBadminGetUserList(ctx, NULL); - node = eurephiaXML_getRoot(ctx, xmldoc, "userlist", 1); + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &xmldoc, &node); + assert( (xmldoc != NULL) && (node != NULL) ); + xmlNewProp(node, (xmlChar *) "mode", (xmlChar *) "view"); + + node = xmlNewChild(node, NULL, (xmlChar *) "fieldMapping", NULL); + assert( node != NULL ); + xmlNewProp(node, (xmlChar *) "table", (xmlChar *) "users"); + + resxml = eDBadminUserAccount(ctx, xmldoc); + node = eurephiaXML_getRoot(ctx, resxml, "UserAccount", 1); if( node == NULL ) { fprintf(stderr, "Could not retrieve valid data\n"); xmlFreeDoc(xmldoc); + xmlFreeDoc(resxml); return 0; } - if( node->children != NULL ) { + node = xmlFindNode(node, "Account"); + if( (node != NULL) ) { printf("User accounts found, aborting. eurephia is already initialised\n"); xmlFreeDoc(xmldoc); + xmlFreeDoc(resxml); return 0; } xmlFreeDoc(xmldoc); xmldoc = NULL; + xmlFreeDoc(resxml); resxml = NULL; printf("None found. Good!\n"); get_console_input(uname, 64, "Admin username: ", 0); @@ -252,7 +264,8 @@ int setup_admin_account(eurephiaCTX *ctx) { } memset(pwd2, 0, 66); - eurephiaXML_CreateDoc(ctx, 1, "add_user", &xmldoc, &node); + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &xmldoc, &node); + xmlNewProp(node, (xmlChar *) "mode", (xmlChar *) "add"); node = xmlNewChild(node, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(node, (xmlChar *) "table", (xmlChar *) "users"); @@ -261,18 +274,40 @@ int setup_admin_account(eurephiaCTX *ctx) { xmlNewProp(node2, (xmlChar *) "pwhash", (xmlChar *) "none"); // Add the user - uid = eDBadminAddUser(ctx, xmldoc); + resxml = eDBadminUserAccount(ctx, xmldoc); memset(pwd1, 0, 66); + xmlFreeDoc(xmldoc); - if( uid > 0 ) { - fprintf(stdout, "Admin user account registered successfully (user id %i)\n", uid); - } else { + if( !eurephiaXML_IsResultMsg(ctx, resxml) ) { fprintf(stderr, "Failed to register user\n"); - xmlFreeDoc(xmldoc); + if( resxml ) { + xmlFreeDoc(resxml); + } return 0; - } - xmlFreeDoc(xmldoc); + } else { + eurephiaRESULT *res = NULL; + res = eurephiaXML_ParseResultMsg(ctx, resxml); + switch( res->resultType ) { + case exmlERROR: + fprintf(stderr, "** ERROR ** %s\n", res->message); + uid = 0; + break; + + case exmlRESULT: + fprintf(stdout, "%s\n", res->message); + node = xmlFindNode(res->details, "UserAccount"); + uid = atoi_nullsafe(xmlGetAttrValue(node->properties, "uid")); + break; + } + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); + + if( uid < 1 ) { + fprintf(stderr, "Failed to register user\n"); + return 0; + } + } // Grant all available access levels to the admin account static char *grants[] = { "config", "useradmin", "certadmin", "fwprofiles", @@ -312,7 +347,8 @@ int setup_admin_account(eurephiaCTX *ctx) { // Activate the user account printf("Activating the user account ... "); - eurephiaXML_CreateDoc(ctx, 1, "update_user", &xmldoc, &node); + eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &xmldoc, &node); + xmlNewProp(node, (xmlChar *) "mode", (xmlChar *) "update"); xmlNewProp(node, (xmlChar *) "uid", (xmlChar *) uname); // uid should still be in uname as string // Add fieldMapping - to correctly map eurephia fields into the database fields @@ -320,11 +356,30 @@ int setup_admin_account(eurephiaCTX *ctx) { xmlNewProp(node2, (xmlChar *) "table", (xmlChar *) "users"); xmlNewChild(node2, NULL, (xmlChar *) "activated", (xmlChar *) "CURRENT_TIMESTAMP"); - if( !eDBadminUpdateUser(ctx, uid, xmldoc) ) { + resxml = eDBadminUserAccount(ctx, xmldoc); + if( !eurephiaXML_IsResultMsg(ctx, resxml) ) { printf("FAILED\n"); xmlFreeDoc(xmldoc); + xmlFreeDoc(resxml); return 0; + } else { + eurephiaRESULT *res = NULL; + + res = eurephiaXML_ParseResultMsg(ctx, resxml); + switch( res->resultType ) { + case exmlERROR: + fprintf(stderr, "** ERROR ** %s\n", res->message); + break; + + case exmlRESULT: + break; + } + xmlFreeDoc(resxml); + free_nullsafe(ctx, res); } + + + printf("Done"); xmlFreeDoc(xmldoc); @@ -563,6 +618,7 @@ int main(int argc, char **argv) { int argi = 0; eurephiaVALUES *cfg = NULL; eurephiaCTX *ctx = NULL; + int rc = 0; static e_options argopts[] = { {"--version", "-V", 0}, @@ -582,10 +638,13 @@ int main(int argc, char **argv) { switch( eurephia_getopt(&argi, argc, argv, argopts) ) { case 'V': print_version(argv[0]); - return 0; + rc = 0; + goto exit; + case 'h': print_help(argv[0]); - return 0; + rc = 0; + goto exit; case 'l': eAdd_value(NULL, cfg, "log", optargs[0]); @@ -612,56 +671,67 @@ int main(int argc, char **argv) { break; default: - return 1; + rc = 1; + goto exit; } } if( eGet_value(cfg, "database_driver") == NULL ) { fprintf(stderr, "Missing required database driver (--database-driver)\n"); - return 2; + rc = 2; + goto exit; } if( eGet_value(cfg, "database_params") == NULL ) { fprintf(stderr, "Missing required database driver parameters (--database-args)\n"); - return 2; + rc = 2; + goto exit; } ctx = eurephiaCTX_init("eurephia_init", NULL, 0, cfg); if( ctx == NULL ) { fprintf(stderr, "Failed to initialise an eurephia context.\n"); - return 3; + rc = 3; + goto exit; } if( !eurephia_ConnectDB(ctx, cfg) ) { fprintf(stderr, "Failed to access the database.\n"); - return 4; + rc = 4; + goto exit; } if( !setup_password_params(ctx, hash_thr_min, hash_thr_max) ) { - return 11; + rc = 11; + goto exit; } if( !setup_admin_account(ctx) ) { - return 12; + rc = 12; + goto exit; } if( !setup_session_params(ctx) ) { - return 13; + rc = 13; + goto exit; } if( !setup_attempt_limits(ctx) ) { - return 14; + rc = 14; + goto exit; } #ifdef FW_IPTABLES if( !setup_iptables(ctx) ){ - return 15; + rc = 15; + goto exit; } #endif printf("\neurephia is now configured. For further changes, please use the eurephiadm utility.\n\n"); + exit: eFree_values(ctx, cfg); eurephiaCTX_destroy(ctx); return 0; diff --git a/xslt/eurephiadm/certificates.xsl b/xslt/eurephiadm/certificates.xsl index c79dae2..945c939 100644 --- a/xslt/eurephiadm/certificates.xsl +++ b/xslt/eurephiadm/certificates.xsl @@ -24,10 +24,10 @@ <xsl:strip-space elements="*"/> <xsl:template match="/eurephia"> - <xsl:apply-templates select="certificates|user/certificates"/> + <xsl:apply-templates select="certificates|UserAccount/Account/certificates"/> </xsl:template> - <xsl:template match="/eurephia/certificates|/eurephia/user/certificates"> + <xsl:template match="/eurephia/certificates|/eurephia/UserAccount/Account/certificates"> <xsl:text> ID (D) Common name Organisation </xsl:text> <xsl:text> e-mail Registered </xsl:text> <xsl:if test="$view_digest = '1'"> diff --git a/xslt/eurephiadm/lastlog.xsl b/xslt/eurephiadm/lastlog.xsl index da5ac7c..5484ce3 100644 --- a/xslt/eurephiadm/lastlog.xsl +++ b/xslt/eurephiadm/lastlog.xsl @@ -26,10 +26,10 @@ <xsl:template match="/eurephia"> <xsl:choose> <xsl:when test="$view = 'list'"> - <xsl:apply-templates select="lastlog|user/lastlog" mode="list"/> + <xsl:apply-templates select="lastlog|UserAccount/Account/lastlog" mode="list"/> </xsl:when> <xsl:when test="$view = 'details' or $view = 'details2'"> - <xsl:apply-templates select="lastlog|user/lastlog" mode="details"/> + <xsl:apply-templates select="lastlog|UserAccount/Account/lastlog" mode="details"/> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes">Invalid view: <xsl:value-of select="$view"/></xsl:message> diff --git a/xslt/eurephiadm/users.xsl b/xslt/eurephiadm/users.xsl index cae7a66..6ded6f6 100644 --- a/xslt/eurephiadm/users.xsl +++ b/xslt/eurephiadm/users.xsl @@ -26,13 +26,13 @@ <xsl:template match="/eurephia"> <xsl:choose> <xsl:when test="$view = 'userlist'"> - <xsl:apply-templates select="userlist" mode="userlist"/> + <xsl:apply-templates select="UserAccount" mode="userlist"/> </xsl:when> <xsl:when test="$view = 'userinfo'"> - <xsl:apply-templates select="user" mode="userinfo"/> + <xsl:apply-templates select="UserAccount/Account" mode="userinfo"/> </xsl:when> <xsl:when test="$view = 'attemptblacklist'"> - <xsl:apply-templates select="user" mode="attemptblacklist"/> + <xsl:apply-templates select="UserAccount/Account" mode="attemptblacklist"/> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes">Invalid view: <xsl:value-of select="$view"/></xsl:message> @@ -40,14 +40,14 @@ </xsl:choose> </xsl:template> - <xsl:template match="/eurephia/userlist" mode="userlist"> + <xsl:template match="/eurephia/UserAccount" mode="userlist"> <xsl:text> ID Username Activated Deactivated Last access </xsl:text> <xsl:text> ------------------------------------------------------------------------------ </xsl:text> - <xsl:apply-templates select="user" mode="userlist"/> + <xsl:apply-templates select="Account" mode="userlist"/> <xsl:text> ------------------------------------------------------------------------------ </xsl:text> </xsl:template> - <xsl:template match="/eurephia/userlist/user" mode="userlist"> + <xsl:template match="/eurephia/UserAccount/Account" mode="userlist"> <xsl:text> </xsl:text> <xsl:call-template name="left-align"> <xsl:with-param name="value" select="@uid"/> @@ -98,7 +98,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="/eurephia/user" mode="userinfo"> + <xsl:template match="/eurephia/UserAccount/Account" mode="userinfo"> <xsl:text> User id: </xsl:text> <xsl:value-of select="@uid"/> <xsl:text> </xsl:text> @@ -142,7 +142,7 @@ <xsl:text> </xsl:text> </xsl:template> - <xsl:template match="/eurephia/user" mode="attemptblacklist"> + <xsl:template match="/eurephia/UserAccount/Account" mode="attemptblacklist"> <xsl:text>Login attempt information: </xsl:text> <xsl:choose> <xsl:when test="count(attempts/*) > 0"> |