mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
dropped dependency on gdbm. Cookies are stored in a hash.
This commit is contained in:
@@ -111,9 +111,6 @@
|
||||
/* Define to 1 if you have the `fstat' function. */
|
||||
#undef HAVE_FSTAT
|
||||
|
||||
/* Enable the GDBM library */
|
||||
#undef HAVE_GDBM
|
||||
|
||||
/* Define to 1 if you have the `getdtablesize' function. */
|
||||
#undef HAVE_GETDTABLESIZE
|
||||
|
||||
|
||||
17
configure.ac
17
configure.ac
@@ -20,23 +20,6 @@ AC_C_BIGENDIAN
|
||||
|
||||
PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.0.28])
|
||||
|
||||
LIBS="$oldlibs -lgdbm"
|
||||
AC_MSG_CHECKING([for gdbm library])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <gdbm.h>],[
|
||||
GDBM_FILE dbf;
|
||||
dbf = gdbm_open("",0,0,0,0);])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
AC_SUBST([GDBM_LIBS], [-lgdbm])
|
||||
AC_SUBST([GDBM_CFLAGS], [])
|
||||
AC_DEFINE([HAVE_GDBM], 1, [Enable the GDBM library])],
|
||||
[AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([[
|
||||
***
|
||||
*** gdbm was not found. It is required for building this program.
|
||||
*** ]])])
|
||||
LIBS="$oldlibs"
|
||||
|
||||
LIBS="$oldlibs -lpam"
|
||||
AC_MSG_CHECKING([for pam library])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
|
||||
@@ -144,7 +144,6 @@ unsigned j;
|
||||
|
||||
READ_NUMERIC("cookie-validity", config->cookie_validity, 1);
|
||||
READ_NUMERIC("auth-timeout", config->auth_timeout, 0);
|
||||
READ_STRING("cookie-db", config->cookie_db, 1);
|
||||
READ_NUMERIC("max-clients", config->max_clients, 0);
|
||||
|
||||
val = optionGetValue(pov, "run-as-user"); \
|
||||
|
||||
163
src/cookies.c
163
src/cookies.c
@@ -30,116 +30,111 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <gdbm.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <main.h>
|
||||
#include <cookies.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
|
||||
/* All the functions return zero on success and a negative value on error */
|
||||
#define MAX_COOKIES(n) ((n>0)?(2*n):4096)
|
||||
|
||||
int store_cookie(const struct cfg_st *config, const void* cookie, unsigned cookie_size,
|
||||
const struct stored_cookie_st* sc)
|
||||
/* receives allocated data and stores them.
|
||||
*/
|
||||
int store_cookie(main_server_st *s, struct stored_cookie_st* sc)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
datum key;
|
||||
datum data;
|
||||
int ret;
|
||||
size_t key;
|
||||
|
||||
dbf = gdbm_open((char*)config->cookie_db, 0, GDBM_WRCREAT, S_IRUSR|S_IWUSR, NULL);
|
||||
if (dbf == NULL) {
|
||||
syslog(LOG_ERR, "Cannot open cookie database: %s", config->cookie_db);
|
||||
if (s->cookie_db->entries >= MAX_COOKIES(s->config->max_clients)) {
|
||||
syslog(LOG_INFO, "Maximum number of cookies was reached (%u)", MAX_COOKIES(s->config->max_clients));
|
||||
return -1;
|
||||
}
|
||||
|
||||
key.dptr = (void*)cookie;
|
||||
key.dsize = cookie_size;
|
||||
data.dptr = (void*)sc;
|
||||
data.dsize = sizeof(*sc);
|
||||
key = hash_stable_8(sc->cookie, COOKIE_SIZE, 0);
|
||||
|
||||
ret = gdbm_store( dbf, key, data, GDBM_INSERT);
|
||||
if (ret != 0) {
|
||||
ret = -1;
|
||||
goto finish;
|
||||
}
|
||||
htable_add(&s->cookie_db->ht, key, sc);
|
||||
s->cookie_db->entries++;
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
gdbm_close(dbf);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int retrieve_cookie(const struct cfg_st *config, const void* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* sc)
|
||||
int retrieve_cookie(main_server_st *s, const void* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* rsc)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
datum key;
|
||||
datum data;
|
||||
int ret;
|
||||
size_t key;
|
||||
struct htable_iter iter;
|
||||
struct stored_cookie_st * sc;
|
||||
|
||||
dbf = gdbm_open((char*)config->cookie_db, 0, GDBM_READER, 0, NULL);
|
||||
if (dbf == NULL) {
|
||||
syslog(LOG_ERR, "Cannot open cookie database: %s", config->cookie_db);
|
||||
return -1;
|
||||
}
|
||||
key = hash_stable_8(cookie, cookie_size, 0);
|
||||
|
||||
key.dptr = (void*)cookie;
|
||||
key.dsize = cookie_size;
|
||||
sc = htable_firstval(&s->cookie_db->ht, &iter, key);
|
||||
while(sc != NULL) {
|
||||
if (cookie_size == COOKIE_SIZE &&
|
||||
memcmp (cookie, sc->cookie, COOKIE_SIZE) == 0) {
|
||||
|
||||
data = gdbm_fetch( dbf, key);
|
||||
if (data.dsize != sizeof(*sc)) {
|
||||
ret = -1;
|
||||
goto finish;
|
||||
}
|
||||
memcpy(sc, data.dptr, data.dsize);
|
||||
if (sc->expiration < time(0))
|
||||
return -1;
|
||||
|
||||
memcpy(rsc, sc, sizeof(*sc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sc->expiration >= time(0))
|
||||
ret = 0;
|
||||
else
|
||||
ret = -1;
|
||||
sc = htable_nextval(&s->cookie_db->ht, &iter, key);
|
||||
}
|
||||
|
||||
finish:
|
||||
gdbm_close(dbf);
|
||||
return ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void expire_cookies(main_server_st* s)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
datum key;
|
||||
datum data;
|
||||
int deleted = 0;
|
||||
struct stored_cookie_st sc;
|
||||
struct stored_cookie_st *sc;
|
||||
struct htable_iter iter;
|
||||
time_t now = time(0);
|
||||
|
||||
dbf = gdbm_open((char*)s->config->cookie_db, 0, GDBM_WRITER, 0, NULL);
|
||||
if (dbf == NULL)
|
||||
return;
|
||||
|
||||
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++;
|
||||
}
|
||||
sc = htable_first(&s->cookie_db->ht, &iter);
|
||||
while(sc != NULL) {
|
||||
if (sc->expiration <= now) {
|
||||
htable_delval(&s->cookie_db->ht, &iter);
|
||||
free(sc);
|
||||
s->cookie_db->entries--;
|
||||
}
|
||||
|
||||
key = gdbm_nextkey(dbf, key);
|
||||
}
|
||||
|
||||
if (deleted > 0)
|
||||
gdbm_reorganize(dbf);
|
||||
|
||||
finish:
|
||||
gdbm_close(dbf);
|
||||
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);
|
||||
}
|
||||
|
||||
void cookie_db_init(hash_db_st** _db)
|
||||
{
|
||||
hash_db_st * db;
|
||||
|
||||
db = malloc(sizeof(*db));
|
||||
if (db == NULL)
|
||||
exit(1);
|
||||
|
||||
htable_init(&db->ht, rehash, NULL);
|
||||
db->entries = 0;
|
||||
|
||||
*_db = db;
|
||||
}
|
||||
|
||||
void cookie_db_deinit(hash_db_st* db)
|
||||
{
|
||||
struct stored_cookie_st* cache;
|
||||
struct htable_iter iter;
|
||||
|
||||
cache = htable_first(&db->ht, &iter);
|
||||
while(cache != NULL) {
|
||||
free(cache);
|
||||
cache = htable_next(&db->ht, &iter);
|
||||
}
|
||||
htable_clear(&db->ht);
|
||||
db->entries = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,18 +2,22 @@
|
||||
#define COOKIES_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
|
||||
struct __attribute__ ((__packed__)) stored_cookie_st {
|
||||
struct stored_cookie_st {
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
char hostname[MAX_USERNAME_SIZE];
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
time_t expiration;
|
||||
};
|
||||
|
||||
int store_cookie(const struct cfg_st *, const void* cookie, unsigned cookie_size,
|
||||
const struct stored_cookie_st* sc);
|
||||
int store_cookie(main_server_st *, struct stored_cookie_st* sc);
|
||||
|
||||
int retrieve_cookie(const struct cfg_st *, const void* cookie, unsigned cookie_size,
|
||||
int retrieve_cookie(main_server_st *, const void* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* sc);
|
||||
|
||||
void cookie_db_deinit(hash_db_st* db);
|
||||
void cookie_db_init(hash_db_st** _db);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -104,7 +104,7 @@ static int handle_auth_cookie_req(main_server_st* s, struct proc_st* proc,
|
||||
int ret;
|
||||
struct stored_cookie_st sc;
|
||||
|
||||
ret = retrieve_cookie(s->config, req->cookie, sizeof(req->cookie), &sc);
|
||||
ret = retrieve_cookie(s, req->cookie, sizeof(req->cookie), &sc);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ static
|
||||
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));
|
||||
if (ret < 0)
|
||||
@@ -135,16 +135,23 @@ struct stored_cookie_st sc;
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
|
||||
memset(&sc, 0, sizeof(sc));
|
||||
sc.expiration = time(0) + s->config->cookie_validity;
|
||||
sc = calloc(1, sizeof(*sc));
|
||||
if (sc == NULL)
|
||||
return -2;
|
||||
|
||||
sc->expiration = time(0) + s->config->cookie_validity;
|
||||
|
||||
memcpy(sc.username, proc->username, sizeof(sc.username));
|
||||
memcpy(sc.hostname, proc->hostname, sizeof(sc.hostname));
|
||||
memcpy(sc.session_id, proc->session_id, sizeof(sc.session_id));
|
||||
memcpy(sc->cookie, proc->cookie, sizeof(proc->cookie));
|
||||
memcpy(sc->username, proc->username, sizeof(sc->username));
|
||||
memcpy(sc->hostname, proc->hostname, sizeof(sc->hostname));
|
||||
memcpy(sc->session_id, proc->session_id, sizeof(sc->session_id));
|
||||
|
||||
ret = store_cookie(s->config, proc->cookie, sizeof(proc->cookie), &sc);
|
||||
if (ret < 0)
|
||||
/* the sc pointer stays there */
|
||||
ret = store_cookie(s, sc);
|
||||
if (ret < 0) {
|
||||
free(sc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -352,11 +352,11 @@ int main(int argc, char** argv)
|
||||
struct cfg_st config;
|
||||
unsigned active_clients = 0;
|
||||
main_server_st s;
|
||||
tls_cache_db_st* tls_db;
|
||||
|
||||
list_head_init(&clist.head);
|
||||
tun_st_init(&tun);
|
||||
tls_cache_init(&config, &tls_db);
|
||||
tls_cache_init(&s.tls_db);
|
||||
cookie_db_init(&s.cookie_db);
|
||||
|
||||
signal(SIGINT, handle_term);
|
||||
signal(SIGTERM, handle_term);
|
||||
@@ -379,7 +379,6 @@ int main(int argc, char** argv)
|
||||
|
||||
s.config = &config;
|
||||
s.tun = &tun;
|
||||
s.tls_db = tls_db;
|
||||
s.llist = &llist;
|
||||
s.clist = &clist;
|
||||
|
||||
|
||||
@@ -44,8 +44,9 @@ struct proc_list_st {
|
||||
typedef struct main_server_st {
|
||||
struct cfg_st *config;
|
||||
struct tun_st *tun;
|
||||
tls_cache_db_st *tls_db;
|
||||
|
||||
hash_db_st *tls_db;
|
||||
hash_db_st *cookie_db;
|
||||
|
||||
struct listen_list_st* llist;
|
||||
struct proc_list_st* clist;
|
||||
} main_server_st;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
||||
*
|
||||
* It has been AutoGen-ed February 6, 2013 at 06:03:52 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed February 7, 2013 at 12:56:29 AM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -68,7 +68,11 @@ An example configuration file follows.
|
||||
auth = "pam"
|
||||
|
||||
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
||||
# listen-host = [IP|HOSTNAME]
|
||||
#listen-host = [IP|HOSTNAME]
|
||||
|
||||
# Limit the number of clients. Unset or set to zero for unlimited.
|
||||
#max-clients = 1024
|
||||
max-clients = 16
|
||||
|
||||
# TCP port number
|
||||
tcp-port = 3333
|
||||
@@ -114,9 +118,6 @@ cookie-validity = 14400
|
||||
connect-script = /bin/echo
|
||||
disconnect-script = /bin/echo
|
||||
|
||||
# Cookie database file. Where to store the cookies.
|
||||
cookie-db = /path/to/db
|
||||
|
||||
# UTMP
|
||||
use-utmp = true
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
||||
*
|
||||
* It has been AutoGen-ed February 6, 2013 at 06:03:51 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed February 7, 2013 at 12:56:29 AM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -51,9 +51,6 @@ tls-priorities = "PERFORMANCE:%SERVER_PRECEDENCE:%COMPAT"
|
||||
# of that cookie.
|
||||
cookie-validity = 14400
|
||||
|
||||
# Cookie database file. Where to store the cookies.
|
||||
cookie-db = /var/tmp/ocserv-cookie.db
|
||||
|
||||
run-as-user = nobody
|
||||
run-as-group = nogroup
|
||||
|
||||
|
||||
@@ -124,9 +124,9 @@ const tls_cache_st *e = _e;
|
||||
return hash_stable_8(e->session_id, e->session_id_size, 0);
|
||||
}
|
||||
|
||||
void tls_cache_init(struct cfg_st* config, tls_cache_db_st** _db)
|
||||
void tls_cache_init(hash_db_st** _db)
|
||||
{
|
||||
tls_cache_db_st * db;
|
||||
hash_db_st * db;
|
||||
|
||||
db = malloc(sizeof(*db));
|
||||
if (db == NULL)
|
||||
@@ -138,7 +138,7 @@ tls_cache_db_st * db;
|
||||
*_db = db;
|
||||
}
|
||||
|
||||
void tls_cache_deinit(tls_cache_db_st* db)
|
||||
void tls_cache_deinit(hash_db_st* db)
|
||||
{
|
||||
tls_cache_st* cache;
|
||||
struct htable_iter iter;
|
||||
|
||||
@@ -46,13 +46,8 @@ typedef struct
|
||||
|
||||
#define TLS_SESSION_EXPIRATION_TIME 600
|
||||
#define DEFAULT_MAX_CACHED_TLS_SESSIONS(db) 256
|
||||
typedef struct
|
||||
{
|
||||
struct htable ht;
|
||||
unsigned int entries;
|
||||
} tls_cache_db_st;
|
||||
|
||||
void tls_cache_init(struct cfg_st* config, tls_cache_db_st** db);
|
||||
void tls_cache_deinit(tls_cache_db_st* db);
|
||||
void tls_cache_init(hash_db_st** db);
|
||||
void tls_cache_deinit(hash_db_st* db);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <config.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <http-parser/http_parser.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -27,6 +28,13 @@ extern int syslog_open;
|
||||
#define AUTH_TYPE_PAM (1<<1 | AUTH_TYPE_USERNAME_PASS)
|
||||
#define AUTH_TYPE_CERTIFICATE (1<<2)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct htable ht;
|
||||
unsigned int entries;
|
||||
} hash_db_st;
|
||||
|
||||
|
||||
struct vpn_st {
|
||||
const char *name; /* device name */
|
||||
const char *ipv4_netmask;
|
||||
@@ -57,7 +65,6 @@ struct cfg_st {
|
||||
time_t cookie_validity; /* in seconds */
|
||||
unsigned auth_timeout; /* timeout of HTTP auth */
|
||||
unsigned keepalive;
|
||||
const char *cookie_db;
|
||||
unsigned foreground;
|
||||
unsigned tls_debug;
|
||||
unsigned debug;
|
||||
|
||||
Reference in New Issue
Block a user