mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 16:57:00 +08:00
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:
@@ -35,6 +35,7 @@
|
||||
#include <auth/plain.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
#include <main.h>
|
||||
#include <ctl.h>
|
||||
#include <tlslib.h>
|
||||
@@ -100,7 +101,7 @@ static struct cfg_options available_options[] = {
|
||||
{ .name = "mtu", .type = OPTION_NUMERIC, .mandatory = 0 },
|
||||
{ .name = "net-priority", .type = OPTION_STRING, .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-method", .type = OPTION_STRING, .mandatory = 0 },
|
||||
{ .name = "auth-timeout", .type = OPTION_NUMERIC, .mandatory = 0 },
|
||||
@@ -476,7 +477,6 @@ unsigned force_cert_auth;
|
||||
config->tx_per_sec /= 1000;
|
||||
|
||||
READ_TF("deny-roaming", config->deny_roaming, 0);
|
||||
READ_NUMERIC("cookie-validity", config->cookie_validity);
|
||||
|
||||
config->rekey_time = -1;
|
||||
READ_NUMERIC("rekey-time", config->rekey_time);
|
||||
@@ -496,6 +496,10 @@ unsigned force_cert_auth;
|
||||
}
|
||||
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("idle-timeout", config->idle_timeout);
|
||||
|
||||
|
||||
148
src/cookies.c
148
src/cookies.c
@@ -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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -31,6 +32,8 @@
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ccan/htable/htable.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <ip-lease.h>
|
||||
#include <main.h>
|
||||
#include <cookies.h>
|
||||
@@ -52,10 +55,10 @@ unsigned p_size;
|
||||
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, key, &iv);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
cookie += COOKIE_IV_SIZE;
|
||||
cookie_size -= (COOKIE_IV_SIZE + COOKIE_MAC_SIZE);
|
||||
|
||||
|
||||
ret = gnutls_cipher_decrypt2(h, cookie, cookie_size, cookie, cookie_size);
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
@@ -70,7 +73,6 @@ unsigned p_size;
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cookie += cookie_size;
|
||||
if (memcmp(tag, cookie, COOKIE_MAC_SIZE) != 0) {
|
||||
ret = -1;
|
||||
@@ -88,7 +90,7 @@ unsigned p_size;
|
||||
|
||||
cleanup:
|
||||
gnutls_cipher_deinit(h);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -122,7 +124,7 @@ uint8_t *packed = NULL, *e;
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, key, &iv);
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
@@ -142,7 +144,7 @@ uint8_t *packed = NULL, *e;
|
||||
memcpy(e, _iv, COOKIE_IV_SIZE);
|
||||
e += COOKIE_IV_SIZE;
|
||||
e_size -= COOKIE_IV_SIZE;
|
||||
|
||||
|
||||
ret = gnutls_cipher_encrypt2(h, packed, packed_size, e, e_size);
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
@@ -150,7 +152,7 @@ uint8_t *packed = NULL, *e;
|
||||
}
|
||||
|
||||
e += packed_size;
|
||||
|
||||
|
||||
ret = gnutls_cipher_tag(h, e, COOKIE_MAC_SIZE);
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
@@ -158,7 +160,7 @@ uint8_t *packed = NULL, *e;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
||||
cleanup:
|
||||
talloc_free(packed);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -22,17 +22,27 @@
|
||||
#define COOKIES_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
#include <ipc.pb-c.h>
|
||||
|
||||
#define COOKIE_KEY_SIZE 16
|
||||
|
||||
#define COOKIE_IV_SIZE 12 /* 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,
|
||||
uint8_t** ecookie, unsigned *ecookie_size);
|
||||
int decrypt_cookie(ProtobufCAllocator *pa, gnutls_datum_t *key,
|
||||
uint8_t *cookie, unsigned cookie_size,
|
||||
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
|
||||
|
||||
@@ -166,45 +166,30 @@ time_t now = time(0);
|
||||
gnutls_datum_t key = {s->cookie_key, sizeof(s->cookie_key)};
|
||||
char str_ip[MAX_IP_STR+1];
|
||||
PROTOBUF_ALLOCATOR(pa, proc);
|
||||
struct cookie_entry_st *old;
|
||||
|
||||
if (req->cookie.len == 0) {
|
||||
mslog(s, proc, LOG_INFO, "error in cookie size");
|
||||
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);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_INFO, "error decrypting cookie");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmsg->expiration < now)
|
||||
return -1;
|
||||
|
||||
if (cmsg->username == NULL)
|
||||
return -1;
|
||||
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))
|
||||
return -1;
|
||||
|
||||
memcpy(proc->dtls_session_id, cmsg->session_id.data, 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 */
|
||||
/* cookie is good so far, now read config (in order to know whether roaming is allowed or not */
|
||||
memset(&proc->config, 0, sizeof(proc->config));
|
||||
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;
|
||||
}
|
||||
@@ -256,17 +276,12 @@ int check_multiple_users(main_server_st *s, struct proc_st* proc)
|
||||
struct proc_st *ctmp = NULL, *cpos;
|
||||
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) {
|
||||
if (ctmp != proc && ctmp->pid != -1) {
|
||||
if (ctmp->cookie_size == proc->cookie_size &&
|
||||
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) {
|
||||
if (strcmp(proc->username, ctmp->username) == 0) {
|
||||
entries++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +193,14 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
||||
if (proc->ipv4 || proc->ipv6)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -588,6 +588,7 @@ void clear_lists(main_server_st *s)
|
||||
tls_cache_deinit(&s->tls_db);
|
||||
ip_lease_deinit(&s->ip_leases);
|
||||
ctl_handler_deinit(s);
|
||||
cookie_db_deinit(&s->cookies);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -796,6 +797,7 @@ unsigned total = 10;
|
||||
need_maintenance = 0;
|
||||
mslog(s, NULL, LOG_DEBUG, "performing maintenance");
|
||||
expire_tls_sessions(s);
|
||||
expire_cookies(&s->cookies);
|
||||
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->script_list.head);
|
||||
tls_cache_init(s, &s->tls_db);
|
||||
cookie_db_init(s, &s->cookies);
|
||||
ip_lease_init(&s->ip_leases);
|
||||
|
||||
sigemptyset(&blockset);
|
||||
|
||||
22
src/main.h
22
src/main.h
@@ -28,9 +28,10 @@
|
||||
#include <vpn.h>
|
||||
#include <tlslib.h>
|
||||
#include "ipc.pb-c.h"
|
||||
#include <cookies.h>
|
||||
#include <common.h>
|
||||
|
||||
#define COOKIE_KEY_SIZE 16
|
||||
|
||||
int cmd_parser (void *pool, int argc, char **argv, struct cfg_st** config);
|
||||
void reload_cfg_file(void *pool, struct cfg_st* config);
|
||||
void clear_cfg_file(struct cfg_st* config);
|
||||
@@ -71,6 +72,14 @@ enum {
|
||||
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.
|
||||
*/
|
||||
typedef struct proc_st {
|
||||
@@ -100,8 +109,6 @@ typedef struct proc_st {
|
||||
char username[MAX_USERNAME_SIZE]; /* the owner */
|
||||
char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */
|
||||
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
|
||||
* purposes (from main-ctl-handler). */
|
||||
@@ -109,6 +116,9 @@ typedef struct proc_st {
|
||||
char tls_ciphersuite[MAX_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
|
||||
* and are considered when generating an IP address. That is used to
|
||||
* generate the same address as previously allocated.
|
||||
@@ -151,10 +161,16 @@ struct ban_list_st {
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
struct cookie_entry_db_st {
|
||||
struct htable *db;
|
||||
unsigned total;
|
||||
};
|
||||
|
||||
typedef struct main_server_st {
|
||||
struct cfg_st *config;
|
||||
|
||||
struct ip_lease_db_st ip_leases;
|
||||
struct cookie_entry_db_st cookies;
|
||||
|
||||
tls_sess_db_st tls_db;
|
||||
tls_st *creds;
|
||||
|
||||
@@ -208,11 +208,14 @@ auth-timeout = 40
|
||||
# a failed authentication attempt.
|
||||
#min-reauth-time = 2
|
||||
|
||||
# Cookie validity time (in seconds)
|
||||
# Cookie timeout (in seconds)
|
||||
# Once a client is authenticated he's provided a cookie with
|
||||
# which he can reconnect. This option sets the maximum lifetime
|
||||
# of that cookie.
|
||||
cookie-validity = 10800
|
||||
# which he can reconnect. That cookie will be invalided if not
|
||||
# used within this timeout value. On a user disconnection, that
|
||||
# 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
|
||||
# restricted to a single IP address and cannot be re-used
|
||||
|
||||
@@ -93,7 +93,9 @@ static int generate_cookie(sec_mod_st * sec, client_entry_st * entry)
|
||||
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 =
|
||||
encrypt_cookie(entry, &sec->dcookie_key, &msg, &entry->cookie,
|
||||
|
||||
@@ -210,7 +210,7 @@ struct cfg_st {
|
||||
char* socket_file_prefix;
|
||||
|
||||
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 */
|
||||
unsigned rekey_method; /* REKEY_METHOD_ */
|
||||
|
||||
@@ -833,8 +833,8 @@ int post_common_handler(worker_st * ws, unsigned http_ver)
|
||||
|
||||
ret =
|
||||
tls_printf(ws->session,
|
||||
"Set-Cookie: webvpn=%s; Max-Age=%u; Secure\r\n",
|
||||
str_cookie, (unsigned)ws->config->cookie_validity);
|
||||
"Set-Cookie: webvpn=%s; Secure\r\n",
|
||||
str_cookie);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user