mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 16:57:00 +08:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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--;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user