From 1e6a855038242733fa9e043e0258fbaafce21ea6 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Mon, 7 Jul 2014 09:15:40 +0100 Subject: [PATCH] add session removal by ip --- include/application/application.h | 29 +++++++----- include/http/worker.h | 2 + include/session.h | 13 ++---- src/application/adapter/http/update.c | 7 ++- src/application/application.c | 9 ++-- src/application/session_cleanup.c | 12 +++-- src/application/session_get.c | 67 +++++++++++++++++++++------ src/application/session_start.c | 30 ++++++++++-- src/application/session_stop.c | 25 +++++++++- src/server/handle_accept.c | 19 +++++--- src/session/session.c | 2 + 11 files changed, 160 insertions(+), 55 deletions(-) diff --git a/include/application/application.h b/include/application/application.h index 31b342f..f8daff8 100644 --- a/include/application/application.h +++ b/include/application/application.h @@ -42,25 +42,30 @@ struct randval { int value; }; +struct sessinfo { + TR_Hash sessions; + TR_Tree ip_index; +}; + TR_CLASS(Application) { - TR_Hash * active_sessions; + struct sessinfo * active_sessions; time_t session_time_ofs; Auth auth; - struct randval * val; + struct randval * val; - Storage users; - Storage passwords; - Storage roles; + Storage users; + Storage passwords; + Storage roles; - TR_Uuid user_namespace; + TR_Uuid user_namespace; - TR_Hash roles_user_index; - TR_Hash roles_resource_index; + TR_Hash roles_user_index; + TR_Hash roles_resource_index; - const char * version; - const char * loc; + const char * version; + const char * loc; }; int applicationLogin(Application, Credential, Session); @@ -70,8 +75,8 @@ TR_Uuid applicationUpdateUser(Application, User); User applicationGetUser(Application, TR_Uuid); int applicationUpdatePassword(Application, Credential, User); -Session applicationSessionStart(Application); -Session applicationSessionGet(Application, const char *); +Session applicationSessionStart(Application, uint32_t); +Session applicationSessionGet(Application, const char *, uint32_t); void applicationSessionStop(Application, Session); void applicationSessionCleanup(Application, time_t); diff --git a/include/http/worker.h b/include/http/worker.h index 906a29d..81ac0f4 100644 --- a/include/http/worker.h +++ b/include/http/worker.h @@ -29,6 +29,7 @@ #include "trbase.h" #include "trdata.h" +#include "trio.h" #include "http/parser.h" #include "http/writer.h" #include "session.h" @@ -39,6 +40,7 @@ TR_CLASS(HttpWorker) { char * id; + TR_Sock socket; TR_Cbuf pbuf; TR_Hash asset_pool; diff --git a/include/session.h b/include/session.h index 156c0af..b0b7498 100644 --- a/include/session.h +++ b/include/session.h @@ -24,6 +24,7 @@ #define __SESSION_H__ #include +#include #include #include @@ -54,16 +55,7 @@ * This sums up to 10GB of used memory within the 5 minutes * session livetime. * - * @TODO - * One possible solution is to prevent the creation of sessions - * for subsequent requests from the same connection or ip within - * a given time range. This time range should be the session - * livetime. This would effectively prevent such malicious requests - * from doing harm but also prevents non attackers that did a - * first request from another client (lets say telnet) from getting - * a session in their browser. This might be accaptable if the user - * gets a fitting error message. - * To prevent this we could associate the session with the ip it was + * To prevent this I associate the session with the ip it was * created on. If there then is a subsequent request from the same ip * without a sessionid, the old session can be removed and a new one * can be created. This might give a small but acceptable performance @@ -73,6 +65,7 @@ TR_CLASS(Session) { char id[37]; unsigned long hash; + uint32_t ip; time_t livetime; User user; diff --git a/src/application/adapter/http/update.c b/src/application/adapter/http/update.c index d08de8c..1517bcd 100644 --- a/src/application/adapter/http/update.c +++ b/src/application/adapter/http/update.c @@ -23,10 +23,12 @@ #define _GNU_SOURCE #include +#include #include #include "trbase.h" #include "trdata.h" +#include "trio.h" #include "application/application.h" #include "application/adapter/http.h" @@ -58,6 +60,7 @@ applicationAdapterHttpUpdate(void * _this, void * subject) HttpWorker worker = (HttpWorker)subject; Session session = NULL; time_t now = time(NULL); + uint32_t ip = TR_socketGetIp(worker->socket); char * sid; char buf[1000]; @@ -66,10 +69,10 @@ applicationAdapterHttpUpdate(void * _this, void * subject) applicationSessionCleanup(this->application, now); sid = getSessionId(worker->current_request->cookies); - session = applicationSessionGet(this->application, sid); + session = applicationSessionGet(this->application, sid, ip); if (NULL == session) { - session = applicationSessionStart(this->application); + session = applicationSessionStart(this->application, ip); } // send session cookie diff --git a/src/application/application.c b/src/application/application.c index 09cf09c..9cf1c47 100644 --- a/src/application/application.c +++ b/src/application/application.c @@ -57,9 +57,11 @@ applicationCtor(void * _this, va_list * params) this->auth = va_arg(*params, void *); - this->active_sessions = TR_calloc(SESSION_LIVETIME, sizeof(TR_Hash)); + this->active_sessions = TR_calloc( + SESSION_LIVETIME, + sizeof(struct sessinfo)); for (i=0; iactive_sessions[i] = TR_new(TR_Hash); + this->active_sessions[i].sessions = TR_new(TR_Hash); } this->version = VERSION; @@ -76,7 +78,8 @@ applicationDtor(void * _this) size_t i; for (i=0; iactive_sessions[i]); + TR_delete(this->active_sessions[i].sessions); + TR_delete(this->active_sessions[i].ip_index); } TR_MEM_FREE(this->active_sessions); diff --git a/src/application/session_cleanup.c b/src/application/session_cleanup.c index 205e6e6..ec57fc8 100644 --- a/src/application/session_cleanup.c +++ b/src/application/session_cleanup.c @@ -23,6 +23,7 @@ #define _GNU_SOURCE #include +#include #include #include "trdata.h" @@ -43,23 +44,26 @@ applicationSessionCleanup(Application this, time_t now) } if (0 < expired && SESSION_LIVETIME > expired) { - TR_Hash * tmp_buf = TR_calloc(SESSION_LIVETIME, sizeof(TR_Hash)); + struct sessinfo * tmp_buf = TR_calloc( + SESSION_LIVETIME, + sizeof(struct sessinfo)); memcpy( &(tmp_buf[expired]), this->active_sessions, - (SESSION_LIVETIME - expired) * sizeof(TR_Hash)); + (SESSION_LIVETIME - expired) * sizeof(struct sessinfo)); memcpy( tmp_buf, &(this->active_sessions[SESSION_LIVETIME - expired]), - expired * sizeof(TR_Hash)); + expired * sizeof(struct sessinfo)); TR_MEM_FREE(this->active_sessions); this->active_sessions = tmp_buf; } for (i=0; iactive_sessions[i]); + TR_treeDestroy(&(this->active_sessions[i].ip_index), NULL); + TR_hashCleanup(this->active_sessions[i].sessions); } this->session_time_ofs = now; diff --git a/src/application/session_get.c b/src/application/session_get.c index 097198e..e611250 100644 --- a/src/application/session_get.c +++ b/src/application/session_get.c @@ -23,37 +23,76 @@ #define _GNU_SOURCE #include +#include + +#include +#include #include "trdata.h" #include "session.h" #include "application/application.h" +static +inline + int +sessionIpIndexComp(const void * a, const void * b) +{ + Session sess_a = (Session)a; + uint32_t ip = *(uint32_t *)b; + + if (sess_a->ip < ip) { + return -1; + } + + if (sess_a->ip > ip) { + return 1; + } + + return 0; +} Session -applicationSessionGet(Application this, const char * sid) +applicationSessionGet(Application this, const char * sid, uint32_t ip) { Session sess = NULL; int index; - if (NULL != sid) { - /** - * now get the session if not expired - */ - for (index=0; indexactive_sessions)[index], sid, 36); - if (NULL != sess) { - break; - } + (this->active_sessions)[index].sessions, sid, 36); } - /** - * update livetime of session if found - */ if (NULL != sess) { + /** + * update livetime of session if found + */ sess->livetime = this->session_time_ofs + SESSION_LIVETIME; - TR_hashAdd((this->active_sessions)[0], sess); + sess = (Session)TR_treeDelete( + &((this->active_sessions)[index].ip_index), + &ip, sessionIpIndexComp); + TR_hashAdd((this->active_sessions)[0].sessions, sess); + TR_treeInsert( + &((this->active_sessions)[0].ip_index), + sess, + sessionIpIndexComp); + break; + } else { + sess = (Session)TR_treeDelete( + &((this->active_sessions)[index].ip_index), + &ip, sessionIpIndexComp); + if (NULL != sess) { + // we have a previous session from this ip, remove it. + TR_hashDelete( + (this->active_sessions)[index].sessions, + sess->id, 36); + TR_delete(sess); + break; + } } } diff --git a/src/application/session_start.c b/src/application/session_start.c index aee94d6..97c45cd 100644 --- a/src/application/session_start.c +++ b/src/application/session_start.c @@ -23,6 +23,7 @@ #define _GNU_SOURCE #include +#include #include #include "trbase.h" @@ -32,12 +33,35 @@ #include "application/application.h" +static +inline +int +sessionIpIndexComp(const void * a, const void * b) +{ + Session sess_a = (Session)a; + Session sess_b = (Session)b; + + if (sess_a->ip < sess_b->ip) { + return -1; + } + + if (sess_a->ip > sess_b->ip) { + return 1; + } + + return 0; +} + Session -applicationSessionStart(Application this) +applicationSessionStart(Application this, uint32_t ip) { - Session sess = TR_new(Session); + Session sess = TR_new(Session, ip); - TR_hashAdd((this->active_sessions)[0], sess); + TR_hashAdd((this->active_sessions)[0].sessions, sess); + TR_treeInsert( + &((this->active_sessions)[0].ip_index), + sess, + sessionIpIndexComp); return sess; } diff --git a/src/application/session_stop.c b/src/application/session_stop.c index 3d91373..5238694 100644 --- a/src/application/session_stop.c +++ b/src/application/session_stop.c @@ -29,6 +29,24 @@ #include "session.h" #include "application/application.h" +static +inline +int +sessionIpIndexComp(const void * a, const void * b) +{ + Session sess_a = (Session)a; + Session sess_b = (Session)b; + + if (sess_a->ip < sess_b->ip) { + return -1; + } + + if (sess_a->ip > sess_b->ip) { + return 1; + } + + return 0; +} void applicationSessionStop(Application this, Session session) @@ -37,7 +55,12 @@ applicationSessionStop(Application this, Session session) (session->livetime - this->session_time_ofs); if (SESSION_LIVETIME > index) { - TR_hashDeleteByVal((this->active_sessions)[index], session->hash); + TR_hashDeleteByVal( + (this->active_sessions)[index].sessions, + session->hash); + TR_treeDelete( + &((this->active_sessions)[index].ip_index), + session, sessionIpIndexComp); } } diff --git a/src/server/handle_accept.c b/src/server/handle_accept.c index c614263..a4bc2e8 100644 --- a/src/server/handle_accept.c +++ b/src/server/handle_accept.c @@ -69,14 +69,21 @@ serverHandleAccept(Server this, unsigned int i) } // save the socket handle - (this->conns)[acc->handle].sock = acc; + (this->conns)[acc->handle].sock = acc; // clone worker - (this->conns)[acc->handle].worker = TR_clone(this->worker); - (this->conns)[acc->handle].stream = st; - - (this->fds)[this->nfds].fd = acc->handle; - (this->fds)[this->nfds].events = POLLIN; + (this->conns)[acc->handle].worker = TR_clone(this->worker); + /** + * TODO + * workers need an interface to set the socket within them... + * as I currently only have http workers I do a cast here + * but this is not future save. + */ + ((HttpWorker)(this->conns)[acc->handle].worker)->socket = acc; + (this->conns)[acc->handle].stream = st; + + (this->fds)[this->nfds].fd = acc->handle; + (this->fds)[this->nfds].events = POLLIN; this->nfds++; } else { TR_delete(acc); diff --git a/src/session/session.c b/src/session/session.c index 83a2ebf..8b8078a 100644 --- a/src/session/session.c +++ b/src/session/session.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ sessionCtor(void * _this, va_list * params) uuid_unparse(uuid, this->id); this->hash = TR_sdbm((unsigned char *)this->id, 36); + this->ip = va_arg(*params, uint32_t); return 0; }