mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-14 02:22:03 +08:00
Cookies are no longer persistent
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
vpn.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \
|
||||
config.c pam.c pam.h worker-resume.c worker.h main-resume.c main.h \
|
||||
worker-extras.c main-auth.h \
|
||||
main-user.c cookies-gdbm.c cookies-hash.c worker-misc.c setproctitle.h \
|
||||
main-user.c worker-misc.c setproctitle.h \
|
||||
setproctitle.c worker-privs.c plain.c plain.h common.h common.c \
|
||||
sec-mod.c sec-mod.h script-list.h system.c system.h icmp-ping.c icmp-ping.h \
|
||||
str.c str.h gettime.h $(CCAN_SOURCES)
|
||||
|
||||
@@ -191,8 +191,6 @@ unsigned j;
|
||||
READ_STRING("tls-priorities", config->priorities, 0);
|
||||
READ_STRING("chroot-dir", config->chroot_dir, 0);
|
||||
|
||||
READ_STRING("cookie-db", config->cookie_db_name, 0);
|
||||
|
||||
READ_NUMERIC("cookie-validity", config->cookie_validity, 1);
|
||||
READ_NUMERIC("auth-timeout", config->auth_timeout, 0);
|
||||
READ_NUMERIC("max-clients", config->max_clients, 0);
|
||||
@@ -376,7 +374,6 @@ unsigned i;
|
||||
DEL(config->cert_group_oid);
|
||||
DEL(config->priorities);
|
||||
DEL(config->chroot_dir);
|
||||
DEL(config->cookie_db_name);
|
||||
DEL(config->connect_script);
|
||||
DEL(config->disconnect_script);
|
||||
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include "setproctitle.h"
|
||||
#include <main.h>
|
||||
#include <cookies.h>
|
||||
|
||||
#ifdef HAVE_GDBM
|
||||
|
||||
# include <gdbm.h>
|
||||
|
||||
/* Note that it receives allocated data and stores them. Do not
|
||||
* free the sc.
|
||||
*/
|
||||
static
|
||||
int cookie_gdbm_store(main_server_st *s, struct stored_cookie_st* sc)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
datum key;
|
||||
datum data;
|
||||
int ret;
|
||||
|
||||
dbf = gdbm_open((char*)s->config->cookie_db_name, 0, GDBM_WRCREAT, S_IRUSR|S_IWUSR, NULL);
|
||||
if (dbf == NULL) {
|
||||
syslog(LOG_ERR, "Cannot open cookie database: %s", s->config->cookie_db_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
key.dptr = (void*)sc->cookie;
|
||||
key.dsize = sizeof(sc->cookie);
|
||||
data.dptr = (void*)sc;
|
||||
data.dsize = sizeof(*sc);
|
||||
|
||||
ret = gdbm_store( dbf, key, data, GDBM_INSERT);
|
||||
if (ret != 0) {
|
||||
ret = -1;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
free(sc);
|
||||
gdbm_close(dbf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* retrieves and deletes the entry */
|
||||
static
|
||||
int cookie_gdbm_retrieve(main_server_st *s, const void* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* sc)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
datum key;
|
||||
datum data;
|
||||
int ret;
|
||||
|
||||
dbf = gdbm_open((char*)s->config->cookie_db_name, 0, GDBM_READER, 0, NULL);
|
||||
if (dbf == NULL) {
|
||||
syslog(LOG_ERR, "Cannot open cookie database: %s", s->config->cookie_db_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
key.dptr = (void*)cookie;
|
||||
key.dsize = cookie_size;
|
||||
|
||||
data = gdbm_fetch( dbf, key);
|
||||
if (data.dsize != sizeof(*sc)) {
|
||||
ret = -1;
|
||||
goto finish;
|
||||
}
|
||||
memcpy(sc, data.dptr, data.dsize);
|
||||
gdbm_delete(dbf, key);
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
gdbm_close(dbf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void cookie_gdbm_expire(main_server_st* s)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
datum key;
|
||||
datum data;
|
||||
int deleted = 0;
|
||||
struct stored_cookie_st sc;
|
||||
time_t now = time(0);
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) { /* child */
|
||||
clear_lists(s);
|
||||
setproctitle(PACKAGE_NAME"-maint");
|
||||
|
||||
dbf = gdbm_open((char*)s->config->cookie_db_name, 0, GDBM_WRITER, 0, NULL);
|
||||
if (dbf == NULL)
|
||||
exit(1);
|
||||
|
||||
key = gdbm_firstkey(dbf);
|
||||
if (key.dptr == NULL)
|
||||
goto finish;
|
||||
|
||||
while(key.dptr != NULL) {
|
||||
data = gdbm_fetch( dbf, key);
|
||||
if (data.dsize != sizeof(sc)) {
|
||||
gdbm_delete(dbf, key);
|
||||
deleted++;
|
||||
} else {
|
||||
memcpy(&sc, data.dptr, data.dsize);
|
||||
if (sc.expiration <= now) {
|
||||
gdbm_delete(dbf, key);
|
||||
deleted++;
|
||||
}
|
||||
}
|
||||
|
||||
key = gdbm_nextkey(dbf, key);
|
||||
}
|
||||
|
||||
if (deleted > 0)
|
||||
gdbm_reorganize(dbf);
|
||||
|
||||
finish:
|
||||
gdbm_close(dbf);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
int cookie_gdbm_init(main_server_st* s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void cookie_gdbm_erase(main_server_st* s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void cookie_gdbm_deinit(main_server_st* s)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct cookie_storage_st gdbm_cookie_funcs = {
|
||||
.store = cookie_gdbm_store,
|
||||
.retrieve = cookie_gdbm_retrieve,
|
||||
.expire = cookie_gdbm_expire,
|
||||
.init = cookie_gdbm_init,
|
||||
.deinit = cookie_gdbm_deinit,
|
||||
.erase = cookie_gdbm_erase,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <main.h>
|
||||
#include <cookies.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
|
||||
#define MAX_COOKIES(n) ((n>0&&n>64)?(2*n):128)
|
||||
|
||||
/* Note that it receives allocated data and stores them. Do not
|
||||
* free the sc.
|
||||
*/
|
||||
static
|
||||
int store_cookie_hash(main_server_st *s, struct stored_cookie_st* sc)
|
||||
{
|
||||
size_t key;
|
||||
|
||||
if (s->cookie_db->entries >= MAX_COOKIES(s->config->max_clients)) {
|
||||
mslog(s, NULL, LOG_INFO, "maximum number of cookies was reached (%u)", MAX_COOKIES(s->config->max_clients));
|
||||
need_maintainance = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
key = hash_stable_8(sc->cookie, COOKIE_SIZE, 0);
|
||||
|
||||
htable_add(&s->cookie_db->ht, key, sc);
|
||||
s->cookie_db->entries++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* retrieves and deletes the entry */
|
||||
static
|
||||
int retrieve_cookie_hash(main_server_st *s, const void* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* rsc)
|
||||
{
|
||||
size_t key;
|
||||
struct htable_iter iter;
|
||||
struct stored_cookie_st * sc;
|
||||
|
||||
key = hash_stable_8(cookie, cookie_size, 0);
|
||||
|
||||
sc = htable_firstval(&s->cookie_db->ht, &iter, key);
|
||||
while(sc != NULL) {
|
||||
if (cookie_size == COOKIE_SIZE &&
|
||||
memcmp (cookie, sc->cookie, COOKIE_SIZE) == 0) {
|
||||
|
||||
memcpy(rsc, sc, sizeof(*sc));
|
||||
htable_delval(&s->cookie_db->ht, &iter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc = htable_nextval(&s->cookie_db->ht, &iter, key);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void delete_entry(hash_db_st *cookie_db, struct htable_iter *iter,
|
||||
struct stored_cookie_st *sc)
|
||||
{
|
||||
htable_delval(&cookie_db->ht, iter);
|
||||
free(sc);
|
||||
cookie_db->entries--;
|
||||
}
|
||||
|
||||
static
|
||||
void expire_cookies_hash(main_server_st* s)
|
||||
{
|
||||
struct stored_cookie_st *sc;
|
||||
struct htable_iter iter;
|
||||
time_t now = time(0);
|
||||
unsigned int todelete;
|
||||
|
||||
sc = htable_first(&s->cookie_db->ht, &iter);
|
||||
while(sc != NULL) {
|
||||
if (sc->expiration <= now) {
|
||||
delete_entry(s->cookie_db, &iter, sc);
|
||||
}
|
||||
sc = htable_next(&s->cookie_db->ht, &iter);
|
||||
}
|
||||
|
||||
/* if the hash is still full then delete the few first cookies */
|
||||
if (s->cookie_db->entries >= MAX_COOKIES(s->config->max_clients)) {
|
||||
todelete = MAX_COOKIES(s->config->max_clients)/5;
|
||||
mslog(s, NULL, LOG_INFO, "too many cookies present; expiring the first %u", todelete);
|
||||
sc = htable_first(&s->cookie_db->ht, &iter);
|
||||
while(sc != NULL) {
|
||||
if (todelete >= 0) {
|
||||
delete_entry(s->cookie_db, &iter, sc);
|
||||
todelete--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
sc = htable_next(&s->cookie_db->ht, &iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void erase_cookies_hash(main_server_st* s)
|
||||
{
|
||||
struct stored_cookie_st *sc;
|
||||
struct htable_iter iter;
|
||||
time_t now = time(0);
|
||||
|
||||
sc = htable_first(&s->cookie_db->ht, &iter);
|
||||
while(sc != NULL) {
|
||||
if (sc->expiration <= now) {
|
||||
htable_delval(&s->cookie_db->ht, &iter);
|
||||
memset(sc->cookie, 0, sizeof(sc->cookie));
|
||||
free(sc);
|
||||
s->cookie_db->entries--;
|
||||
}
|
||||
sc = htable_next(&s->cookie_db->ht, &iter);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t rehash(const void *_e, void *unused)
|
||||
{
|
||||
const struct stored_cookie_st *e = _e;
|
||||
|
||||
return hash_stable_8(e->cookie, COOKIE_SIZE, 0);
|
||||
}
|
||||
|
||||
static
|
||||
int cookie_db_init_hash(main_server_st * s)
|
||||
{
|
||||
hash_db_st * db;
|
||||
|
||||
db = malloc(sizeof(*db));
|
||||
if (db == NULL)
|
||||
return -1;
|
||||
|
||||
htable_init(&db->ht, rehash, NULL);
|
||||
db->entries = 0;
|
||||
|
||||
s->cookie_db = db;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void cookie_db_deinit_hash(main_server_st* s)
|
||||
{
|
||||
struct stored_cookie_st* cache;
|
||||
struct htable_iter iter;
|
||||
|
||||
cache = htable_first(&s->cookie_db->ht, &iter);
|
||||
while(cache != NULL) {
|
||||
free(cache);
|
||||
cache = htable_next(&s->cookie_db->ht, &iter);
|
||||
}
|
||||
htable_clear(&s->cookie_db->ht);
|
||||
s->cookie_db->entries = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
struct cookie_storage_st hash_cookie_funcs = {
|
||||
.store = store_cookie_hash,
|
||||
.retrieve = retrieve_cookie_hash,
|
||||
.expire = expire_cookies_hash,
|
||||
.erase = erase_cookies_hash,
|
||||
.init = cookie_db_init_hash,
|
||||
.deinit = cookie_db_deinit_hash,
|
||||
};
|
||||
+83
-20
@@ -35,28 +35,91 @@
|
||||
#include <main.h>
|
||||
#include <cookies.h>
|
||||
|
||||
cookie_store_fn store_cookie;
|
||||
cookie_retrieve_fn retrieve_cookie;
|
||||
cookie_db_deinit_fn cookie_db_deinit;
|
||||
cookie_expire_fn expire_cookies;
|
||||
cookie_expire_fn erase_cookies;
|
||||
|
||||
int cookie_db_init(main_server_st* s)
|
||||
int decrypt_cookie(main_server_st * s, const uint8_t* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* sc)
|
||||
{
|
||||
struct cookie_storage_st* funcs;
|
||||
gnutls_datum_t iv = { (void*)cookie, COOKIE_IV_SIZE };
|
||||
int ret;
|
||||
uint8_t tag[COOKIE_MAC_SIZE];
|
||||
gnutls_cipher_hd_t h;
|
||||
gnutls_datum_t key = { (void*)s->cookie_key, sizeof(s->cookie_key) };
|
||||
|
||||
#ifdef HAVE_GDBM
|
||||
if (s->config->cookie_db_name != NULL)
|
||||
funcs = &gdbm_cookie_funcs;
|
||||
else
|
||||
#endif
|
||||
funcs = &hash_cookie_funcs;
|
||||
if (cookie_size != COOKIE_SIZE)
|
||||
return -1;
|
||||
|
||||
cookie_db_deinit = funcs->deinit;
|
||||
expire_cookies = funcs->expire;
|
||||
erase_cookies = funcs->erase;
|
||||
store_cookie = funcs->store;
|
||||
retrieve_cookie = funcs->retrieve;
|
||||
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, &key, &iv);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
cookie += COOKIE_IV_SIZE;
|
||||
|
||||
ret = gnutls_cipher_decrypt2(h, cookie, sizeof(*sc), sc, sizeof(*sc));
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = gnutls_cipher_tag(h, tag, sizeof(tag));
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cookie += sizeof(*sc);
|
||||
if (memcmp(tag, cookie, COOKIE_MAC_SIZE) != 0) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
gnutls_cipher_deinit(h);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int encrypt_cookie(main_server_st * s, uint8_t* cookie, unsigned cookie_size,
|
||||
const struct stored_cookie_st* sc)
|
||||
{
|
||||
uint8_t _iv[COOKIE_IV_SIZE];
|
||||
gnutls_cipher_hd_t h;
|
||||
gnutls_datum_t iv = { _iv, sizeof(_iv) };
|
||||
gnutls_datum_t key = { (void*)s->cookie_key, sizeof(s->cookie_key) };
|
||||
int ret;
|
||||
|
||||
if (cookie_size != COOKIE_SIZE)
|
||||
return -1;
|
||||
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, _iv, sizeof(_iv));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
ret = gnutls_cipher_init(&h, GNUTLS_CIPHER_AES_128_GCM, &key, &iv);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(cookie, _iv, COOKIE_IV_SIZE);
|
||||
cookie += COOKIE_IV_SIZE;
|
||||
|
||||
ret = gnutls_cipher_encrypt2(h, sc, sizeof(*sc), cookie, sizeof(*sc));
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cookie += sizeof(*sc);
|
||||
|
||||
ret = gnutls_cipher_tag(h, cookie, COOKIE_MAC_SIZE);
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
gnutls_cipher_deinit(h);
|
||||
return ret;
|
||||
|
||||
return funcs->init(s);
|
||||
}
|
||||
|
||||
+8
-30
@@ -2,44 +2,22 @@
|
||||
#define COOKIES_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
|
||||
struct stored_cookie_st {
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
struct __attribute__ ((__packed__)) stored_cookie_st {
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
char groupname[MAX_GROUPNAME_SIZE];
|
||||
char hostname[MAX_HOSTNAME_SIZE];
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
time_t expiration;
|
||||
uint32_t expiration;
|
||||
};
|
||||
|
||||
typedef int (*cookie_store_fn)(main_server_st *, struct stored_cookie_st* sc);
|
||||
#define COOKIE_IV_SIZE 12 /* AES-GCM */
|
||||
#define COOKIE_MAC_SIZE 12 /* 96-bits of AES-GCM */
|
||||
#define COOKIE_SIZE (COOKIE_IV_SIZE + sizeof(struct stored_cookie_st) + COOKIE_MAC_SIZE)
|
||||
|
||||
typedef int (*cookie_retrieve_fn)(main_server_st *, const void* cookie, unsigned cookie_size,
|
||||
int encrypt_cookie(struct main_server_st * s, uint8_t* cookie, unsigned cookie_size,
|
||||
const struct stored_cookie_st* sc);
|
||||
int decrypt_cookie(struct main_server_st * s, const uint8_t* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* sc);
|
||||
|
||||
typedef void (*cookie_db_deinit_fn)(main_server_st*);
|
||||
typedef void (*cookie_expire_fn)(main_server_st* s);
|
||||
|
||||
extern cookie_store_fn store_cookie;
|
||||
extern cookie_retrieve_fn retrieve_cookie;
|
||||
extern cookie_db_deinit_fn cookie_db_deinit;
|
||||
extern cookie_expire_fn expire_cookies;
|
||||
extern cookie_expire_fn erase_cookies;
|
||||
|
||||
int cookie_db_init(main_server_st*);
|
||||
|
||||
|
||||
struct cookie_storage_st {
|
||||
cookie_store_fn store;
|
||||
cookie_retrieve_fn retrieve;
|
||||
cookie_expire_fn expire;
|
||||
cookie_expire_fn erase; /* erases cookies if stored in process */
|
||||
int (*init)(main_server_st *);
|
||||
cookie_db_deinit_fn deinit;
|
||||
};
|
||||
|
||||
extern struct cookie_storage_st gdbm_cookie_funcs;
|
||||
extern struct cookie_storage_st hash_cookie_funcs;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <net/if.h>
|
||||
#include <vpn.h>
|
||||
#include <tlslib.h>
|
||||
#include <cookies.h>
|
||||
|
||||
#define MAX_MSG_SIZE 256
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <vpn.h>
|
||||
#include <worker.h>
|
||||
#include <main.h>
|
||||
|
||||
const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
||||
void *_buf, size_t buflen)
|
||||
|
||||
+22
-45
@@ -155,29 +155,25 @@ int handle_auth_cookie_req(main_server_st* s, struct proc_st* proc,
|
||||
const struct cmd_auth_cookie_req_st * req)
|
||||
{
|
||||
int ret;
|
||||
struct stored_cookie_st *sc;
|
||||
struct stored_cookie_st sc;
|
||||
time_t now = time(0);
|
||||
|
||||
sc = malloc(sizeof(*sc));
|
||||
if (sc == NULL)
|
||||
return -1;
|
||||
|
||||
ret = retrieve_cookie(s, req->cookie, sizeof(req->cookie), sc);
|
||||
ret = decrypt_cookie(s, req->cookie, sizeof(req->cookie), &sc);
|
||||
if (ret < 0) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (sc->expiration < now) {
|
||||
if (sc.expiration < now) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memcpy(proc->cookie, req->cookie, sizeof(proc->cookie));
|
||||
memcpy(proc->username, sc->username, sizeof(proc->username));
|
||||
memcpy(proc->groupname, sc->groupname, sizeof(proc->groupname));
|
||||
memcpy(proc->hostname, sc->hostname, sizeof(proc->hostname));
|
||||
memcpy(proc->session_id, sc->session_id, sizeof(proc->session_id));
|
||||
memcpy(proc->username, sc.username, sizeof(proc->username));
|
||||
memcpy(proc->groupname, sc.groupname, sizeof(proc->groupname));
|
||||
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;
|
||||
@@ -197,51 +193,32 @@ time_t now = time(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ok auth ok. Renew the cookie. */
|
||||
sc->expiration = time(0) + s->config->cookie_validity;
|
||||
ret = store_cookie(s, sc);
|
||||
if (ret < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* sc is freed in store_cookie() */
|
||||
|
||||
return 0;
|
||||
cleanup:
|
||||
free(sc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int generate_and_store_vals(main_server_st *s, struct proc_st* proc)
|
||||
{
|
||||
int ret;
|
||||
struct stored_cookie_st *sc;
|
||||
struct stored_cookie_st sc;
|
||||
|
||||
ret = gnutls_rnd(GNUTLS_RND_RANDOM, proc->cookie, sizeof(proc->cookie));
|
||||
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, proc->cookie, sizeof(proc->cookie), &sc);
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, proc->session_id, sizeof(proc->session_id));
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
proc->session_id_size = sizeof(proc->session_id);
|
||||
|
||||
sc = calloc(1, sizeof(*sc));
|
||||
if (sc == NULL)
|
||||
return -2;
|
||||
|
||||
sc->expiration = time(0) + s->config->cookie_validity;
|
||||
|
||||
memcpy(sc->cookie, proc->cookie, sizeof(proc->cookie));
|
||||
memcpy(sc->username, proc->username, sizeof(sc->username));
|
||||
memcpy(sc->groupname, proc->groupname, sizeof(sc->groupname));
|
||||
memcpy(sc->hostname, proc->hostname, sizeof(sc->hostname));
|
||||
memcpy(sc->session_id, proc->session_id, sizeof(sc->session_id));
|
||||
|
||||
/* the sc pointer stays there */
|
||||
ret = store_cookie(s, sc);
|
||||
if (ret < 0) {
|
||||
free(sc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+6
-4
@@ -147,7 +147,7 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int accept_user(main_server_st *s, struct proc_st* proc, unsigned cmd)
|
||||
static int accept_user(main_server_st *s, struct proc_st* proc, unsigned cmd, const char* prev_user)
|
||||
{
|
||||
int ret;
|
||||
const char* group;
|
||||
@@ -155,7 +155,7 @@ const char* group;
|
||||
mslog(s, proc, LOG_DEBUG, "accepting user '%s'", proc->username);
|
||||
proc_auth_deinit(s, proc);
|
||||
|
||||
ret = open_tun(s, &proc->lease);
|
||||
ret = open_tun(s, &proc->lease, prev_user);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -201,6 +201,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
/* FIXME: do not write directly to the union */
|
||||
union {
|
||||
struct cmd_auth_req_st auth;
|
||||
struct cmd_auth_cookie_req_st cauth;
|
||||
@@ -347,7 +348,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = accept_user(s, proc, cmd);
|
||||
ret = accept_user(s, proc, cmd, NULL);
|
||||
if (ret < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -355,6 +356,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
goto cleanup;
|
||||
|
||||
case AUTH_COOKIE_REQ:
|
||||
|
||||
if (cmd_data_len != sizeof(cmd_data.cauth)) {
|
||||
mslog(s, proc, LOG_ERR, "error in received message (%u) length.", (unsigned)cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
@@ -366,7 +368,7 @@ int handle_commands(main_server_st *s, struct proc_st* proc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = accept_user(s, proc, cmd);
|
||||
ret = accept_user(s, proc, cmd, (proc->username[0] != 0)?proc->username:NULL);
|
||||
if (ret < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
+7
-8
@@ -36,6 +36,7 @@
|
||||
#include <script-list.h>
|
||||
|
||||
#include <gnutls/x509.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <tlslib.h>
|
||||
#include "ipc.h"
|
||||
#include "setproctitle.h"
|
||||
@@ -599,7 +600,6 @@ static void check_other_work(main_server_st *s)
|
||||
need_maintainance = 0;
|
||||
mslog(s, NULL, LOG_INFO, "Performing maintainance");
|
||||
expire_tls_sessions(s);
|
||||
expire_cookies(s);
|
||||
expire_banned(s);
|
||||
alarm(MAINTAINANCE_TIME(s));
|
||||
}
|
||||
@@ -656,6 +656,12 @@ int main(int argc, char** argv)
|
||||
/* Initialize GnuTLS */
|
||||
tls_global_init(&s);
|
||||
|
||||
ret = gnutls_rnd(GNUTLS_RND_RANDOM, s.cookie_key, sizeof(s.cookie_key));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error in cookie key generation\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* load configuration */
|
||||
ret = cmd_parser(argc, argv, &config);
|
||||
if (ret < 0) {
|
||||
@@ -675,12 +681,6 @@ int main(int argc, char** argv)
|
||||
|
||||
main_auth_init(&s);
|
||||
|
||||
ret = cookie_db_init(&s);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not initialize cookie database.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Listen to network ports */
|
||||
ret = listen_ports(&config, &s.llist, config.name);
|
||||
if (ret < 0) {
|
||||
@@ -808,7 +808,6 @@ int main(int argc, char** argv)
|
||||
*/
|
||||
close(cmd_fd[0]);
|
||||
clear_lists(&s);
|
||||
erase_cookies(&s);
|
||||
|
||||
setproctitle(PACKAGE_NAME"-worker");
|
||||
kill_on_parent_kill(SIGTERM);
|
||||
|
||||
+4
-2
@@ -8,6 +8,7 @@
|
||||
#include <vpn.h>
|
||||
#include <tlslib.h>
|
||||
#include "ipc.h"
|
||||
#include <cookies.h>
|
||||
|
||||
int cmd_parser (int argc, char **argv, struct cfg_st* config);
|
||||
void reload_cfg_file(struct cfg_st* config);
|
||||
@@ -99,7 +100,8 @@ typedef struct main_server_st {
|
||||
struct cfg_st *config;
|
||||
struct tun_st *tun;
|
||||
hash_db_st *tls_db;
|
||||
hash_db_st *cookie_db;
|
||||
|
||||
uint8_t cookie_key[16];
|
||||
|
||||
/* tls credentials */
|
||||
struct tls_st creds;
|
||||
@@ -148,7 +150,7 @@ __attribute__ ((format(printf, 4, 5)))
|
||||
void mslog_hex(const main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *prefix, uint8_t* bin, unsigned bin_size);
|
||||
|
||||
int open_tun(main_server_st* s, struct lease_st** l);
|
||||
int open_tun(main_server_st* s, struct lease_st** l, const char* prev_name);
|
||||
int set_tun_mtu(main_server_st* s, struct proc_st * proc, unsigned mtu);
|
||||
|
||||
int send_auth_reply_msg(main_server_st* s, struct proc_st* proc);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
||||
*
|
||||
* It has been AutoGen-ed June 27, 2013 at 05:58:30 PM by AutoGen 5.17.3
|
||||
* It has been AutoGen-ed July 1, 2013 at 12:18:22 PM by AutoGen 5.17.3
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -185,10 +185,6 @@ auth-timeout = 40
|
||||
# of that cookie.
|
||||
cookie-validity = 172800
|
||||
|
||||
# A cookie database. If not set cookies are stored in memory and
|
||||
# server restarts won't preserve them.
|
||||
#cookie-db = /var/tmp/cookies.db
|
||||
|
||||
# Script to call when a client connects and obtains an IP
|
||||
# Parameters are passed on the environment.
|
||||
# REASON, USERNAME, GROUPNAME, HOSTNAME (the hostname selected by client),
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
||||
*
|
||||
* It has been AutoGen-ed June 27, 2013 at 05:58:30 PM by AutoGen 5.17.3
|
||||
* It has been AutoGen-ed July 1, 2013 at 12:18:22 PM by AutoGen 5.17.3
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -289,7 +289,7 @@ static int set_network_info( main_server_st* s, const struct lease_st *lease)
|
||||
}
|
||||
|
||||
|
||||
int open_tun(main_server_st* s, struct lease_st** l)
|
||||
int open_tun(main_server_st* s, struct lease_st** l, const char* prev_name)
|
||||
{
|
||||
int tunfd, ret, e;
|
||||
struct ifreq ifr;
|
||||
@@ -298,6 +298,7 @@ int open_tun(main_server_st* s, struct lease_st** l)
|
||||
struct lease_st *last4, *tmp;
|
||||
struct lease_st *last6;
|
||||
unsigned current = s->tun->total;
|
||||
time_t now = time(0);
|
||||
|
||||
last4 = last6 = NULL;
|
||||
|
||||
@@ -305,7 +306,7 @@ int open_tun(main_server_st* s, struct lease_st** l)
|
||||
list_for_each(&s->tun->head, tmp, list) {
|
||||
/* if the device isn't in use by the server and the IPs
|
||||
* are free. */
|
||||
if (tmp->in_use == 0) {
|
||||
if (tmp->in_use == 0 && (tmp->available_at < now || (prev_name != NULL && strcmp(prev_name, tmp->name) == 0))) {
|
||||
if ((tmp->lip6_len != 0 && icmp_ping6(s, (void*)&tmp->lip6, (void*)&tmp->rip6) == 0) ||
|
||||
(tmp->lip4_len != 0 && icmp_ping4(s, (void*)&tmp->lip4, (void*)&tmp->rip4) == 0)) {
|
||||
lease = tmp;
|
||||
@@ -434,6 +435,7 @@ int open_tun(main_server_st* s, struct lease_st** l)
|
||||
}
|
||||
|
||||
lease->in_use = 1;
|
||||
lease->available_at = now + s->config->cookie_validity;
|
||||
lease->fd = tunfd;
|
||||
*l = lease;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ struct lease_st {
|
||||
char name[IFNAMSIZ];
|
||||
unsigned int tun_nr;
|
||||
unsigned int in_use;
|
||||
time_t available_at; /* when it will be available */
|
||||
|
||||
struct sockaddr_storage rip4;
|
||||
socklen_t rip4_len;
|
||||
|
||||
@@ -113,9 +113,6 @@ struct cfg_st {
|
||||
unsigned rate_limit_ms; /* if non zero force a connection every rate_limit milliseconds */
|
||||
unsigned ping_leases; /* non zero if we need to ping prior to leasing */
|
||||
|
||||
/* if gdbm is there */
|
||||
char* cookie_db_name;
|
||||
|
||||
char *connect_script;
|
||||
char *disconnect_script;
|
||||
|
||||
@@ -144,7 +141,6 @@ struct main_server_st;
|
||||
#define TLS_MASTER_SIZE 48
|
||||
#define MAX_HOSTNAME_SIZE MAX_USERNAME_SIZE
|
||||
#define MAX_GROUPNAME_SIZE MAX_USERNAME_SIZE
|
||||
#define COOKIE_SIZE 32
|
||||
#define MAX_SESSION_DATA_SIZE (4*1024)
|
||||
|
||||
const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
||||
|
||||
Reference in New Issue
Block a user