/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2023 Martin Preuss, all rights reserved. * * The license for this file can be found in the file COPYING which you * should have received along with this file. ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif //#define DISABLE_DEBUGLOG #include "aqhome/http/httpservice_conf.h" #include "aqhome/http/httpservice_p.h" #include #include #include #include #include #include #include #include #include #define AQH_HTTP_SERVICE_FILE_CONFIG "service.conf" #define AQH_HTTP_SERVICE_DIR_MODS "modules" #define AQH_HTTP_SERVICE_DIR_USERS "users" #define AQH_HTTP_SERVICE_DIR_SESSIONS "sessions" #ifdef GWEN_INHERIT_REF GWEN_INHERIT_REF(AQH_SERVICE, AQH_HTTP_SERVICE) #else extern uint32_t AQH_HTTP_SERVICE_ID; #endif /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void _calculateUserPerms(AQH_SERVICE *sv, AQH_USER *user); static void _calculateModuleUserPerms(AQH_SERVICE *sv, AQH_MODULE_PERMS *p); static AQH_MODULE *_ensureModule(AQH_SERVICE *sv, const char *modName); static AQH_USER *_ensureUser(AQH_SERVICE *sv, const char *alias); static AQH_SESSION *_ensureSession(AQH_SERVICE *sv, const char *sessionUid); static GWEN_BUFFER *_getConfigFilePath(const AQH_SERVICE *sv, const char *fileName); static GWEN_BUFFER *_getModuleFilePath(const AQH_SERVICE *sv, const char *modName); static GWEN_BUFFER *_getUserFilePath(const AQH_SERVICE *sv, const char *userAlias); static GWEN_BUFFER *_getSessionFilePath(const AQH_SERVICE *sv, const char *sessionUid); static GWEN_BUFFER *_getSessionFolder(const AQH_SERVICE *sv); static int _checkUser(const AQH_USER *user, int ignoreMissingId); static int _checkSession(const AQH_SESSION *session); static int _checkModule(const AQH_MODULE *m, int ignoreMissingId); static int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId); static int _writeDbFile(const char *fname, GWEN_DB_NODE *db); static AQH_SESSION_LIST *_readAllSessionsIntoList(const AQH_SERVICE *sv); static AQH_SESSION *_readSessionFromFile(const char *filename); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ int AQH_HttpService_LoadConfig(AQH_SERVICE *sv) { AQH_HTTP_SERVICE *xsv; GWEN_BUFFER *nameBuf; int rv; GWEN_DB_NODE *db; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return GWEN_ERROR_INVALID; } db=GWEN_DB_Group_new("service"); nameBuf=_getConfigFilePath(sv, AQH_HTTP_SERVICE_FILE_CONFIG); rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(nameBuf); GWEN_DB_Group_free(db); return rv; } GWEN_Buffer_free(nameBuf); xsv->lastModuleId=GWEN_DB_GetIntValue(db, "lastModuleId", 0, 0); xsv->lastUserId=GWEN_DB_GetIntValue(db, "lastUserId", 0, 0); xsv->maxSessionAgeInSecs=GWEN_DB_GetIntValue(db, "maxSessionAgeInSecs", 0, AQH_HTTP_SERVICE_DEFAULT_MAXSESSIONAGE); GWEN_DB_Group_free(db); return 0; } int AQH_HttpService_SaveConfig(const AQH_SERVICE *sv) { AQH_HTTP_SERVICE *xsv; int rv; GWEN_BUFFER *nameBuf; GWEN_DB_NODE *db; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return GWEN_ERROR_INVALID; } db=GWEN_DB_Group_new("service"); GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "lastModuleId", xsv->lastModuleId); GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "lastUserId", xsv->lastUserId); GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "maxSessionAgeInSecs", xsv->maxSessionAgeInSecs); nameBuf=_getConfigFilePath(sv, AQH_HTTP_SERVICE_FILE_CONFIG); rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db); GWEN_Buffer_free(nameBuf); GWEN_DB_Group_free(db); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } return 0; } AQH_MODULE *AQH_HttpService_GetModule(AQH_SERVICE *sv, const char *modName) { AQH_HTTP_SERVICE *xsv; AQH_MODULE *m; int rv; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return NULL; } rv=GWEN_Mutex_Lock(xsv->moduleMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on module mutex"); return NULL; } m=_ensureModule(sv, modName); rv=GWEN_Mutex_Unlock(xsv->moduleMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on module mutex"); return NULL; } if (m==NULL) { DBG_INFO(AQH_LOGDOMAIN, "here"); return NULL; } return m; } AQH_USER *AQH_HttpService_GetUser(AQH_SERVICE *sv, const char *alias) { AQH_HTTP_SERVICE *xsv; AQH_USER *user; int rv; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return NULL; } rv=GWEN_Mutex_Lock(xsv->userMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on user mutex"); return NULL; } user=_ensureUser(sv, alias); rv=GWEN_Mutex_Unlock(xsv->userMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on user mutex"); return NULL; } if (user==NULL) { DBG_INFO(AQH_LOGDOMAIN, "here"); return NULL; } return user; } int AQH_HttpService_WriteUser(const AQH_SERVICE *sv, const AQH_USER *user) { AQH_HTTP_SERVICE *xsv; int rv; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return GWEN_ERROR_INVALID; } rv=GWEN_Mutex_Lock(xsv->userMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on user mutex"); return rv; } rv=AQH_HttpService_SaveUser(sv, user); if (rv<0) { GWEN_Mutex_Unlock(xsv->userMutex); DBG_ERROR(AQH_LOGDOMAIN, "Error saving user \"%s\" (%d)", AQH_User_GetAlias(user), rv); return rv; } rv=GWEN_Mutex_Unlock(xsv->userMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on user mutex"); return rv; } return 0; } AQH_SESSION *AQH_HttpService_GetSession(AQH_SERVICE *sv, const char *sessionUid) { AQH_HTTP_SERVICE *xsv; AQH_SESSION *session; int rv; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return NULL; } rv=GWEN_Mutex_Lock(xsv->sessionMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on session mutex"); return NULL; } session=_ensureSession(sv, sessionUid); rv=GWEN_Mutex_Unlock(xsv->sessionMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on session mutex"); return NULL; } if (session==NULL) { DBG_INFO(AQH_LOGDOMAIN, "here"); return NULL; } return session; } int AQH_HttpService_LockSessions(AQH_SERVICE *sv) { AQH_HTTP_SERVICE *xsv; int rv; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return GWEN_ERROR_GENERIC; } rv=GWEN_Mutex_Lock(xsv->sessionMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on session mutex"); return rv; } return 0; } int AQH_HttpService_UnlockSessions(AQH_SERVICE *sv) { AQH_HTTP_SERVICE *xsv; int rv; xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv); if (xsv==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object"); return GWEN_ERROR_GENERIC; } rv=GWEN_Mutex_Unlock(xsv->sessionMutex); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on session mutex"); return rv; } return 0; } int AQH_HttpService_CleanupSessions(AQH_SERVICE *sv, int maxAgeInSecs) { time_t tNow; AQH_SESSION_LIST *sessionList; int rv; rv=AQH_HttpService_LockSessions(sv); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Error locking sessions (%d)", rv); return rv; } tNow=time(NULL); sessionList=AQH_Service_GetSessionList(sv); if (sessionList) { AQH_SESSION *session; session=AQH_Session_List_First(sessionList); while(session) { AQH_SESSION *next; const GWEN_TIMESTAMP *ts; next=AQH_Session_List_Next(session); ts=AQH_Session_GetTimestampLastAccess(session); if (ts==NULL) ts=AQH_Session_GetTimestampCreation(session); if (ts) { time_t diff; diff=tNow-GWEN_Timestamp_toTimeT(ts); if (((int)diff)>maxAgeInSecs) { DBG_INFO(AQH_LOGDOMAIN, "Session \"%s\" expired (%d secs)", AQH_Session_GetUid(session), (int) diff); rv=AQH_HttpService_DelSession(sv, session); /* frees session!! */ if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); } } } session=next; } } rv=AQH_HttpService_UnlockSessions(sv); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Error unlocking sessions (%d)", rv); return rv; } return 0; } void AQH_HttpService_LoadAllSessions(AQH_SERVICE *sv) { AQH_SESSION_LIST *sessionList; sessionList=_readAllSessionsIntoList(sv); if (sessionList) { AQH_SESSION *session; while( (session=AQH_Session_List_First(sessionList)) ) { const char *sessionUid; const char *userAlias; AQH_Session_List_Del(session); sessionUid=AQH_Session_GetUid(session); userAlias=AQH_Session_GetUserAlias(session); if (userAlias && *userAlias) { AQH_USER *user; user=AQH_HttpService_GetUser(sv, userAlias); if (user==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "User \"%s\" for session \"%s\" not available", userAlias, sessionUid); AQH_Session_free(session); } else { DBG_INFO(AQH_LOGDOMAIN, "Adding session \"%s\" (user=%s)", sessionUid, userAlias); AQH_Session_SetUser(session, user); AQH_Service_AddSession(sv, session); } } else { DBG_ERROR(AQH_LOGDOMAIN, "Session has no user, not adding"); AQH_Session_free(session); } } /* while */ AQH_Session_List_free(sessionList); } } AQH_MODULE *AQH_HttpService_LoadModule(const AQH_SERVICE *sv, const char *modName) { GWEN_BUFFER *nameBuf; int rv; GWEN_DB_NODE *db; AQH_MODULE *m; db=GWEN_DB_Group_new("user"); nameBuf=_getModuleFilePath(sv, modName); rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(nameBuf); GWEN_DB_Group_free(db); return NULL; } GWEN_Buffer_free(nameBuf); m=AQH_Module_fromDb(db); if (m==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Error loading module \"%s\" from config group", modName); GWEN_DB_Group_free(db); return NULL; } GWEN_DB_Group_free(db); rv=_checkModule(m, 0); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Invalid data for module \"%s\"", modName); AQH_Module_free(m); return NULL; } return m; } int AQH_HttpService_SaveModule(const AQH_SERVICE *sv, const AQH_MODULE *m) { int rv; const char *modName; GWEN_BUFFER *nameBuf; GWEN_DB_NODE *db; rv=_checkModule(m, 0); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } db=GWEN_DB_Group_new("module"); rv=AQH_Module_toDb(m, db); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } modName=AQH_Module_GetName(m); nameBuf=_getModuleFilePath(sv, modName); rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db); GWEN_Buffer_free(nameBuf); GWEN_DB_Group_free(db); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } return 0; } int AQH_HttpService_AddModule(AQH_SERVICE *sv, AQH_MODULE *m) { int rv; uint32_t id; AQH_ROLE_LIST *roleList; AQH_ROLE *r; rv=_checkModule(m, 1); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Not adding invalid module (%d)", rv); return rv; } /* assign module id */ id=AQH_HttpService_GetNextModuleId(sv); AQH_Module_SetId(m, id); /* assign role ids */ roleList=AQH_Module_GetRoleList(m); id=1; r=AQH_Role_List_First(roleList); while(r) { AQH_Role_SetId(r, id++); r=AQH_Role_List_Next(r); } rv=AQH_HttpService_SaveModule(sv, m); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error saving module module \"%s\" (%d)", AQH_Module_GetName(m), rv); return rv; } AQH_Service_AddModule(sv, m); return 0; } AQH_USER *AQH_HttpService_LoadUser(const AQH_SERVICE *sv, const char *userAlias) { GWEN_BUFFER *nameBuf; int rv; GWEN_DB_NODE *db; AQH_USER *user; db=GWEN_DB_Group_new("user"); nameBuf=_getUserFilePath(sv, userAlias); rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(nameBuf); GWEN_DB_Group_free(db); return NULL; } GWEN_Buffer_free(nameBuf); user=AQH_User_fromDb(db); if (user==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Error loading user \"%s\" from config group", userAlias); GWEN_DB_Group_free(db); return NULL; } GWEN_DB_Group_free(db); rv=_checkUser(user, 0); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Invalid data for user \"%s\"", userAlias); AQH_User_free(user); return NULL; } return user; } int AQH_HttpService_SaveUser(const AQH_SERVICE *sv, const AQH_USER *user) { int rv; const char *sAlias; GWEN_BUFFER *nameBuf; GWEN_DB_NODE *db; rv=_checkUser(user, 0); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } db=GWEN_DB_Group_new("user"); rv=AQH_User_toDb(user, db); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } sAlias=AQH_User_GetAlias(user); nameBuf=_getUserFilePath(sv, sAlias); rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db); GWEN_Buffer_free(nameBuf); GWEN_DB_Group_free(db); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } return 0; } int AQH_HttpService_AddUser(AQH_SERVICE *sv, AQH_USER *user) { int rv; uint32_t id; rv=_checkUser(user, 0); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } /* assign user id */ id=AQH_HttpService_GetNextUserId(sv); AQH_User_SetId(user, id); rv=AQH_HttpService_SaveUser(sv, user); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } AQH_Service_AddUser(sv, user); return 0; } int AQH_HttpService_DelUser(AQH_SERVICE *sv, AQH_USER *user) { const char *sAlias; GWEN_BUFFER *nameBuf; uint32_t userId; sAlias=AQH_User_GetAlias(user); userId=AQH_User_GetId(user); nameBuf=_getUserFilePath(sv, sAlias); unlink(GWEN_Buffer_GetStart(nameBuf)); GWEN_Buffer_free(nameBuf); AQH_Service_DelUser(sv, userId); return 0; } AQH_SESSION *AQH_HttpService_LoadSession(const AQH_SERVICE *sv, const char *sessionUid) { GWEN_BUFFER *nameBuf; int rv; AQH_SESSION *session; nameBuf=_getSessionFilePath(sv, sessionUid); if (nameBuf==NULL) { DBG_INFO(AQH_LOGDOMAIN, "here"); return NULL; } session=_readSessionFromFile(GWEN_Buffer_GetStart(nameBuf)); if (session==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Error loading session \"%s\" from config group", sessionUid); GWEN_Buffer_free(nameBuf); return NULL; } GWEN_Buffer_free(nameBuf); rv=_checkSession(session); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Invalid data for session \"%s\"", sessionUid); AQH_Session_free(session); return NULL; } return session; } int AQH_HttpService_SaveSession(const AQH_SERVICE *sv, const AQH_SESSION *session) { int rv; const char *sUid; GWEN_BUFFER *nameBuf; GWEN_DB_NODE *db; rv=_checkSession(session); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } db=GWEN_DB_Group_new("user"); rv=AQH_Session_toDb(session, db); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } sUid=AQH_Session_GetUid(session); nameBuf=_getSessionFilePath(sv, sUid); rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db); GWEN_Buffer_free(nameBuf); GWEN_DB_Group_free(db); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } return 0; } int AQH_HttpService_AddSession(AQH_SERVICE *sv, AQH_SESSION *session) { int rv; rv=_checkSession(session); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } rv=AQH_HttpService_SaveSession(sv, session); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); return rv; } AQH_Service_AddSession(sv, session); return 0; } int AQH_HttpService_DelSession(AQH_SERVICE *sv, AQH_SESSION *session) { const char *uid; GWEN_BUFFER *nameBuf; uid=AQH_Session_GetUid(session); nameBuf=_getSessionFilePath(sv, uid); unlink(GWEN_Buffer_GetStart(nameBuf)); GWEN_Buffer_free(nameBuf); AQH_Service_DelSession(sv, uid); return 0; } GWEN_STRINGLIST *AQH_HttpService_GetFolderFileList(const char *folder, const char *mask, int senseCase) { GWEN_STRINGLIST *sl; int rv; sl=GWEN_StringList_new(); GWEN_StringList_SetSenseCase(sl, senseCase); rv=GWEN_Directory_GetFileEntries(folder, sl, mask); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_StringList_free(sl); return NULL; } if (GWEN_StringList_Count(sl)<1) { DBG_INFO(AQH_LOGDOMAIN, "Empty string list"); GWEN_StringList_free(sl); return NULL; } return sl; } AQH_MODULE *_ensureModule(AQH_SERVICE *sv, const char *modName) { AQH_MODULE *module; module=AQH_Service_GetModuleByName(sv, modName); if (module) return module; module=AQH_HttpService_LoadModule(sv, modName); if (module==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Could not load module \"%s\"", modName); return NULL; } AQH_Service_AddModule(sv, module); return module; } AQH_USER *_ensureUser(AQH_SERVICE *sv, const char *alias) { AQH_USER *user; user=AQH_Service_GetUserByAlias(sv, alias); if (user) return user; user=AQH_HttpService_LoadUser(sv, alias); if (user==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Could not load user \"%s\"", alias); return NULL; } _calculateUserPerms(sv, user); AQH_Service_AddUser(sv, user); return user; } AQH_SESSION *_ensureSession(AQH_SERVICE *sv, const char *sessionUid) { AQH_SESSION *session; session=AQH_Service_GetSessionByUid(sv, sessionUid); if (session) return session; session=AQH_HttpService_LoadSession(sv, sessionUid); if (session) { AQH_USER *user; user=AQH_HttpService_GetUser(sv, AQH_Session_GetUserAlias(session)); if (user==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "User \"%s\" for session \"%s\" not available", AQH_Session_GetUserAlias(session), sessionUid); AQH_Session_free(session); return NULL; } AQH_Session_SetUser(session, user); AQH_Service_AddSession(sv, session); } if (session==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Could not load session \"%s\"", sessionUid); return NULL; } return session; } GWEN_BUFFER *_getConfigFilePath(const AQH_SERVICE *sv, const char *fileName) { const char *configFolder; configFolder=AQH_HttpService_GetConfigFolder(sv); if (!(configFolder && *configFolder)) { DBG_ERROR(AQH_LOGDOMAIN, "No config folder given"); return NULL; } else { GWEN_BUFFER *nameBuf; nameBuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(nameBuf, configFolder); GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S); GWEN_Buffer_AppendString(nameBuf, fileName); return nameBuf; } } GWEN_BUFFER *_getModuleFilePath(const AQH_SERVICE *sv, const char *modName) { const char *configFolder; configFolder=AQH_HttpService_GetConfigFolder(sv); if (!(configFolder && *configFolder)) { DBG_ERROR(AQH_LOGDOMAIN, "No config folder given"); return NULL; } else { GWEN_BUFFER *nameBuf; nameBuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(nameBuf, configFolder); GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_MODS GWEN_DIR_SEPARATOR_S); GWEN_Text_EscapeToBuffer(modName, nameBuf); GWEN_Buffer_AppendString(nameBuf, ".conf"); return nameBuf; } } GWEN_BUFFER *_getUserFilePath(const AQH_SERVICE *sv, const char *userAlias) { const char *configFolder; configFolder=AQH_HttpService_GetConfigFolder(sv); if (!(configFolder && *configFolder)) { DBG_ERROR(AQH_LOGDOMAIN, "No config folder given"); return NULL; } else { GWEN_BUFFER *nameBuf; nameBuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(nameBuf, configFolder); GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_USERS GWEN_DIR_SEPARATOR_S); GWEN_Text_EscapeToBuffer(userAlias, nameBuf); GWEN_Buffer_AppendString(nameBuf, ".conf"); return nameBuf; } } GWEN_BUFFER *_getSessionFilePath(const AQH_SERVICE *sv, const char *sessionUid) { GWEN_BUFFER *nameBuf; nameBuf=_getSessionFolder(sv); if (nameBuf) { GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S); GWEN_Text_EscapeToBuffer(sessionUid, nameBuf); GWEN_Buffer_AppendString(nameBuf, ".conf"); return nameBuf; } return NULL; } int _checkUser(const AQH_USER *user, int ignoreMissingId) { const char *s; if (!ignoreMissingId) { uint32_t id; id=AQH_User_GetId(user); if (id==0) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no id"); return GWEN_ERROR_BAD_DATA; } } s=AQH_User_GetAlias(user); if (!(s && *s)) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no alias"); return GWEN_ERROR_BAD_DATA; } s=AQH_User_GetHashedPassword(user); if (!(s && *s)) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no password"); return GWEN_ERROR_BAD_DATA; } s=AQH_User_GetEmail(user); if (!(s && *s)) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no email"); return GWEN_ERROR_BAD_DATA; } return 0; } int _checkSession(const AQH_SESSION *session) { const char *s; s=AQH_Session_GetUid(session); if (!(s && *s)) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid session: no uid"); return GWEN_ERROR_BAD_DATA; } s=AQH_Session_GetUserAlias(session); if (!(s && *s)) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid session: no user alias"); return GWEN_ERROR_BAD_DATA; } if (AQH_Session_GetTimestampCreation(session)==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid session: no creation time"); return GWEN_ERROR_BAD_DATA; } return 0; } int _checkModule(const AQH_MODULE *m, int ignoreMissingId) { const char *s; const AQH_ROLE_LIST *roleList; int rv; if (!ignoreMissingId) { if (AQH_Module_GetId(m)==0) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid module: missing id"); return GWEN_ERROR_BAD_DATA; } } s=AQH_Module_GetName(m); if (!(s && *s)) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid module: missing name"); return GWEN_ERROR_BAD_DATA; } roleList=AQH_Module_GetRoleList(m); if (roleList==NULL || AQH_Role_List_GetCount(roleList)<1) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid module: empty or missing role list"); return GWEN_ERROR_BAD_DATA; } rv=_checkRoleList(roleList, ignoreMissingId); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid module %s: invalid role definition", AQH_Module_GetName(m)); return rv; } return 0; } int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId) { const AQH_ROLE *r; r=AQH_Role_List_First(roleList); while(r) { const char *s; if (!ignoreMissingId) { if (AQH_Role_GetId(r)==0) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid role: missing id"); return GWEN_ERROR_BAD_DATA; } } s=AQH_Role_GetName(r); if (!(s && *s)) { DBG_ERROR(AQH_LOGDOMAIN, "Invalid role: missing name"); return GWEN_ERROR_BAD_DATA; } r=AQH_Role_List_Next(r); } return 0; } void _calculateUserPerms(AQH_SERVICE *sv, AQH_USER *user) { AQH_MODULE_PERMS_LIST *permList; permList=AQH_User_GetModulePermList(user); if (permList) { AQH_MODULE_PERMS *p; p=AQH_ModulePerms_List_First(permList); while(p) { _calculateModuleUserPerms(sv, p); p=AQH_ModulePerms_List_Next(p); } } AQH_User_AddRuntimeFlags(user, AQH_USER_RTFLAGS_PERMSCALC); } void _calculateModuleUserPerms(AQH_SERVICE *sv, AQH_MODULE_PERMS *p) { uint32_t perms=0; uint32_t addPerms=0; uint32_t delPerms=0; const AQH_MODULE *m; m=AQH_Service_GetModuleById(sv, AQH_ModulePerms_GetModuleId(p)); if (m==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Module \"%d\" not found, ignoring", AQH_ModulePerms_GetModuleId(p)); } else { const AQH_ROLE_LIST *roleList; roleList=AQH_Module_GetRoleList(m); if (roleList) { int i, j; j=AQH_ModulePerms_GetRoleArrayArraySize(); for(i=0; i0) { AQH_ROLE *r; r=AQH_Role_List_GetById(roleList, roleId); if (r==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Role %d not found in module \"%s\", ignoring", roleId, AQH_Module_GetName(m)); } else { DBG_INFO(AQH_LOGDOMAIN, "Module \"%s\": adding perms for role \"%s\"", AQH_Module_GetName(m), AQH_Role_GetName(r)); perms|=AQH_Role_GetPerms(r); addPerms|=AQH_Role_GetExplAddPerms(r); delPerms|=AQH_Role_GetExplDelPerms(r); } } } } } perms|=addPerms; perms&=~delPerms; AQH_ModulePerms_SetPerms(p, perms); } int _writeDbFile(const char *fname, GWEN_DB_NODE *db) { GWEN_BUFFER *tmpFilenameBuf; int rv; tmpFilenameBuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(tmpFilenameBuf, fname); GWEN_Buffer_AppendString(tmpFilenameBuf, ".tmp"); unlink(GWEN_Buffer_GetStart(tmpFilenameBuf)); rv=GWEN_DB_WriteFile(db, GWEN_Buffer_GetStart(tmpFilenameBuf), GWEN_DB_FLAGS_DEFAULT); if (rv<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error writing db file \"%s\": %d", GWEN_Buffer_GetStart(tmpFilenameBuf), rv); GWEN_Buffer_free(tmpFilenameBuf); return rv; } if (rename(GWEN_Buffer_GetStart(tmpFilenameBuf), fname)<0) { DBG_ERROR(AQH_LOGDOMAIN, "Error renaming tmp file to \"%s\": %d (%s)", fname, errno, strerror(errno)); GWEN_Buffer_free(tmpFilenameBuf); return GWEN_ERROR_IO; } unlink(GWEN_Buffer_GetStart(tmpFilenameBuf)); GWEN_Buffer_free(tmpFilenameBuf); return 0; } GWEN_BUFFER *_getSessionFolder(const AQH_SERVICE *sv) { const char *configFolder; configFolder=AQH_HttpService_GetConfigFolder(sv); if (!(configFolder && *configFolder)) { DBG_ERROR(AQH_LOGDOMAIN, "No config folder given"); return NULL; } else { GWEN_BUFFER *nameBuf; nameBuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(nameBuf, configFolder); GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_SESSIONS); return nameBuf; } } AQH_SESSION_LIST *_readAllSessionsIntoList(const AQH_SERVICE *sv) { GWEN_BUFFER *folderBuf; folderBuf=_getSessionFolder(sv); if (folderBuf) { GWEN_STRINGLIST *fileList; fileList=AQH_HttpService_GetFolderFileList(GWEN_Buffer_GetStart(folderBuf), "*.conf", 1); if (fileList) { AQH_SESSION_LIST *sessionList; uint32_t pos; GWEN_STRINGLISTENTRY *se; sessionList=AQH_Session_List_new(); GWEN_Buffer_AppendString(folderBuf, GWEN_DIR_SEPARATOR_S); pos=GWEN_Buffer_GetPos(folderBuf); se=GWEN_StringList_FirstEntry(fileList); while(se) { const char *s; s=GWEN_StringListEntry_Data(se); if (s && *s) { AQH_SESSION *session; GWEN_Buffer_AppendString(folderBuf, s); session=_readSessionFromFile(GWEN_Buffer_GetStart(folderBuf)); if (session==NULL) { DBG_INFO(AQH_LOGDOMAIN, "here"); } else { AQH_Session_List_Add(session, sessionList); } GWEN_Buffer_Crop(folderBuf, 0, pos); } se=GWEN_StringListEntry_Next(se); } if (AQH_Session_List_GetCount(sessionList)<1) { DBG_INFO(NULL, "Empty session list"); AQH_Session_List_free(sessionList); GWEN_StringList_free(fileList); GWEN_Buffer_free(folderBuf); return NULL; } GWEN_StringList_free(fileList); GWEN_Buffer_free(folderBuf); return sessionList; } GWEN_Buffer_free(folderBuf); } return NULL; } AQH_SESSION *_readSessionFromFile(const char *filename) { int rv; GWEN_DB_NODE *db; AQH_SESSION *session; db=GWEN_DB_Group_new("session"); rv=GWEN_DB_ReadFile(db, filename, GWEN_DB_FLAGS_DEFAULT); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); GWEN_DB_Group_free(db); return NULL; } session=AQH_Session_fromDb(db); if (session==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Error loading session from file \"%s\"", filename); GWEN_DB_Group_free(db); return NULL; } GWEN_DB_Group_free(db); return session; }