Keep track of cookies internally.

That allows to restrict the cookie validity time to the absolutely minimum
required to establish and reconnect a recently disconnected session.
That deprecates the cookie-validity option and introduces the cookie-timeout
option.
This commit is contained in:
Nikos Mavrogiannopoulos
2014-05-27 16:00:57 +02:00
parent a2728265b3
commit 25fbdfbf70
11 changed files with 242 additions and 51 deletions
+6 -2
View File
@@ -35,6 +35,7 @@
#include <auth/plain.h> #include <auth/plain.h>
#include <vpn.h> #include <vpn.h>
#include <cookies.h>
#include <main.h> #include <main.h>
#include <ctl.h> #include <ctl.h>
#include <tlslib.h> #include <tlslib.h>
@@ -100,7 +101,7 @@ static struct cfg_options available_options[] = {
{ .name = "mtu", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "mtu", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "net-priority", .type = OPTION_STRING, .mandatory = 0 }, { .name = "net-priority", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "output-buffer", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "output-buffer", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "cookie-validity", .type = OPTION_NUMERIC, .mandatory = 1 }, { .name = "cookie-timeout", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "rekey-time", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "rekey-time", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "rekey-method", .type = OPTION_STRING, .mandatory = 0 }, { .name = "rekey-method", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "auth-timeout", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "auth-timeout", .type = OPTION_NUMERIC, .mandatory = 0 },
@@ -476,7 +477,6 @@ unsigned force_cert_auth;
config->tx_per_sec /= 1000; config->tx_per_sec /= 1000;
READ_TF("deny-roaming", config->deny_roaming, 0); READ_TF("deny-roaming", config->deny_roaming, 0);
READ_NUMERIC("cookie-validity", config->cookie_validity);
config->rekey_time = -1; config->rekey_time = -1;
READ_NUMERIC("rekey-time", config->rekey_time); READ_NUMERIC("rekey-time", config->rekey_time);
@@ -496,6 +496,10 @@ unsigned force_cert_auth;
} }
talloc_free(tmp); tmp = NULL; talloc_free(tmp); tmp = NULL;
READ_NUMERIC("cookie-timeout", config->cookie_timeout);
if (config->cookie_timeout == 0)
config->cookie_timeout = DEFAULT_COOKIE_RECON_TIMEOUT;
READ_NUMERIC("auth-timeout", config->auth_timeout); READ_NUMERIC("auth-timeout", config->auth_timeout);
READ_NUMERIC("idle-timeout", config->idle_timeout); READ_NUMERIC("idle-timeout", config->idle_timeout);
+139 -9
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2013 Nikos Mavrogiannopoulos * Copyright (C) 2013, 2014 Nikos Mavrogiannopoulos
* Copyright (C) 2014 Red Hat
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -31,6 +32,8 @@
#include <limits.h> #include <limits.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <ccan/htable/htable.h>
#include <ccan/hash/hash.h>
#include <ip-lease.h> #include <ip-lease.h>
#include <main.h> #include <main.h>
#include <cookies.h> #include <cookies.h>
@@ -52,10 +55,10 @@ unsigned p_size;
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, key, &iv); ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, key, &iv);
if (ret < 0) if (ret < 0)
return -1; return -1;
cookie += COOKIE_IV_SIZE; cookie += COOKIE_IV_SIZE;
cookie_size -= (COOKIE_IV_SIZE + COOKIE_MAC_SIZE); cookie_size -= (COOKIE_IV_SIZE + COOKIE_MAC_SIZE);
ret = gnutls_cipher_decrypt2(h, cookie, cookie_size, cookie, cookie_size); ret = gnutls_cipher_decrypt2(h, cookie, cookie_size, cookie, cookie_size);
if (ret < 0) { if (ret < 0) {
ret = -1; ret = -1;
@@ -70,7 +73,6 @@ unsigned p_size;
ret = -1; ret = -1;
goto cleanup; goto cleanup;
} }
cookie += cookie_size; cookie += cookie_size;
if (memcmp(tag, cookie, COOKIE_MAC_SIZE) != 0) { if (memcmp(tag, cookie, COOKIE_MAC_SIZE) != 0) {
ret = -1; ret = -1;
@@ -88,7 +90,7 @@ unsigned p_size;
cleanup: cleanup:
gnutls_cipher_deinit(h); gnutls_cipher_deinit(h);
return ret; return ret;
} }
@@ -122,7 +124,7 @@ uint8_t *packed = NULL, *e;
ret = -1; ret = -1;
goto cleanup; goto cleanup;
} }
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, key, &iv); ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, key, &iv);
if (ret < 0) { if (ret < 0) {
ret = -1; ret = -1;
@@ -142,7 +144,7 @@ uint8_t *packed = NULL, *e;
memcpy(e, _iv, COOKIE_IV_SIZE); memcpy(e, _iv, COOKIE_IV_SIZE);
e += COOKIE_IV_SIZE; e += COOKIE_IV_SIZE;
e_size -= COOKIE_IV_SIZE; e_size -= COOKIE_IV_SIZE;
ret = gnutls_cipher_encrypt2(h, packed, packed_size, e, e_size); ret = gnutls_cipher_encrypt2(h, packed, packed_size, e, e_size);
if (ret < 0) { if (ret < 0) {
ret = -1; ret = -1;
@@ -150,7 +152,7 @@ uint8_t *packed = NULL, *e;
} }
e += packed_size; e += packed_size;
ret = gnutls_cipher_tag(h, e, COOKIE_MAC_SIZE); ret = gnutls_cipher_tag(h, e, COOKIE_MAC_SIZE);
if (ret < 0) { if (ret < 0) {
ret = -1; ret = -1;
@@ -158,7 +160,7 @@ uint8_t *packed = NULL, *e;
} }
ret = 0; ret = 0;
cleanup: cleanup:
talloc_free(packed); talloc_free(packed);
if (h != NULL) if (h != NULL)
@@ -167,3 +169,131 @@ cleanup:
} }
void cookie_db_deinit(struct cookie_entry_db_st* db)
{
struct cookie_entry_st * e;
struct htable_iter iter;
e = htable_first(db->db, &iter);
while(e != NULL) {
if (e->proc)
e->proc->cookie_ptr = NULL;
e->proc = NULL;
safe_memset(e->cookie, 0, e->cookie_size);
talloc_free(e);
e = htable_next(db->db, &iter);
}
htable_clear(db->db);
talloc_free(db->db);
return;
}
void expire_cookies(struct cookie_entry_db_st* db)
{
struct cookie_entry_st * e;
struct htable_iter iter;
time_t now = time(0);
e = htable_first(db->db, &iter);
while(e != NULL) {
if (e->expiration == -1 || now < e->expiration)
goto cont;
if (e->proc) {
syslog(LOG_ERR, "found proc that references expired cookie!");
e->proc->cookie_ptr = NULL;
}
htable_delval(db->db, &iter);
db->total--;
safe_memset(e->cookie, 0, e->cookie_size);
talloc_free(e);
cont:
e = htable_next(db->db, &iter);
}
return;
}
static size_t rehash(const void* _e, void* unused)
{
const struct cookie_entry_st * e = _e;
return hash_any(e->cookie, e->cookie_size, 0);
}
void cookie_db_init(void *pool, struct cookie_entry_db_st* db)
{
db->db = talloc(pool, struct htable);
htable_init(db->db, rehash, NULL);
db->total = 0;
}
static bool cookie_entry_cmp(const void* _c1, void* _c2)
{
const struct cookie_entry_st* c1 = _c1;
struct cookie_entry_st* c2 = _c2;
if (c1->cookie_size == c2->cookie_size &&
memcmp(c1->cookie, c2->cookie, c2->cookie_size) == 0)
return 1;
return 0;
}
struct cookie_entry_st *find_cookie_entry(struct cookie_entry_db_st* db, void *cookie, unsigned cookie_size)
{
struct cookie_entry_st *e;
struct cookie_entry_st t;
t.cookie = cookie;
t.cookie_size = cookie_size;
e = htable_get(db->db, hash_any(cookie, cookie_size, 0), cookie_entry_cmp, &t);
if (e == NULL)
return NULL;
if (e->expiration != -1 && e->expiration < time(0))
return NULL;
return e;
}
void revive_cookie(struct cookie_entry_st * e)
{
e->expiration = -1;
}
struct cookie_entry_st *new_cookie_entry(struct cookie_entry_db_st* db, proc_st *proc, void *cookie, unsigned cookie_size)
{
struct cookie_entry_st *t;
t = talloc(db->db, struct cookie_entry_st);
if (t == NULL)
return NULL;
t->expiration = -1;
t->cookie = talloc_memdup(t, cookie, cookie_size);
t->cookie_size = cookie_size;
if (t->cookie == NULL) {
goto fail;
}
t->proc = proc;
if (htable_add(db->db, rehash(t, NULL), t) == 0) {
goto fail;
}
db->total++;
return t;
fail:
talloc_free(t);
return NULL;
}
+12 -2
View File
@@ -22,17 +22,27 @@
#define COOKIES_H #define COOKIES_H
#include <vpn.h> #include <vpn.h>
#include <main.h>
#include <ipc.pb-c.h> #include <ipc.pb-c.h>
#define COOKIE_KEY_SIZE 16
#define COOKIE_IV_SIZE 12 /* AES-GCM */ #define COOKIE_IV_SIZE 12 /* AES-GCM */
#define COOKIE_MAC_SIZE 12 /* 96-bits of AES-GCM */ #define COOKIE_MAC_SIZE 12 /* 96-bits of AES-GCM */
/* The time after a disconnection the cookie is valid */
#define DEFAULT_COOKIE_RECON_TIMEOUT 120
int encrypt_cookie(void *pool, gnutls_datum_t *key, const Cookie *msg, int encrypt_cookie(void *pool, gnutls_datum_t *key, const Cookie *msg,
uint8_t** ecookie, unsigned *ecookie_size); uint8_t** ecookie, unsigned *ecookie_size);
int decrypt_cookie(ProtobufCAllocator *pa, gnutls_datum_t *key, int decrypt_cookie(ProtobufCAllocator *pa, gnutls_datum_t *key,
uint8_t *cookie, unsigned cookie_size, uint8_t *cookie, unsigned cookie_size,
Cookie **msg); Cookie **msg);
void cookie_db_init(void *pool, struct cookie_entry_db_st* db);
void cookie_db_deinit(struct cookie_entry_db_st* db);
void expire_cookies(struct cookie_entry_db_st* db);
struct cookie_entry_st *new_cookie_entry(struct cookie_entry_db_st* db, proc_st *proc, void *cookie, unsigned cookie_size);
struct cookie_entry_st *find_cookie_entry(struct cookie_entry_db_st* db, void *cookie, unsigned cookie_len);
void revive_cookie(struct cookie_entry_st *);
#endif #endif
+41 -26
View File
@@ -166,45 +166,30 @@ time_t now = time(0);
gnutls_datum_t key = {s->cookie_key, sizeof(s->cookie_key)}; gnutls_datum_t key = {s->cookie_key, sizeof(s->cookie_key)};
char str_ip[MAX_IP_STR+1]; char str_ip[MAX_IP_STR+1];
PROTOBUF_ALLOCATOR(pa, proc); PROTOBUF_ALLOCATOR(pa, proc);
struct cookie_entry_st *old;
if (req->cookie.len == 0) { if (req->cookie.len == 0) {
mslog(s, proc, LOG_INFO, "error in cookie size"); mslog(s, proc, LOG_INFO, "error in cookie size");
return -1; return -1;
} }
proc->cookie = talloc_memdup(proc, req->cookie.data, req->cookie.len);
if (proc->cookie == NULL)
return -1;
proc->cookie_size = req->cookie.len;
ret = decrypt_cookie(&pa, &key, req->cookie.data, req->cookie.len, &cmsg); ret = decrypt_cookie(&pa, &key, req->cookie.data, req->cookie.len, &cmsg);
if (ret < 0) { if (ret < 0) {
mslog(s, proc, LOG_INFO, "error decrypting cookie"); mslog(s, proc, LOG_INFO, "error decrypting cookie");
return -1; return -1;
} }
if (cmsg->expiration < now)
return -1;
if (cmsg->username == NULL) if (cmsg->username == NULL)
return -1; return -1;
snprintf(proc->username, sizeof(proc->username), "%s", cmsg->username); snprintf(proc->username, sizeof(proc->username), "%s", cmsg->username);
if (cmsg->groupname)
snprintf(proc->groupname, sizeof(proc->groupname), "%s", cmsg->groupname);
if (cmsg->hostname)
snprintf(proc->hostname, sizeof(proc->hostname), "%s", cmsg->hostname);
if (cmsg->session_id.len != sizeof(proc->dtls_session_id)) if (cmsg->session_id.len != sizeof(proc->dtls_session_id))
return -1; return -1;
memcpy(proc->dtls_session_id, cmsg->session_id.data, cmsg->session_id.len); memcpy(proc->dtls_session_id, cmsg->session_id.data, cmsg->session_id.len);
proc->dtls_session_id_size = cmsg->session_id.len; proc->dtls_session_id_size = cmsg->session_id.len;
memcpy(proc->ipv4_seed, &cmsg->ipv4_seed, sizeof(proc->ipv4_seed)); /* cookie is good so far, now read config (in order to know whether roaming is allowed or not */
/* cookie is good so far, now read config */
memset(&proc->config, 0, sizeof(proc->config)); memset(&proc->config, 0, sizeof(proc->config));
apply_default_sup_config(s->config, proc); apply_default_sup_config(s->config, proc);
@@ -238,6 +223,41 @@ PROTOBUF_ALLOCATOR(pa, proc);
} }
} }
/* check for a valid stored cookie */
if ((old=find_cookie_entry(&s->cookies, req->cookie.data, req->cookie.len)) != NULL) {
if (old->proc != NULL) {
mslog(s, old->proc, LOG_DEBUG, "disconnecting '%s' due to new cookie connection", old->proc->username);
/* steal its leases */
steal_ip_leases(old->proc, proc);
/* steal its cookie */
old->proc->cookie_ptr = NULL;
kill(old->proc->pid, SIGTERM);
} else {
revive_cookie(old);
}
proc->cookie_ptr = old;
old->proc = proc;
} else {
if (cmsg->expiration < now) {
mslog(s, proc, LOG_INFO, "ignoring expired cookie");
return -1;
}
proc->cookie_ptr = new_cookie_entry(&s->cookies, proc, req->cookie.data, req->cookie.len);
if (proc->cookie_ptr == NULL)
return -1;
}
if (cmsg->groupname)
snprintf(proc->groupname, sizeof(proc->groupname), "%s", cmsg->groupname);
if (cmsg->hostname)
snprintf(proc->hostname, sizeof(proc->hostname), "%s", cmsg->hostname);
memcpy(proc->ipv4_seed, &cmsg->ipv4_seed, sizeof(proc->ipv4_seed));
return 0; return 0;
} }
@@ -256,17 +276,12 @@ int check_multiple_users(main_server_st *s, struct proc_st* proc)
struct proc_st *ctmp = NULL, *cpos; struct proc_st *ctmp = NULL, *cpos;
unsigned int entries = 1; /* that one */ unsigned int entries = 1; /* that one */
if (s->config->max_same_clients == 0)
return 0;
list_for_each_safe(&s->proc_list.head, ctmp, cpos, list) { list_for_each_safe(&s->proc_list.head, ctmp, cpos, list) {
if (ctmp != proc && ctmp->pid != -1) { if (ctmp != proc && ctmp->pid != -1) {
if (ctmp->cookie_size == proc->cookie_size && if (strcmp(proc->username, ctmp->username) == 0) {
memcmp(proc->cookie, ctmp->cookie, ctmp->cookie_size) == 0) {
mslog(s, ctmp, LOG_DEBUG, "disconnecting '%s' due to new cookie connection", ctmp->username);
/* steal its leases */
steal_ip_leases(ctmp, proc);
kill(ctmp->pid, SIGTERM);
} else if (strcmp(proc->username, ctmp->username) == 0) {
entries++; entries++;
} }
} }
+8
View File
@@ -193,6 +193,14 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
if (proc->ipv4 || proc->ipv6) if (proc->ipv4 || proc->ipv6)
remove_ip_leases(s, proc); remove_ip_leases(s, proc);
/* expire any available cookies */
if (proc->cookie_ptr) {
unsigned timeout = s->config->cookie_timeout;
proc->cookie_ptr->expiration = time(0) + timeout;
proc->cookie_ptr->proc = NULL;
}
talloc_free(proc); talloc_free(proc);
} }
+4 -1
View File
@@ -588,6 +588,7 @@ void clear_lists(main_server_st *s)
tls_cache_deinit(&s->tls_db); tls_cache_deinit(&s->tls_db);
ip_lease_deinit(&s->ip_leases); ip_lease_deinit(&s->ip_leases);
ctl_handler_deinit(s); ctl_handler_deinit(s);
cookie_db_deinit(&s->cookies);
} }
static void kill_children(main_server_st* s) static void kill_children(main_server_st* s)
@@ -746,7 +747,7 @@ fail:
} }
#define MAINTAINANCE_TIME(s) (MIN(300, ((s)->config->cookie_validity + 300))) #define MAINTAINANCE_TIME(s) (300)
static void check_other_work(main_server_st *s) static void check_other_work(main_server_st *s)
{ {
@@ -796,6 +797,7 @@ unsigned total = 10;
need_maintenance = 0; need_maintenance = 0;
mslog(s, NULL, LOG_DEBUG, "performing maintenance"); mslog(s, NULL, LOG_DEBUG, "performing maintenance");
expire_tls_sessions(s); expire_tls_sessions(s);
expire_cookies(&s->cookies);
alarm(MAINTAINANCE_TIME(s)); alarm(MAINTAINANCE_TIME(s));
} }
} }
@@ -866,6 +868,7 @@ int main(int argc, char** argv)
list_head_init(&s->ban_list.head); list_head_init(&s->ban_list.head);
list_head_init(&s->script_list.head); list_head_init(&s->script_list.head);
tls_cache_init(s, &s->tls_db); tls_cache_init(s, &s->tls_db);
cookie_db_init(s, &s->cookies);
ip_lease_init(&s->ip_leases); ip_lease_init(&s->ip_leases);
sigemptyset(&blockset); sigemptyset(&blockset);
+19 -3
View File
@@ -28,9 +28,10 @@
#include <vpn.h> #include <vpn.h>
#include <tlslib.h> #include <tlslib.h>
#include "ipc.pb-c.h" #include "ipc.pb-c.h"
#include <cookies.h>
#include <common.h> #include <common.h>
#define COOKIE_KEY_SIZE 16
int cmd_parser (void *pool, int argc, char **argv, struct cfg_st** config); int cmd_parser (void *pool, int argc, char **argv, struct cfg_st** config);
void reload_cfg_file(void *pool, struct cfg_st* config); void reload_cfg_file(void *pool, struct cfg_st* config);
void clear_cfg_file(struct cfg_st* config); void clear_cfg_file(struct cfg_st* config);
@@ -71,6 +72,14 @@ enum {
PS_AUTH_COMPLETED, /* successful authentication */ PS_AUTH_COMPLETED, /* successful authentication */
}; };
typedef struct cookie_entry_st {
struct proc_st *proc; /* may be null, otherwise the proc that uses that cookie */
time_t expiration; /* -1 or the time it should expire */
uint8_t *cookie; /* the cookie associated with the session */
unsigned cookie_size;
} cookie_st;
/* Each worker process maps to a unique proc_st structure. /* Each worker process maps to a unique proc_st structure.
*/ */
typedef struct proc_st { typedef struct proc_st {
@@ -100,8 +109,6 @@ typedef struct proc_st {
char username[MAX_USERNAME_SIZE]; /* the owner */ char username[MAX_USERNAME_SIZE]; /* the owner */
char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */ char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */
char hostname[MAX_HOSTNAME_SIZE]; /* the requested hostname */ char hostname[MAX_HOSTNAME_SIZE]; /* the requested hostname */
uint8_t *cookie; /* the cookie associated with the session */
unsigned cookie_size;
/* the following are copied here from the worker process for reporting /* the following are copied here from the worker process for reporting
* purposes (from main-ctl-handler). */ * purposes (from main-ctl-handler). */
@@ -109,6 +116,9 @@ typedef struct proc_st {
char tls_ciphersuite[MAX_CIPHERSUITE_NAME]; char tls_ciphersuite[MAX_CIPHERSUITE_NAME];
char dtls_ciphersuite[MAX_DTLS_CIPHERSUITE_NAME]; char dtls_ciphersuite[MAX_DTLS_CIPHERSUITE_NAME];
/* pointer to the cookie used by this session */
struct cookie_entry_st *cookie_ptr;
/* if the session is initiated by a cookie the following two are set /* if the session is initiated by a cookie the following two are set
* and are considered when generating an IP address. That is used to * and are considered when generating an IP address. That is used to
* generate the same address as previously allocated. * generate the same address as previously allocated.
@@ -151,10 +161,16 @@ struct ban_list_st {
struct list_head head; struct list_head head;
}; };
struct cookie_entry_db_st {
struct htable *db;
unsigned total;
};
typedef struct main_server_st { typedef struct main_server_st {
struct cfg_st *config; struct cfg_st *config;
struct ip_lease_db_st ip_leases; struct ip_lease_db_st ip_leases;
struct cookie_entry_db_st cookies;
tls_sess_db_st tls_db; tls_sess_db_st tls_db;
tls_st *creds; tls_st *creds;
+7 -4
View File
@@ -208,11 +208,14 @@ auth-timeout = 40
# a failed authentication attempt. # a failed authentication attempt.
#min-reauth-time = 2 #min-reauth-time = 2
# Cookie validity time (in seconds) # Cookie timeout (in seconds)
# Once a client is authenticated he's provided a cookie with # Once a client is authenticated he's provided a cookie with
# which he can reconnect. This option sets the maximum lifetime # which he can reconnect. That cookie will be invalided if not
# of that cookie. # used within this timeout value. On a user disconnection, that
cookie-validity = 10800 # cookie will also be active for this time amount prior to be
# invalid. That allows a reasonable amount of time for roaming between
# networks.
cookie-timeout = 300
# Whether roaming is allowed, i.e., if true a cookie is # Whether roaming is allowed, i.e., if true a cookie is
# restricted to a single IP address and cannot be re-used # restricted to a single IP address and cannot be re-used
+3 -1
View File
@@ -93,7 +93,9 @@ static int generate_cookie(sec_mod_st * sec, client_entry_st * entry)
return -1; return -1;
} }
msg.expiration = time(0) + sec->config->cookie_validity; /* this is the time when this cookie must be activated (used to authenticate).
* if not activated by that time it expires */
msg.expiration = time(0) + sec->config->cookie_timeout;
ret = ret =
encrypt_cookie(entry, &sec->dcookie_key, &msg, &entry->cookie, encrypt_cookie(entry, &sec->dcookie_key, &msg, &entry->cookie,
+1 -1
View File
@@ -210,7 +210,7 @@ struct cfg_st {
char* socket_file_prefix; char* socket_file_prefix;
unsigned deny_roaming; /* whether a cookie is restricted to a single IP */ unsigned deny_roaming; /* whether a cookie is restricted to a single IP */
time_t cookie_validity; /* in seconds */ time_t cookie_timeout; /* in seconds */
time_t rekey_time; /* in seconds */ time_t rekey_time; /* in seconds */
unsigned rekey_method; /* REKEY_METHOD_ */ unsigned rekey_method; /* REKEY_METHOD_ */
+2 -2
View File
@@ -833,8 +833,8 @@ int post_common_handler(worker_st * ws, unsigned http_ver)
ret = ret =
tls_printf(ws->session, tls_printf(ws->session,
"Set-Cookie: webvpn=%s; Max-Age=%u; Secure\r\n", "Set-Cookie: webvpn=%s; Secure\r\n",
str_cookie, (unsigned)ws->config->cookie_validity); str_cookie);
if (ret < 0) if (ret < 0)
return -1; return -1;