Augmented cookie format to store the seeds used to generate IPv4 and IPv6 addresses.

This ensures that if the IP previously used by a user is free, it will
be reassigned to him after a reconnection with the same cookie.
This commit is contained in:
Nikos Mavrogiannopoulos
2013-12-11 10:03:45 +01:00
parent 80a7ac124c
commit cb5092e820
5 changed files with 58 additions and 31 deletions

View File

@@ -31,6 +31,7 @@
#include <limits.h>
#include <sys/stat.h>
#include <ip-lease.h>
#include <main.h>
#include <cookies.h>
@@ -122,3 +123,32 @@ cleanup:
return ret;
}
int generate_cookie(main_server_st *s, struct proc_st* proc)
{
int ret;
struct stored_cookie_st sc;
ret = gnutls_rnd(GNUTLS_RND_NONCE, proc->session_id, sizeof(proc->session_id));
if (ret < 0)
return -1;
proc->session_id_size = sizeof(proc->session_id);
memcpy(sc.username, proc->username, sizeof(proc->username));
memcpy(sc.groupname, proc->groupname, sizeof(proc->groupname));
memcpy(sc.hostname, proc->hostname, sizeof(proc->hostname));
memcpy(sc.session_id, proc->session_id, sizeof(proc->session_id));
sc.expiration = time(0) + s->config->cookie_validity;
memcpy(sc.ipv4_seed, SA_IN_U8_P(&proc->ipv4->lip), 4);
memcpy(sc.ipv6_seed, SA_IN6_U8_P(&proc->ipv6->lip), 16);
ret = encrypt_cookie(s, &sc, proc->cookie, sizeof(proc->cookie));
if (ret < 0)
return -1;
return 0;
}

View File

@@ -29,6 +29,9 @@ struct __attribute__ ((__packed__)) stored_cookie_st {
char hostname[MAX_HOSTNAME_SIZE];
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
uint32_t expiration;
uint8_t ipv4_seed[4];
uint8_t ipv6_seed[16];
};
#define COOKIE_IV_SIZE 12 /* AES-GCM */

View File

@@ -166,8 +166,12 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
goto fail;
}
if (max_loops == MAX_IP_TRIES) {
uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
memcpy(SA_IN_U8_P(&rnd), &t, 4);
if (proc->seeds_are_set) {
memcpy(SA_IN_U8_P(&rnd), proc->ipv4_seed, 4);
} else {
uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
memcpy(SA_IN_U8_P(&rnd), &t, 4);
}
} else
gnutls_rnd(GNUTLS_RND_NONCE, SA_IN_U8_P(&rnd), sizeof(struct in_addr));
max_loops--;
@@ -298,9 +302,13 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
}
if (max_loops == MAX_IP_TRIES) {
uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
memset(SA_IN6_U8_P(&rnd), 0, sizeof(struct in6_addr));
memcpy(SA_IN6_U8_P(&rnd)+sizeof(struct in6_addr)-5, &t, 4);
if (proc->seeds_are_set) {
memcpy(SA_IN6_U8_P(&rnd), proc->ipv6_seed, 16);
} else {
uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
memset(SA_IN6_U8_P(&rnd), 0, sizeof(struct in6_addr));
memcpy(SA_IN6_U8_P(&rnd)+sizeof(struct in6_addr)-5, &t, 4);
}
} else
gnutls_rnd(GNUTLS_RND_NONCE, SA_IN6_U8_P(&rnd), sizeof(struct in6_addr));
max_loops--;

View File

@@ -353,10 +353,14 @@ time_t now = time(0);
memcpy(proc->hostname, sc.hostname, sizeof(proc->hostname));
memcpy(proc->session_id, sc.session_id, sizeof(proc->session_id));
proc->session_id_size = sizeof(proc->session_id);
proc->username[sizeof(proc->username)-1] = 0;
proc->groupname[sizeof(proc->groupname)-1] = 0;
proc->hostname[sizeof(proc->hostname)-1] = 0;
memcpy(proc->ipv4_seed, sc.ipv4_seed, sizeof(proc->ipv4_seed));
memcpy(proc->ipv6_seed, sc.ipv6_seed, sizeof(proc->ipv6_seed));
proc->seeds_are_set = 1;
ret = check_user_group_status(s, proc, req->tls_auth_ok, req->cert_user, req->cert_group);
if (ret < 0)
@@ -365,31 +369,6 @@ time_t now = time(0);
return 0;
}
int generate_cookie(main_server_st *s, struct proc_st* proc)
{
int ret;
struct stored_cookie_st sc;
ret = gnutls_rnd(GNUTLS_RND_NONCE, proc->session_id, sizeof(proc->session_id));
if (ret < 0)
return -1;
proc->session_id_size = sizeof(proc->session_id);
memcpy(sc.username, proc->username, sizeof(proc->username));
memcpy(sc.groupname, proc->groupname, sizeof(proc->groupname));
memcpy(sc.hostname, proc->hostname, sizeof(proc->hostname));
memcpy(sc.session_id, proc->session_id, sizeof(proc->session_id));
sc.expiration = time(0) + s->config->cookie_validity;
ret = encrypt_cookie(s, &sc, proc->cookie, sizeof(proc->cookie));
if (ret < 0)
return -1;
return 0;
}
int handle_auth_init(main_server_st *s, struct proc_st* proc,
const struct cmd_auth_init_st * req)
{

View File

@@ -96,6 +96,13 @@ struct proc_st {
char hostname[MAX_HOSTNAME_SIZE]; /* the requested hostname */
uint8_t cookie[COOKIE_SIZE]; /* the cookie associated with the session */
/* if the session is initiated by a cookie the following two are set
* and are considered when generating an IP address.
*/
uint8_t seeds_are_set; /* non zero if the following two elements are set */
uint8_t ipv4_seed[4];
uint8_t ipv6_seed[16];
void * auth_ctx; /* the context of authentication */
unsigned auth_status; /* PS_AUTH_ */
unsigned auth_reqs; /* the number of requests received */