Browse Source

add session removal by ip

next
Georg Hopp 12 years ago
parent
commit
1e6a855038
  1. 29
      include/application/application.h
  2. 2
      include/http/worker.h
  3. 13
      include/session.h
  4. 7
      src/application/adapter/http/update.c
  5. 9
      src/application/application.c
  6. 12
      src/application/session_cleanup.c
  7. 67
      src/application/session_get.c
  8. 30
      src/application/session_start.c
  9. 25
      src/application/session_stop.c
  10. 19
      src/server/handle_accept.c
  11. 2
      src/session/session.c

29
include/application/application.h

@ -42,25 +42,30 @@ struct randval {
int value; int value;
}; };
struct sessinfo {
TR_Hash sessions;
TR_Tree ip_index;
};
TR_CLASS(Application) { TR_CLASS(Application) {
TR_Hash * active_sessions;
struct sessinfo * active_sessions;
time_t session_time_ofs; time_t session_time_ofs;
Auth auth; 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); int applicationLogin(Application, Credential, Session);
@ -70,8 +75,8 @@ TR_Uuid applicationUpdateUser(Application, User);
User applicationGetUser(Application, TR_Uuid); User applicationGetUser(Application, TR_Uuid);
int applicationUpdatePassword(Application, Credential, User); 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 applicationSessionStop(Application, Session);
void applicationSessionCleanup(Application, time_t); void applicationSessionCleanup(Application, time_t);

2
include/http/worker.h

@ -29,6 +29,7 @@
#include "trbase.h" #include "trbase.h"
#include "trdata.h" #include "trdata.h"
#include "trio.h"
#include "http/parser.h" #include "http/parser.h"
#include "http/writer.h" #include "http/writer.h"
#include "session.h" #include "session.h"
@ -39,6 +40,7 @@
TR_CLASS(HttpWorker) { TR_CLASS(HttpWorker) {
char * id; char * id;
TR_Sock socket;
TR_Cbuf pbuf; TR_Cbuf pbuf;
TR_Hash asset_pool; TR_Hash asset_pool;

13
include/session.h

@ -24,6 +24,7 @@
#define __SESSION_H__ #define __SESSION_H__
#include <time.h> #include <time.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <user.h> #include <user.h>
@ -54,16 +55,7 @@
* This sums up to 10GB of used memory within the 5 minutes * This sums up to 10GB of used memory within the 5 minutes
* session livetime. * 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 * 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 * without a sessionid, the old session can be removed and a new one
* can be created. This might give a small but acceptable performance * can be created. This might give a small but acceptable performance
@ -73,6 +65,7 @@
TR_CLASS(Session) { TR_CLASS(Session) {
char id[37]; char id[37];
unsigned long hash; unsigned long hash;
uint32_t ip;
time_t livetime; time_t livetime;
User user; User user;

7
src/application/adapter/http/update.c

@ -23,10 +23,12 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include "trbase.h" #include "trbase.h"
#include "trdata.h" #include "trdata.h"
#include "trio.h"
#include "application/application.h" #include "application/application.h"
#include "application/adapter/http.h" #include "application/adapter/http.h"
@ -58,6 +60,7 @@ applicationAdapterHttpUpdate(void * _this, void * subject)
HttpWorker worker = (HttpWorker)subject; HttpWorker worker = (HttpWorker)subject;
Session session = NULL; Session session = NULL;
time_t now = time(NULL); time_t now = time(NULL);
uint32_t ip = TR_socketGetIp(worker->socket);
char * sid; char * sid;
char buf[1000]; char buf[1000];
@ -66,10 +69,10 @@ applicationAdapterHttpUpdate(void * _this, void * subject)
applicationSessionCleanup(this->application, now); applicationSessionCleanup(this->application, now);
sid = getSessionId(worker->current_request->cookies); sid = getSessionId(worker->current_request->cookies);
session = applicationSessionGet(this->application, sid);
session = applicationSessionGet(this->application, sid, ip);
if (NULL == session) { if (NULL == session) {
session = applicationSessionStart(this->application);
session = applicationSessionStart(this->application, ip);
} }
// send session cookie // send session cookie

9
src/application/application.c

@ -57,9 +57,11 @@ applicationCtor(void * _this, va_list * params)
this->auth = va_arg(*params, void *); 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; i<SESSION_LIVETIME; i++) { for (i=0; i<SESSION_LIVETIME; i++) {
this->active_sessions[i] = TR_new(TR_Hash);
this->active_sessions[i].sessions = TR_new(TR_Hash);
} }
this->version = VERSION; this->version = VERSION;
@ -76,7 +78,8 @@ applicationDtor(void * _this)
size_t i; size_t i;
for (i=0; i<SESSION_LIVETIME; i++) { for (i=0; i<SESSION_LIVETIME; i++) {
TR_delete(this->active_sessions[i]);
TR_delete(this->active_sessions[i].sessions);
TR_delete(this->active_sessions[i].ip_index);
} }
TR_MEM_FREE(this->active_sessions); TR_MEM_FREE(this->active_sessions);

12
src/application/session_cleanup.c

@ -23,6 +23,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include "trdata.h" #include "trdata.h"
@ -43,23 +44,26 @@ applicationSessionCleanup(Application this, time_t now)
} }
if (0 < expired && SESSION_LIVETIME > expired) { 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( memcpy(
&(tmp_buf[expired]), &(tmp_buf[expired]),
this->active_sessions, this->active_sessions,
(SESSION_LIVETIME - expired) * sizeof(TR_Hash));
(SESSION_LIVETIME - expired) * sizeof(struct sessinfo));
memcpy( memcpy(
tmp_buf, tmp_buf,
&(this->active_sessions[SESSION_LIVETIME - expired]), &(this->active_sessions[SESSION_LIVETIME - expired]),
expired * sizeof(TR_Hash));
expired * sizeof(struct sessinfo));
TR_MEM_FREE(this->active_sessions); TR_MEM_FREE(this->active_sessions);
this->active_sessions = tmp_buf; this->active_sessions = tmp_buf;
} }
for (i=0; i<expired; i++) { for (i=0; i<expired; i++) {
TR_hashCleanup(this->active_sessions[i]);
TR_treeDestroy(&(this->active_sessions[i].ip_index), NULL);
TR_hashCleanup(this->active_sessions[i].sessions);
} }
this->session_time_ofs = now; this->session_time_ofs = now;

67
src/application/session_get.c

@ -23,37 +23,76 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <sys/types.h> #include <sys/types.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include "trdata.h" #include "trdata.h"
#include "session.h" #include "session.h"
#include "application/application.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 Session
applicationSessionGet(Application this, const char * sid)
applicationSessionGet(Application this, const char * sid, uint32_t ip)
{ {
Session sess = NULL; Session sess = NULL;
int index; int index;
if (NULL != sid) {
/**
* now get the session if not expired
*/
for (index=0; index<SESSION_LIVETIME; index++) {
/**
* now get the session if not expired
*/
for (index=0; index<SESSION_LIVETIME; index++) {
if (NULL != sid) {
sess = (Session)TR_hashDelete( sess = (Session)TR_hashDelete(
(this->active_sessions)[index], sid, 36);
if (NULL != sess) {
break;
}
(this->active_sessions)[index].sessions, sid, 36);
} }
/**
* update livetime of session if found
*/
if (NULL != sess) { if (NULL != sess) {
/**
* update livetime of session if found
*/
sess->livetime = this->session_time_ofs + SESSION_LIVETIME; 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;
}
} }
} }

30
src/application/session_start.c

@ -23,6 +23,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include "trbase.h" #include "trbase.h"
@ -32,12 +33,35 @@
#include "application/application.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;
}
Session 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; return sess;
} }

25
src/application/session_stop.c

@ -29,6 +29,24 @@
#include "session.h" #include "session.h"
#include "application/application.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 void
applicationSessionStop(Application this, Session session) applicationSessionStop(Application this, Session session)
@ -37,7 +55,12 @@ applicationSessionStop(Application this, Session session)
(session->livetime - this->session_time_ofs); (session->livetime - this->session_time_ofs);
if (SESSION_LIVETIME > index) { 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);
} }
} }

19
src/server/handle_accept.c

@ -69,14 +69,21 @@ serverHandleAccept(Server this, unsigned int i)
} }
// save the socket handle // save the socket handle
(this->conns)[acc->handle].sock = acc;
(this->conns)[acc->handle].sock = acc;
// clone worker // 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++; this->nfds++;
} else { } else {
TR_delete(acc); TR_delete(acc);

2
src/session/session.c

@ -23,6 +23,7 @@
#include <time.h> #include <time.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
@ -47,6 +48,7 @@ sessionCtor(void * _this, va_list * params)
uuid_unparse(uuid, this->id); uuid_unparse(uuid, this->id);
this->hash = TR_sdbm((unsigned char *)this->id, 36); this->hash = TR_sdbm((unsigned char *)this->id, 36);
this->ip = va_arg(*params, uint32_t);
return 0; return 0;
} }

Loading…
Cancel
Save