dropped dependency on gdbm. Cookies are stored in a hash.

This commit is contained in:
Nikos Mavrogiannopoulos
2013-02-07 00:57:17 +01:00
parent bf3aef7fd0
commit 4370f88001
15 changed files with 128 additions and 143 deletions

View File

@@ -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

View File

@@ -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([

View File

@@ -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"); \

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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
*

View File

@@ -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

View File

@@ -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
*

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;