sec-mod: separated expiration from creation time fields

That allows to set explicit expiration of the cookie, and
ensure that we can close a session in a way that we provide
a limited time window for it to re-open. That handles anyconnect
client compatibility; this client terminates and reconnects
using the original cookie, multiple times.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
This commit is contained in:
Nikos Mavrogiannopoulos
2017-12-09 10:56:41 +01:00
committed by Nikos Mavrogiannopoulos
parent c4a8b21aad
commit 8253cc2920
4 changed files with 31 additions and 13 deletions

View File

@@ -143,7 +143,7 @@ int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTH
}
/* calculate time in auth for this client */
update_auth_time_stats(sec, time(0) - entry->time);
update_auth_time_stats(sec, time(0) - entry->created);
msg.has_sid = 1;
msg.sid.data = entry->sid;
@@ -521,7 +521,8 @@ int handle_secm_session_open_cmd(sec_mod_st *sec, int fd, const SecmSessionOpenM
talloc_free(lpool);
seclog(sec, LOG_INFO, "initiating session for user '%s' "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
e->time = -1;
/* refresh cookie validity */
e->exptime = time(0) + sec->config->cookie_timeout + AUTH_SLACK_TIME;
e->in_use++;
return 0;

View File

@@ -84,8 +84,8 @@ void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec)
cookies[msg.n_cookies].session_is_open = t->session_is_open;
cookies[msg.n_cookies].tls_auth_ok = t->tls_auth_ok;
if (t->time > 0)
cookies[msg.n_cookies].last_modified = t->time;
if (t->created > 0)
cookies[msg.n_cookies].last_modified = t->created;
else
cookies[msg.n_cookies].last_modified = 0;
cookies[msg.n_cookies].username = t->acct_info.username;

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Red Hat
* Copyright (C) 2017 Nikos Mavrogiannopoulos
*
* This file is part of ocserv.
*
@@ -90,6 +91,7 @@ client_entry_st *new_client_entry(sec_mod_st *sec, const char *ip, unsigned pid)
client_entry_st *e, *te;
int ret;
int retries = 3;
time_t now;
e = talloc_zero(db, client_entry_st);
if (e == NULL) {
@@ -117,7 +119,9 @@ client_entry_st *new_client_entry(sec_mod_st *sec, const char *ip, unsigned pid)
}
calc_safe_id(e->sid, SID_SIZE, (char *)e->acct_info.safe_id, sizeof(e->acct_info.safe_id));
e->time = time(0);
now = time(0);
e->exptime = now + sec->config->cookie_timeout + AUTH_SLACK_TIME;
e->created = now;
if (htable_add(db, rehash(e, NULL), e) == 0) {
seclog(sec, LOG_ERR,
@@ -187,18 +191,29 @@ void del_client_entry(sec_mod_st *sec, client_entry_st * e)
void expire_client_entry(sec_mod_st *sec, client_entry_st * e)
{
time_t now;
if (e->in_use > 0)
e->in_use--;
if (e->in_use == 0) {
e->time = time(0);
if (sec->config->persistent_cookies == 0 && (e->discon_reason == REASON_USER_DISCONNECT
|| e->discon_reason == REASON_SERVER_DISCONNECT || e->discon_reason == REASON_SESSION_TIMEOUT)) {
if (sec->config->persistent_cookies == 0 && (e->discon_reason == REASON_SERVER_DISCONNECT ||
e->discon_reason == REASON_SESSION_TIMEOUT)) {
seclog(sec, LOG_INFO, "invalidating session of user '%s' "SESSION_STR,
e->acct_info.username, e->acct_info.safe_id);
e->acct_info.username, e->acct_info.safe_id);
/* immediately disconnect the user */
del_client_entry(sec, e);
} else {
now = time(0);
/* We intentionally don't close the session immediatelly on
* REASON_USER_DISCONNECT, as some anyconect clients
* explicitly disconnect with the intention to reconnect
* seconds later. */
if (e->discon_reason == REASON_USER_DISCONNECT) {
if (!sec->config->persistent_cookies || (now+AUTH_SLACK_TIME >= e->exptime))
e->exptime = now + AUTH_SLACK_TIME;
} else {
e->exptime = now + sec->config->cookie_timeout + AUTH_SLACK_TIME;
}
seclog(sec, LOG_INFO, "temporarily closing session for %s "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
}
}

View File

@@ -75,7 +75,7 @@ typedef struct common_acct_info_st {
unsigned id;
} common_acct_info_st;
#define IS_CLIENT_ENTRY_EXPIRED_FULL(sec, e, now, clean) (e->time != -1 && (now - e->time) > (sec->config->cookie_timeout + (clean?AUTH_SLACK_TIME:0)) && e->in_use == 0)
#define IS_CLIENT_ENTRY_EXPIRED_FULL(sec, e, now, clean) (e->exptime != -1 && now >= e->exptime && e->in_use == 0)
#define IS_CLIENT_ENTRY_EXPIRED(sec, e, now) IS_CLIENT_ENTRY_EXPIRED_FULL(sec, e, now, 0)
typedef struct client_entry_st {
@@ -101,8 +101,10 @@ typedef struct client_entry_st {
uint8_t dtls_session_id[GNUTLS_MAX_SESSION_ID];
/* The time this client entry was last modified (created or closed) */
time_t time;
/* The time this client entry was created */
time_t created;
/* The time this client entry is supposed to expire */
time_t exptime;
/* the auth type associated with the user */
unsigned auth_type;