mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
Added session resumption to TLS server.
This commit is contained in:
@@ -446,6 +446,9 @@
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#undef SIZEOF_SHORT
|
||||
|
||||
/* The size of `unsigned long', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_LONG
|
||||
|
||||
/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type
|
||||
'size_t'. */
|
||||
#undef SIZE_T_SUFFIX
|
||||
|
||||
@@ -15,6 +15,8 @@ if [ test "$GCC" = "yes" ];then
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF([unsigned long])
|
||||
|
||||
PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.0.0])
|
||||
|
||||
LIBS="$oldlibs -lgdbm"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl gettime memmem
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl gettime hash-pjw-bare memmem
|
||||
|
||||
AUTOMAKE_OPTIONS = 1.5 gnits
|
||||
|
||||
@@ -64,6 +64,12 @@ EXTRA_libgnu_a_SOURCES += gettimeofday.c
|
||||
|
||||
## end gnulib module gettimeofday
|
||||
|
||||
## begin gnulib module hash-pjw-bare
|
||||
|
||||
libgnu_a_SOURCES += hash-pjw-bare.h hash-pjw-bare.c
|
||||
|
||||
## end gnulib module hash-pjw-bare
|
||||
|
||||
## begin gnulib module memchr
|
||||
|
||||
|
||||
|
||||
42
gl/hash-pjw-bare.c
Normal file
42
gl/hash-pjw-bare.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/* hash-pjw-bare.c -- compute a hash value from a provided buffer.
|
||||
|
||||
Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "hash-pjw-bare.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
|
||||
|
||||
/* Return a hash of the N bytes of X using the method described by
|
||||
Bruno Haible in http://www.haible.de/bruno/hashfunc.html.
|
||||
Note that while many hash functions reduce their result via modulo
|
||||
to a 0..table_size-1 range, this function does not do that. */
|
||||
|
||||
size_t
|
||||
hash_pjw_bare (const void *x, size_t n)
|
||||
{
|
||||
const unsigned char *s = x;
|
||||
size_t h = 0;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
h = s[i] + ((h << 9) | (h >> (SIZE_BITS - 9)));
|
||||
|
||||
return h;
|
||||
}
|
||||
24
gl/hash-pjw-bare.h
Normal file
24
gl/hash-pjw-bare.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* hash-pjw-bare.h -- declaration for a simple hash function
|
||||
Copyright (C) 2012-2013 Free Software Foundation, Inc.
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Compute a hash code for a buffer starting at X and of size N,
|
||||
and return the hash code. Note that unlike hash_pjw(), it does not
|
||||
return it modulo a table size.
|
||||
The result is platform dependent: it depends on the size of the 'size_t'
|
||||
type and on the signedness of the 'char' type. */
|
||||
extern size_t hash_pjw_bare (const void *x, size_t n) _GL_ATTRIBUTE_PURE;
|
||||
@@ -27,12 +27,13 @@
|
||||
|
||||
|
||||
# Specification in the form of a command-line invocation:
|
||||
# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl gettime memmem
|
||||
# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=gl/tests --aux-dir=build-aux --no-conditional-dependencies --no-libtool --macro-prefix=gl gettime hash-pjw-bare memmem
|
||||
|
||||
# Specification in the form of a few gnulib-tool.m4 macro invocations:
|
||||
gl_LOCAL_DIR([])
|
||||
gl_MODULES([
|
||||
gettime
|
||||
hash-pjw-bare
|
||||
memmem
|
||||
])
|
||||
gl_AVOID([])
|
||||
|
||||
@@ -44,6 +44,7 @@ AC_DEFUN([gl_EARLY],
|
||||
# Code from module extern-inline:
|
||||
# Code from module gettime:
|
||||
# Code from module gettimeofday:
|
||||
# Code from module hash-pjw-bare:
|
||||
# Code from module include_next:
|
||||
# Code from module memchr:
|
||||
# Code from module memmem:
|
||||
@@ -253,6 +254,8 @@ AC_DEFUN([gl_FILE_LIST], [
|
||||
build-aux/snippet/warn-on-use.h
|
||||
lib/gettime.c
|
||||
lib/gettimeofday.c
|
||||
lib/hash-pjw-bare.c
|
||||
lib/hash-pjw-bare.h
|
||||
lib/memchr.c
|
||||
lib/memchr.valgrind
|
||||
lib/memmem.c
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
Ideally we should test __BIONIC__ here, but it is only defined after
|
||||
<sys/cdefs.h> has been included; hence test __ANDROID__ instead. */
|
||||
#if defined __ANDROID__ \
|
||||
&& defined _SYS_TYPES_H_ && !defined _SSIZE_T_DEFINED_
|
||||
&& defined _SYS_TYPES_H_ && !defined __need_size_t
|
||||
# @INCLUDE_NEXT@ @NEXT_STDINT_H@
|
||||
#else
|
||||
|
||||
|
||||
@@ -17,37 +17,34 @@
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#ifndef _@GUARD_PREFIX@_SYS_TIME_H
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
@PRAGMA_SYSTEM_HEADER@
|
||||
#endif
|
||||
@PRAGMA_COLUMNS@
|
||||
|
||||
#if defined _@GUARD_PREFIX@_SYS_TIME_H
|
||||
|
||||
/* Simply delegate to the system's header, without adding anything. */
|
||||
# if @HAVE_SYS_TIME_H@
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
#if @HAVE_SYS_TIME_H@
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
#ifndef _@GUARD_PREFIX@_SYS_TIME_H
|
||||
#define _@GUARD_PREFIX@_SYS_TIME_H
|
||||
|
||||
# define _@GUARD_PREFIX@_SYS_TIME_H
|
||||
|
||||
# if @HAVE_SYS_TIME_H@
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
|
||||
# else
|
||||
#if ! @HAVE_SYS_TIME_H@
|
||||
# include <time.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* On native Windows with MSVC, get the 'struct timeval' type.
|
||||
Also, on native Windows with a 64-bit time_t, where we are overriding the
|
||||
'struct timeval' type, get all declarations of system functions whose
|
||||
signature contains 'struct timeval'. */
|
||||
# if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H
|
||||
#if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H
|
||||
# define _GL_INCLUDING_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
# undef _GL_INCLUDING_WINSOCK2_H
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
|
||||
|
||||
@@ -55,11 +52,11 @@
|
||||
|
||||
/* The definition of _GL_WARN_ON_USE is copied here. */
|
||||
|
||||
# ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@
|
||||
#if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@
|
||||
|
||||
# if @REPLACE_STRUCT_TIMEVAL@
|
||||
# define timeval rpl_timeval
|
||||
@@ -74,13 +71,13 @@ struct timeval
|
||||
# define GNULIB_defined_struct_timeval 1
|
||||
# endif
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# if @GNULIB_GETTIMEOFDAY@
|
||||
#if @GNULIB_GETTIMEOFDAY@
|
||||
# if @REPLACE_GETTIMEOFDAY@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef gettimeofday
|
||||
@@ -103,17 +100,17 @@ _GL_CXXALIAS_SYS_CAST (gettimeofday, int,
|
||||
(struct timeval *restrict, void *restrict));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (gettimeofday);
|
||||
# elif defined GNULIB_POSIXCHECK
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
# undef gettimeofday
|
||||
# if HAVE_RAW_DECL_GETTIMEOFDAY
|
||||
_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - "
|
||||
"use gnulib module gettimeofday for portability");
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Hide some function declarations from <winsock2.h>. */
|
||||
|
||||
# if defined _MSC_VER && @HAVE_WINSOCK2_H@
|
||||
#if defined _MSC_VER && @HAVE_WINSOCK2_H@
|
||||
# if !defined _@GUARD_PREFIX@_UNISTD_H
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef close
|
||||
@@ -200,6 +197,7 @@ _GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - "
|
||||
"select() used without including <sys/select.h>");
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _@GUARD_PREFIX@_SYS_TIME_H */
|
||||
#endif /* _@GUARD_PREFIX@_SYS_TIME_H */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
AM_CPPFLAGS = -I$(srcdir)../gl/ -I$(builddir)../gl/ \
|
||||
AM_CPPFLAGS = -I$(srcdir)/../gl/ -I$(builddir)/../gl/ \
|
||||
-I$(srcdir)/ -I$(builddir)/../ -I$(srcdir)/../libopts
|
||||
|
||||
EXTRA_DIST = ocserv.1 sample.config
|
||||
@@ -8,7 +8,8 @@ bin_PROGRAMS = ocserv
|
||||
ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
cookies.c http-parser/http_parser.c \
|
||||
vpn.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \
|
||||
config.c worker-auth.h pam.c pam.h
|
||||
config.c worker-auth.h pam.c pam.h worker-resume.c worker.h hash.h \
|
||||
hashtable.h main-resume.c
|
||||
|
||||
ocserv_SOURCES += ocserv-args.def ocserv-args.c ocserv-args.h
|
||||
|
||||
|
||||
80
src/hash.h
Normal file
80
src/hash.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef _LINUX_HASH_H
|
||||
#define _LINUX_HASH_H
|
||||
/* Fast hashing routine for ints, longs and pointers.
|
||||
(C) 2002 Nadia Yvette Chambers, IBM */
|
||||
|
||||
/*
|
||||
* Knuth recommends primes in approximately golden ratio to the maximum
|
||||
* integer representable by a machine word for multiplicative hashing.
|
||||
* Chuck Lever verified the effectiveness of this technique:
|
||||
* http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
|
||||
*
|
||||
* These primes are chosen to be bit-sparse, that is operations on
|
||||
* them can use shifts and additions instead of multiplications for
|
||||
* machines where multiplications are slow.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
|
||||
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL
|
||||
/* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
|
||||
#define GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001UL
|
||||
|
||||
#if SIZEOF_UNSIGNED_LONG == 4
|
||||
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_PRIME_32
|
||||
#define hash_long(val, bits) hash_32(val, bits)
|
||||
#elif SIZEOF_UNSIGNED_LONG == 8
|
||||
#define hash_long(val, bits) hash_64(val, bits)
|
||||
#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_PRIME_64
|
||||
#else
|
||||
#error Wordsize not 32 or 64
|
||||
#endif
|
||||
|
||||
static inline uint64_t hash_64(uint64_t val, unsigned int bits)
|
||||
{
|
||||
uint64_t hash = val;
|
||||
|
||||
/* Sigh, gcc can't optimise this alone like it does for 32 bits. */
|
||||
uint64_t n = hash;
|
||||
n <<= 18;
|
||||
hash -= n;
|
||||
n <<= 33;
|
||||
hash -= n;
|
||||
n <<= 3;
|
||||
hash += n;
|
||||
n <<= 3;
|
||||
hash -= n;
|
||||
n <<= 4;
|
||||
hash += n;
|
||||
n <<= 2;
|
||||
hash += n;
|
||||
|
||||
/* High bits are more random, so use them. */
|
||||
return hash >> (64 - bits);
|
||||
}
|
||||
|
||||
static inline uint32_t hash_32(uint32_t val, unsigned int bits)
|
||||
{
|
||||
/* On some cpus multiply is faster, on others gcc will do shifts */
|
||||
uint32_t hash = val * GOLDEN_RATIO_PRIME_32;
|
||||
|
||||
/* High bits are more random, so use them. */
|
||||
return hash >> (32 - bits);
|
||||
}
|
||||
|
||||
static inline unsigned long hash_ptr(const void *ptr, unsigned int bits)
|
||||
{
|
||||
return hash_long((unsigned long)ptr, bits);
|
||||
}
|
||||
|
||||
static inline uint32_t hash32_ptr(const void *ptr)
|
||||
{
|
||||
unsigned long val = (unsigned long)ptr;
|
||||
|
||||
#if SIZEOF_UNSIGNED_LONG == 8
|
||||
val ^= (val >> 32);
|
||||
#endif
|
||||
return (uint32_t)val;
|
||||
}
|
||||
#endif /* _LINUX_HASH_H */
|
||||
231
src/hashtable.h
Normal file
231
src/hashtable.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Statically sized hash table implementation
|
||||
* (C) 2012 Sasha Levin <levinsasha928@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_HASHTABLE_H
|
||||
#define _LINUX_HASHTABLE_H
|
||||
|
||||
#include <list.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
|
||||
* @n - parameter
|
||||
*
|
||||
* constant-capable log of base 2 calculation
|
||||
* - this can be used to initialise global variables from constant data, hence
|
||||
* the massive ternary operator construction
|
||||
*
|
||||
* selects the appropriately-sized optimised version depending on sizeof(n)
|
||||
*/
|
||||
#define hash_ilog2(n) \
|
||||
( \
|
||||
__builtin_constant_p(n) ? ( \
|
||||
(n) < 1 ? -1 : \
|
||||
(n) & (1ULL << 63) ? 63 : \
|
||||
(n) & (1ULL << 62) ? 62 : \
|
||||
(n) & (1ULL << 61) ? 61 : \
|
||||
(n) & (1ULL << 60) ? 60 : \
|
||||
(n) & (1ULL << 59) ? 59 : \
|
||||
(n) & (1ULL << 58) ? 58 : \
|
||||
(n) & (1ULL << 57) ? 57 : \
|
||||
(n) & (1ULL << 56) ? 56 : \
|
||||
(n) & (1ULL << 55) ? 55 : \
|
||||
(n) & (1ULL << 54) ? 54 : \
|
||||
(n) & (1ULL << 53) ? 53 : \
|
||||
(n) & (1ULL << 52) ? 52 : \
|
||||
(n) & (1ULL << 51) ? 51 : \
|
||||
(n) & (1ULL << 50) ? 50 : \
|
||||
(n) & (1ULL << 49) ? 49 : \
|
||||
(n) & (1ULL << 48) ? 48 : \
|
||||
(n) & (1ULL << 47) ? 47 : \
|
||||
(n) & (1ULL << 46) ? 46 : \
|
||||
(n) & (1ULL << 45) ? 45 : \
|
||||
(n) & (1ULL << 44) ? 44 : \
|
||||
(n) & (1ULL << 43) ? 43 : \
|
||||
(n) & (1ULL << 42) ? 42 : \
|
||||
(n) & (1ULL << 41) ? 41 : \
|
||||
(n) & (1ULL << 40) ? 40 : \
|
||||
(n) & (1ULL << 39) ? 39 : \
|
||||
(n) & (1ULL << 38) ? 38 : \
|
||||
(n) & (1ULL << 37) ? 37 : \
|
||||
(n) & (1ULL << 36) ? 36 : \
|
||||
(n) & (1ULL << 35) ? 35 : \
|
||||
(n) & (1ULL << 34) ? 34 : \
|
||||
(n) & (1ULL << 33) ? 33 : \
|
||||
(n) & (1ULL << 32) ? 32 : \
|
||||
(n) & (1ULL << 31) ? 31 : \
|
||||
(n) & (1ULL << 30) ? 30 : \
|
||||
(n) & (1ULL << 29) ? 29 : \
|
||||
(n) & (1ULL << 28) ? 28 : \
|
||||
(n) & (1ULL << 27) ? 27 : \
|
||||
(n) & (1ULL << 26) ? 26 : \
|
||||
(n) & (1ULL << 25) ? 25 : \
|
||||
(n) & (1ULL << 24) ? 24 : \
|
||||
(n) & (1ULL << 23) ? 23 : \
|
||||
(n) & (1ULL << 22) ? 22 : \
|
||||
(n) & (1ULL << 21) ? 21 : \
|
||||
(n) & (1ULL << 20) ? 20 : \
|
||||
(n) & (1ULL << 19) ? 19 : \
|
||||
(n) & (1ULL << 18) ? 18 : \
|
||||
(n) & (1ULL << 17) ? 17 : \
|
||||
(n) & (1ULL << 16) ? 16 : \
|
||||
(n) & (1ULL << 15) ? 15 : \
|
||||
(n) & (1ULL << 14) ? 14 : \
|
||||
(n) & (1ULL << 13) ? 13 : \
|
||||
(n) & (1ULL << 12) ? 12 : \
|
||||
(n) & (1ULL << 11) ? 11 : \
|
||||
(n) & (1ULL << 10) ? 10 : \
|
||||
(n) & (1ULL << 9) ? 9 : \
|
||||
(n) & (1ULL << 8) ? 8 : \
|
||||
(n) & (1ULL << 7) ? 7 : \
|
||||
(n) & (1ULL << 6) ? 6 : \
|
||||
(n) & (1ULL << 5) ? 5 : \
|
||||
(n) & (1ULL << 4) ? 4 : \
|
||||
(n) & (1ULL << 3) ? 3 : \
|
||||
(n) & (1ULL << 2) ? 2 : \
|
||||
(n) & (1ULL << 1) ? 1 : \
|
||||
(n) & (1ULL << 0) ? 0 : \
|
||||
-1 \
|
||||
) : \
|
||||
-1 \
|
||||
)
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
#define DEFINE_HASHTABLE(name, bits) \
|
||||
struct hlist_head name[1 << (bits)] = \
|
||||
{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
|
||||
|
||||
#define DECLARE_HASHTABLE(name, bits) \
|
||||
struct hlist_head name[1 << (bits)]
|
||||
|
||||
#define HASH_SIZE(name) (ARRAY_SIZE(name))
|
||||
#define HASH_BITS(name) hash_ilog2(HASH_SIZE(name))
|
||||
|
||||
/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
|
||||
#define hash_min(val, bits) \
|
||||
(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
|
||||
|
||||
static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
INIT_HLIST_HEAD(&ht[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_init - initialize a hash table
|
||||
* @hashtable: hashtable to be initialized
|
||||
*
|
||||
* Calculates the size of the hashtable from the given parameter, otherwise
|
||||
* same as hash_init_size.
|
||||
*
|
||||
* This has to be a macro since HASH_BITS() will not work on pointers since
|
||||
* it calculates the size during preprocessing.
|
||||
*/
|
||||
#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
|
||||
|
||||
/**
|
||||
* hash_add - add an object to a hashtable
|
||||
* @hashtable: hashtable to add to
|
||||
* @node: the &struct hlist_node of the object to be added
|
||||
* @key: the key of the object to be added
|
||||
*/
|
||||
#define hash_add(hashtable, node, key) \
|
||||
hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
|
||||
|
||||
/**
|
||||
* hash_hashed - check whether an object is in any hashtable
|
||||
* @node: the &struct hlist_node of the object to be checked
|
||||
*/
|
||||
static inline unsigned hash_hashed(struct hlist_node *node)
|
||||
{
|
||||
return !hlist_unhashed(node);
|
||||
}
|
||||
|
||||
static inline unsigned __hash_empty(struct hlist_head *ht, unsigned int sz)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
if (!hlist_empty(&ht[i]))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_empty - check whether a hashtable is empty
|
||||
* @hashtable: hashtable to check
|
||||
*
|
||||
* This has to be a macro since HASH_BITS() will not work on pointers since
|
||||
* it calculates the size during preprocessing.
|
||||
*/
|
||||
#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
|
||||
|
||||
/**
|
||||
* hash_del - remove an object from a hashtable
|
||||
* @node: &struct hlist_node of the object to remove
|
||||
*/
|
||||
static inline void hash_del(struct hlist_node *node)
|
||||
{
|
||||
hlist_del_init(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_for_each - iterate over a hashtable
|
||||
* @name: hashtable to iterate
|
||||
* @bkt: integer to use as bucket loop cursor
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
*/
|
||||
#define hash_for_each(name, bkt, node, obj, member) \
|
||||
for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
|
||||
hlist_for_each_entry(obj, node, &name[bkt], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_safe - iterate over a hashtable safe against removal of
|
||||
* hash entry
|
||||
* @name: hashtable to iterate
|
||||
* @bkt: integer to use as bucket loop cursor
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @tmp: a &struct used for temporary storage
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
*/
|
||||
#define hash_for_each_safe(name, bkt, node, tmp, obj, member) \
|
||||
for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
|
||||
hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_possible - iterate over all possible objects hashing to the
|
||||
* same bucket
|
||||
* @name: hashtable to iterate
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
* @key: the key of the objects to iterate over
|
||||
*/
|
||||
#define hash_for_each_possible(name, obj, node, member, key) \
|
||||
hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_possible_safe - iterate over all possible objects hashing to the
|
||||
* same bucket safe against removals
|
||||
* @name: hashtable to iterate
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @tmp: a &struct used for temporary storage
|
||||
* @member: the name of the hlist_node within the struct
|
||||
* @key: the key of the objects to iterate over
|
||||
*/
|
||||
#define hash_for_each_possible_safe(name, obj, node, tmp, member, key) \
|
||||
hlist_for_each_entry_safe(obj, node, tmp, \
|
||||
&name[hash_min(key, HASH_BITS(name))], member)
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef WORKER_AUTH_H
|
||||
#define WORKER_AUTH_H
|
||||
#ifndef IPC_H
|
||||
#define IPC_H
|
||||
|
||||
#include <config.h>
|
||||
#include <syslog.h>
|
||||
@@ -9,11 +9,16 @@
|
||||
#include <net/if.h>
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
typedef enum {
|
||||
AUTH_REQ = 1,
|
||||
AUTH_COOKIE_REQ,
|
||||
AUTH_REP,
|
||||
RESUME_STORE_REQ,
|
||||
RESUME_DELETE_REQ,
|
||||
RESUME_FETCH_REQ,
|
||||
RESUME_FETCH_REP,
|
||||
CMD_TERMINATE,
|
||||
} cmd_request_t;
|
||||
|
||||
@@ -22,6 +27,11 @@ typedef enum {
|
||||
REP_AUTH_FAILED = 1,
|
||||
} cmd_auth_reply_t;
|
||||
|
||||
typedef enum {
|
||||
REP_RESUME_OK = 0,
|
||||
REP_RESUME_FAILED = 1,
|
||||
} cmd_resume_reply_t;
|
||||
|
||||
/* AUTH_COOKIE_REQ */
|
||||
struct __attribute__ ((__packed__)) cmd_auth_cookie_req_st {
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
@@ -47,10 +57,25 @@ struct __attribute__ ((__packed__)) cmd_auth_reply_st {
|
||||
char user[MAX_USERNAME_SIZE];
|
||||
};
|
||||
|
||||
int auth_cookie(worker_st *ws, void* cookie, size_t cookie_size);
|
||||
/* RESUME_FETCH_REQ + RESUME_DELETE_REQ */
|
||||
struct __attribute__ ((__packed__)) cmd_resume_fetch_req_st {
|
||||
uint8_t session_id_size;
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
};
|
||||
|
||||
int get_auth_handler(worker_st *server);
|
||||
int post_old_auth_handler(worker_st *server);
|
||||
int post_new_auth_handler(worker_st *server);
|
||||
/* RESUME_STORE_REQ */
|
||||
struct __attribute__ ((__packed__)) cmd_resume_store_req_st {
|
||||
uint8_t session_id_size;
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
uint16_t session_data_size;
|
||||
uint8_t session_data[MAX_SESSION_DATA_SIZE];
|
||||
};
|
||||
|
||||
/* RESUME_FETCH_REP */
|
||||
struct __attribute__ ((__packed__)) cmd_resume_fetch_reply_st {
|
||||
uint8_t reply;
|
||||
uint16_t session_data_size;
|
||||
uint8_t session_data[MAX_SESSION_DATA_SIZE];
|
||||
};
|
||||
|
||||
#endif
|
||||
171
src/list.h
171
src/list.h
@@ -575,4 +575,175 @@ static inline void list_splice_tail_init(struct list_head *list,
|
||||
n = list_entry(pos->member.next, typeof(*pos), member)
|
||||
|
||||
|
||||
/*
|
||||
* Double linked lists with a single pointer list head.
|
||||
* Mostly useful for hash tables where the two pointer list head is
|
||||
* too wasteful.
|
||||
* You lose the ability to access the tail in O(1).
|
||||
*/
|
||||
|
||||
struct hlist_head {
|
||||
struct hlist_node *first;
|
||||
};
|
||||
|
||||
struct hlist_node {
|
||||
struct hlist_node *next, **pprev;
|
||||
};
|
||||
|
||||
#define HLIST_HEAD_INIT { .first = NULL }
|
||||
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
|
||||
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
|
||||
static inline void INIT_HLIST_NODE(struct hlist_node *h)
|
||||
{
|
||||
h->next = NULL;
|
||||
h->pprev = NULL;
|
||||
}
|
||||
|
||||
static inline int hlist_unhashed(const struct hlist_node *h)
|
||||
{
|
||||
return !h->pprev;
|
||||
}
|
||||
|
||||
static inline int hlist_empty(const struct hlist_head *h)
|
||||
{
|
||||
return !h->first;
|
||||
}
|
||||
|
||||
static inline void __hlist_del(struct hlist_node *n)
|
||||
{
|
||||
struct hlist_node *next = n->next;
|
||||
struct hlist_node **pprev = n->pprev;
|
||||
*pprev = next;
|
||||
if (next)
|
||||
next->pprev = pprev;
|
||||
}
|
||||
|
||||
#define LIST_POISON1 NULL
|
||||
#define LIST_POISON2 NULL
|
||||
|
||||
static inline void hlist_del(struct hlist_node *n)
|
||||
{
|
||||
__hlist_del(n);
|
||||
n->next = LIST_POISON1;
|
||||
n->pprev = LIST_POISON2;
|
||||
}
|
||||
|
||||
static inline void hlist_del_init(struct hlist_node *n)
|
||||
{
|
||||
if (!hlist_unhashed(n)) {
|
||||
__hlist_del(n);
|
||||
INIT_HLIST_NODE(n);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
|
||||
{
|
||||
struct hlist_node *first = h->first;
|
||||
n->next = first;
|
||||
if (first)
|
||||
first->pprev = &n->next;
|
||||
h->first = n;
|
||||
n->pprev = &h->first;
|
||||
}
|
||||
|
||||
/* next must be != NULL */
|
||||
static inline void hlist_add_before(struct hlist_node *n,
|
||||
struct hlist_node *next)
|
||||
{
|
||||
n->pprev = next->pprev;
|
||||
n->next = next;
|
||||
next->pprev = &n->next;
|
||||
*(n->pprev) = n;
|
||||
}
|
||||
|
||||
static inline void hlist_add_after(struct hlist_node *n,
|
||||
struct hlist_node *next)
|
||||
{
|
||||
next->next = n->next;
|
||||
n->next = next;
|
||||
next->pprev = &n->next;
|
||||
|
||||
if(next->next)
|
||||
next->next->pprev = &next->next;
|
||||
}
|
||||
|
||||
/* after that we'll appear to be on some hlist and hlist_del will work */
|
||||
static inline void hlist_add_fake(struct hlist_node *n)
|
||||
{
|
||||
n->pprev = &n->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move a list from one list head to another. Fixup the pprev
|
||||
* reference of the first entry if it exists.
|
||||
*/
|
||||
static inline void hlist_move_list(struct hlist_head *old,
|
||||
struct hlist_head *new)
|
||||
{
|
||||
new->first = old->first;
|
||||
if (new->first)
|
||||
new->first->pprev = &new->first;
|
||||
old->first = NULL;
|
||||
}
|
||||
|
||||
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
|
||||
|
||||
#define hlist_for_each(pos, head) \
|
||||
for (pos = (head)->first; pos ; pos = pos->next)
|
||||
|
||||
#define hlist_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
|
||||
pos = n)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry - iterate over list of given type
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry(tpos, pos, head, member) \
|
||||
for (pos = (head)->first; \
|
||||
pos && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_continue(tpos, pos, member) \
|
||||
for (pos = (pos)->next; \
|
||||
pos && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_from(tpos, pos, member) \
|
||||
for (; pos && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct hlist_node to use as a loop cursor.
|
||||
* @n: another &struct hlist_node to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the hlist_node within the struct.
|
||||
*/
|
||||
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
|
||||
for (pos = (head)->first; \
|
||||
pos && ({ n = pos->next; 1; }) && \
|
||||
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
|
||||
pos = n)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
104
src/main-auth.c
104
src/main-auth.c
@@ -34,15 +34,17 @@
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <tlslib.h>
|
||||
#include <worker-auth.h>
|
||||
#include "ipc.h"
|
||||
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
#include <tun.h>
|
||||
#include <main.h>
|
||||
#include <list.h>
|
||||
#include "pam.h"
|
||||
|
||||
static int send_auth_reply(cmd_auth_reply_t r, struct proc_list_st* proc, struct lease_st* lease)
|
||||
static int send_auth_reply(main_server_st* s, struct proc_list_st* proc,
|
||||
cmd_auth_reply_t r, struct lease_st* lease)
|
||||
{
|
||||
struct iovec iov[6];
|
||||
uint8_t cmd[2];
|
||||
@@ -96,14 +98,13 @@ static int send_auth_reply(cmd_auth_reply_t r, struct proc_list_st* proc, struct
|
||||
return(sendmsg(proc->fd, &hdr, 0));
|
||||
}
|
||||
|
||||
static int handle_auth_cookie_req(const struct cfg_st *config, struct tun_st *tun,
|
||||
const struct cmd_auth_cookie_req_st * req, struct lease_st **lease,
|
||||
struct proc_list_st* proc)
|
||||
static int handle_auth_cookie_req(main_server_st* s, struct proc_list_st* proc,
|
||||
const struct cmd_auth_cookie_req_st * req, struct lease_st **lease)
|
||||
{
|
||||
int ret;
|
||||
struct stored_cookie_st sc;
|
||||
|
||||
ret = retrieve_cookie(config, req->cookie, sizeof(req->cookie), &sc);
|
||||
ret = retrieve_cookie(s->config, req->cookie, sizeof(req->cookie), &sc);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -114,7 +115,7 @@ struct stored_cookie_st sc;
|
||||
memcpy(proc->username, sc.username, sizeof(proc->username));
|
||||
memcpy(proc->session_id, sc.session_id, sizeof(proc->session_id));
|
||||
|
||||
ret = open_tun(config, tun, lease);
|
||||
ret = open_tun(s->config, s->tun, lease);
|
||||
if (ret < 0)
|
||||
ret = -1; /* sorry */
|
||||
|
||||
@@ -122,7 +123,7 @@ struct stored_cookie_st sc;
|
||||
}
|
||||
|
||||
static
|
||||
int generate_and_store_vals(const struct cfg_st* config, struct proc_list_st* proc)
|
||||
int generate_and_store_vals(main_server_st *s, struct proc_list_st* proc)
|
||||
{
|
||||
int ret;
|
||||
struct stored_cookie_st sc;
|
||||
@@ -135,51 +136,50 @@ struct stored_cookie_st sc;
|
||||
return -2;
|
||||
|
||||
memset(&sc, 0, sizeof(sc));
|
||||
sc.expiration = time(0) + config->cookie_validity;
|
||||
sc.expiration = time(0) + s->config->cookie_validity;
|
||||
|
||||
memcpy(sc.username, proc->username, sizeof(sc.username));
|
||||
memcpy(sc.session_id, proc->session_id, sizeof(sc.session_id));
|
||||
|
||||
ret = store_cookie(config, proc->cookie, sizeof(proc->cookie), &sc);
|
||||
ret = store_cookie(s->config, proc->cookie, sizeof(proc->cookie), &sc);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_auth_req(const struct cfg_st *config, struct tun_st *tun,
|
||||
const struct cmd_auth_req_st * req, struct lease_st **lease,
|
||||
char username[MAX_USERNAME_SIZE])
|
||||
static int handle_auth_req(main_server_st *s, struct proc_list_st* proc,
|
||||
const struct cmd_auth_req_st * req, struct lease_st **lease)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned username_set = 0;
|
||||
|
||||
if (config->auth_types & AUTH_TYPE_PAM) {
|
||||
if (req->user_pass_present != 0 && s->config->auth_types & AUTH_TYPE_PAM) {
|
||||
ret = pam_auth_user(req->user, req->pass);
|
||||
if (ret != 0)
|
||||
ret = -1;
|
||||
|
||||
memcpy(username, req->user, MAX_USERNAME_SIZE);
|
||||
memcpy(proc->username, req->user, MAX_USERNAME_SIZE);
|
||||
username_set = 1;
|
||||
}
|
||||
|
||||
if (config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
if (s->config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
if (req->tls_auth_ok != 0) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (username_set == 0)
|
||||
memcpy(username, req->cert_user, MAX_USERNAME_SIZE);
|
||||
memcpy(proc->username, req->cert_user, MAX_USERNAME_SIZE);
|
||||
else {
|
||||
if (strcmp(username, req->cert_user) != 0) {
|
||||
syslog(LOG_INFO, "User '%s' presented a certificate from user '%s'", username, req->cert_user);
|
||||
if (strcmp(proc->username, req->cert_user) != 0) {
|
||||
syslog(LOG_INFO, "User '%s' presented a certificate from user '%s'", proc->username, req->cert_user);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) { /* open tun */
|
||||
ret = open_tun(config, tun, lease);
|
||||
ret = open_tun(s->config, s->tun, lease);
|
||||
if (ret < 0)
|
||||
ret = -1; /* sorry */
|
||||
}
|
||||
@@ -187,17 +187,19 @@ unsigned username_set = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
struct proc_list_st* proc)
|
||||
int handle_commands(main_server_st *s, struct proc_list_st* proc)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
char buf[128];
|
||||
int e;
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
struct lease_st *lease;
|
||||
union {
|
||||
struct cmd_auth_req_st auth;
|
||||
struct cmd_auth_cookie_req_st cauth;
|
||||
struct cmd_resume_store_req_st sresume;
|
||||
struct cmd_resume_fetch_req_st fresume;
|
||||
} cmd_data;
|
||||
int ret, cmd_data_len;
|
||||
const char* peer_ip;
|
||||
@@ -218,7 +220,8 @@ int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
|
||||
ret = recvmsg( proc->fd, &hdr, 0);
|
||||
if (ret == -1) {
|
||||
syslog(LOG_ERR, "Cannot obtain data from command socket (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
e = errno;
|
||||
syslog(LOG_ERR, "Cannot obtain data from command socket (pid: %d, peer: %s): %s", proc->pid, peer_ip, strerror(e));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -229,6 +232,51 @@ int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
cmd_data_len = ret - 1;
|
||||
|
||||
switch(cmd) {
|
||||
case RESUME_STORE_REQ:
|
||||
if (cmd_data_len != sizeof(cmd_data.sresume)) {
|
||||
syslog(LOG_ERR, "Error in received message length (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
ret = handle_resume_store_req(s, proc, &cmd_data.sresume);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_DEBUG, "Could not store resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RESUME_DELETE_REQ:
|
||||
if (cmd_data_len != sizeof(cmd_data.fresume)) {
|
||||
syslog(LOG_ERR, "Error in received message length (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
ret = handle_resume_delete_req(s, proc, &cmd_data.fresume);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_DEBUG, "Could not delete resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
}
|
||||
|
||||
break;
|
||||
case RESUME_FETCH_REQ: {
|
||||
struct cmd_resume_fetch_reply_st reply;
|
||||
|
||||
if (cmd_data_len != sizeof(cmd_data.fresume)) {
|
||||
syslog(LOG_ERR, "Error in received message length (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
ret = handle_resume_fetch_req(s, proc, &cmd_data.fresume, &reply);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_DEBUG, "Could not fetch resumption data (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
ret = send_resume_fetch_reply(s, proc, REP_RESUME_FAILED, NULL);
|
||||
} else
|
||||
ret = send_resume_fetch_reply(s, proc, REP_RESUME_OK, &reply);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AUTH_REQ:
|
||||
case AUTH_COOKIE_REQ:
|
||||
|
||||
@@ -238,26 +286,26 @@ int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = handle_auth_req(config, tun, &cmd_data.auth, &lease, proc->username);
|
||||
ret = handle_auth_req(s, proc, &cmd_data.auth, &lease);
|
||||
} else {
|
||||
if (cmd_data_len != sizeof(cmd_data.cauth)) {
|
||||
syslog(LOG_ERR, "Error in received message length (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = handle_auth_cookie_req(config, tun, &cmd_data.cauth, &lease, proc);
|
||||
ret = handle_auth_cookie_req(s, proc, &cmd_data.cauth, &lease);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (cmd == AUTH_REQ) {
|
||||
/* generate and store cookie */
|
||||
ret = generate_and_store_vals(config, proc);
|
||||
ret = generate_and_store_vals(s, proc);
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "User '%s' authenticated", proc->username);
|
||||
ret = send_auth_reply(REP_AUTH_OK, proc, lease);
|
||||
ret = send_auth_reply(s, proc, REP_AUTH_OK, lease);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
@@ -270,7 +318,7 @@ int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
lease->fd = -1;
|
||||
} else {
|
||||
syslog(LOG_INFO, "Failed authentication attempt for user '%s'", proc->username);
|
||||
ret = send_auth_reply( REP_AUTH_FAILED, proc, NULL);
|
||||
ret = send_auth_reply( s, proc, REP_AUTH_FAILED, NULL);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
|
||||
165
src/main-resume.c
Normal file
165
src/main-resume.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <tlslib.h>
|
||||
#include "ipc.h"
|
||||
#include <hash.h>
|
||||
#include <hash-pjw-bare.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
int send_resume_fetch_reply(main_server_st* s, struct proc_list_st * proc,
|
||||
cmd_resume_reply_t r, struct cmd_resume_fetch_reply_st * reply)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
uint8_t cmd = RESUME_FETCH_REP;
|
||||
struct msghdr hdr;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
iov[1].iov_base = reply;
|
||||
iov[1].iov_len = sizeof(*reply);
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
iov[2].iov_base = reply;
|
||||
iov[2].iov_len = sizeof(*reply);
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
hdr.msg_iov = iov;
|
||||
|
||||
return(sendmsg(proc->fd, &hdr, 0));
|
||||
}
|
||||
|
||||
int handle_resume_delete_req(main_server_st* s, struct proc_list_st * proc,
|
||||
const struct cmd_resume_fetch_req_st * req)
|
||||
{
|
||||
size_t key;
|
||||
tls_cache_st* cache;
|
||||
struct hlist_node *pos, *tmp;
|
||||
key = hash_pjw_bare(req->session_id, req->session_id_size);
|
||||
|
||||
hash_for_each_possible_safe(s->tls_db->entry, cache, pos, tmp, list, key) {
|
||||
if (req->session_id_size == cache->session_id_size &&
|
||||
memcmp (req->session_id, cache->session_id, req->session_id_size) == 0) {
|
||||
|
||||
cache->session_data_size = 0;
|
||||
cache->session_id_size = 0;
|
||||
|
||||
hash_del(&cache->list);
|
||||
free(cache);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int ip_cmp(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2, size_t n)
|
||||
{
|
||||
if (((struct sockaddr*)s1)->sa_family == AF_INET) {
|
||||
return memcmp(SA_IN_P(s1), SA_IN_P(s2), sizeof(struct in_addr));
|
||||
} else { /* inet6 */
|
||||
return memcmp(SA_IN6_P(s1), SA_IN6_P(s2), sizeof(struct in6_addr));
|
||||
}
|
||||
}
|
||||
|
||||
int handle_resume_fetch_req(main_server_st* s, struct proc_list_st * proc,
|
||||
const struct cmd_resume_fetch_req_st * req,
|
||||
struct cmd_resume_fetch_reply_st * rep)
|
||||
{
|
||||
size_t key;
|
||||
tls_cache_st* cache;
|
||||
struct hlist_node *pos;
|
||||
|
||||
key = hash_pjw_bare(req->session_id, req->session_id_size);
|
||||
rep->reply = REP_RESUME_FAILED;
|
||||
|
||||
hash_for_each_possible(s->tls_db->entry, cache, pos, list, key) {
|
||||
if (req->session_id_size == cache->session_id_size &&
|
||||
memcmp (req->session_id, cache->session_id, req->session_id_size) == 0) {
|
||||
|
||||
if (proc->remote_addr_len == cache->remote_addr_len &&
|
||||
ip_cmp(&proc->remote_addr, &cache->remote_addr, proc->remote_addr_len) == 0) {
|
||||
|
||||
rep->reply = REP_RESUME_OK;
|
||||
|
||||
memcpy(rep->session_data, cache->session_data, cache->session_data_size);
|
||||
rep->session_data_size = cache->session_data_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int handle_resume_store_req(main_server_st* s, struct proc_list_st * proc,
|
||||
const struct cmd_resume_store_req_st * req)
|
||||
{
|
||||
tls_cache_st* cache;
|
||||
size_t key;
|
||||
|
||||
if (req->session_id_size > GNUTLS_MAX_SESSION_ID)
|
||||
return -1;
|
||||
if (req->session_data_size > MAX_SESSION_DATA_SIZE)
|
||||
return -1;
|
||||
|
||||
key = hash_pjw_bare(req->session_id, req->session_id_size);
|
||||
|
||||
cache = malloc(sizeof(*cache));
|
||||
if (cache == NULL)
|
||||
return -1;
|
||||
|
||||
cache->session_id_size = req->session_id_size;
|
||||
cache->session_data_size = req->session_data_size;
|
||||
cache->remote_addr_len = proc->remote_addr_len;
|
||||
|
||||
memcpy(cache->session_id, req->session_id, req->session_id_size);
|
||||
memcpy(cache->session_data, req->session_data, req->session_data_size);
|
||||
memcpy(&cache->remote_addr, &proc->remote_addr, proc->remote_addr_len);
|
||||
|
||||
hash_add(s->tls_db->entry, &cache->list, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
13
src/main.c
13
src/main.c
@@ -34,8 +34,9 @@
|
||||
|
||||
#include <gnutls/x509.h>
|
||||
#include <tlslib.h>
|
||||
#include <worker-auth.h>
|
||||
#include "ipc.h"
|
||||
|
||||
#include <main.h>
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
#include <tun.h>
|
||||
@@ -352,9 +353,12 @@ int main(int argc, char** argv)
|
||||
struct worker_st ws;
|
||||
struct cfg_st config;
|
||||
unsigned active_clients = 0;
|
||||
main_server_st s;
|
||||
tls_cache_db_st* tls_db;
|
||||
|
||||
INIT_LIST_HEAD(&clist.list);
|
||||
tun_st_init(&tun);
|
||||
tls_cache_init(&config, &tls_db);
|
||||
|
||||
signal(SIGINT, handle_term);
|
||||
signal(SIGTERM, handle_term);
|
||||
@@ -374,6 +378,11 @@ int main(int argc, char** argv)
|
||||
fprintf(stderr, "Error in arguments\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
s.config = &config;
|
||||
s.tun = &tun;
|
||||
s.tls_db = tls_db;
|
||||
|
||||
/* Listen to network ports */
|
||||
ret = listen_ports(&config, &llist, config.name, config.port, SOCK_STREAM);
|
||||
if (ret < 0) {
|
||||
@@ -562,7 +571,7 @@ fork_failed:
|
||||
ctmp = list_entry(pos, struct proc_list_st, list);
|
||||
|
||||
if (FD_ISSET(ctmp->fd, &rd)) {
|
||||
ret = handle_commands(&config, &tun, ctmp);
|
||||
ret = handle_commands(&s, ctmp);
|
||||
if (ret < 0) {
|
||||
if (ret == -2) {
|
||||
/* received a bad command from worker */
|
||||
|
||||
49
src/main.h
Normal file
49
src/main.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef MAIN_H
|
||||
# define MAIN_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <tlslib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
|
||||
int cmd_parser (int argc, char **argv, struct cfg_st* config);
|
||||
|
||||
struct proc_list_st {
|
||||
struct list_head list;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
struct sockaddr_storage remote_addr; /* peer address */
|
||||
socklen_t remote_addr_len;
|
||||
char username[MAX_USERNAME_SIZE]; /* the owner */
|
||||
uint8_t cookie[COOKIE_SIZE]; /* the cookie associate with the session */
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
|
||||
/* the tun lease this process has */
|
||||
struct lease_st* lease;
|
||||
};
|
||||
|
||||
typedef struct main_server_st {
|
||||
struct cfg_st *config;
|
||||
struct tun_st *tun;
|
||||
tls_cache_db_st *tls_db;
|
||||
} main_server_st;
|
||||
|
||||
int handle_commands(main_server_st *s, struct proc_list_st* cur);
|
||||
|
||||
|
||||
int send_resume_fetch_reply(main_server_st* s, struct proc_list_st* proc,
|
||||
cmd_resume_reply_t r, struct cmd_resume_fetch_reply_st * reply);
|
||||
|
||||
int handle_resume_delete_req(main_server_st* s, struct proc_list_st* proc,
|
||||
const struct cmd_resume_fetch_req_st * req);
|
||||
|
||||
int handle_resume_fetch_req(main_server_st* s, struct proc_list_st* proc,
|
||||
const struct cmd_resume_fetch_req_st * req,
|
||||
struct cmd_resume_fetch_reply_st * rep);
|
||||
|
||||
int handle_resume_store_req(main_server_st* s, struct proc_list_st *proc,
|
||||
const struct cmd_resume_store_req_st * req);
|
||||
|
||||
#endif
|
||||
13
src/tlslib.c
13
src/tlslib.c
@@ -115,3 +115,16 @@ void tls_fatal_close(gnutls_session_t session,
|
||||
gnutls_alert_send(session, GNUTLS_AL_FATAL, a);
|
||||
gnutls_deinit(session);
|
||||
}
|
||||
|
||||
void tls_cache_init(struct cfg_st* config, tls_cache_db_st** _db)
|
||||
{
|
||||
tls_cache_db_st * db;
|
||||
|
||||
db = malloc(sizeof(*db));
|
||||
if (db == NULL)
|
||||
exit(1);
|
||||
|
||||
hash_init(db->entry);
|
||||
|
||||
*_db = db;
|
||||
}
|
||||
|
||||
29
src/tlslib.h
29
src/tlslib.h
@@ -2,6 +2,10 @@
|
||||
#define TLS_H
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <vpn.h>
|
||||
#include <hashtable.h>
|
||||
|
||||
#define MAX_SESSION_DATA_SIZE (4*1024)
|
||||
|
||||
#define tls_puts(s, str) tls_send(s, str, sizeof(str)-1)
|
||||
|
||||
@@ -28,4 +32,29 @@ void tls_close(gnutls_session_t session);
|
||||
void tls_fatal_close(gnutls_session_t session,
|
||||
gnutls_alert_description_t a);
|
||||
|
||||
#define MAX_SESSION_DATA_SIZE (4*1024)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* does not allow resumption from different address
|
||||
* than the original */
|
||||
struct sockaddr_storage remote_addr;
|
||||
socklen_t remote_addr_len;
|
||||
|
||||
char session_id[GNUTLS_MAX_SESSION_ID];
|
||||
unsigned int session_id_size;
|
||||
|
||||
char session_data[MAX_SESSION_DATA_SIZE];
|
||||
unsigned int session_data_size;
|
||||
|
||||
struct hlist_node list;
|
||||
} tls_cache_st;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DECLARE_HASHTABLE(entry, 7);
|
||||
} tls_cache_db_st;
|
||||
|
||||
void tls_cache_init(struct cfg_st* config, tls_cache_db_st** db);
|
||||
|
||||
#endif
|
||||
|
||||
19
src/vpn.h
19
src/vpn.h
@@ -143,25 +143,6 @@ const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
||||
void __attribute__ ((format(printf, 3, 4)))
|
||||
oclog(const worker_st * server, int priority, const char *fmt, ...);
|
||||
|
||||
int cmd_parser (int argc, char **argv, struct cfg_st* config);
|
||||
|
||||
struct proc_list_st {
|
||||
struct list_head list;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
struct sockaddr_storage remote_addr; /* peer address */
|
||||
socklen_t remote_addr_len;
|
||||
char username[MAX_USERNAME_SIZE]; /* the owner */
|
||||
uint8_t cookie[COOKIE_SIZE]; /* the cookie associate with the session */
|
||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
||||
|
||||
/* the tun lease this process has */
|
||||
struct lease_st* lease;
|
||||
};
|
||||
|
||||
int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
struct proc_list_st* proc);
|
||||
|
||||
/* Helper casts */
|
||||
#define SA_IN_P(p) (&((struct sockaddr_in *)(p))->sin_addr)
|
||||
#define SA_IN_U8_P(p) ((uint8_t*)(&((struct sockaddr_in *)(p))->sin_addr))
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <worker-auth.h>
|
||||
#include "ipc.h"
|
||||
#include <worker.h>
|
||||
#include <cookies.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
|
||||
236
src/worker-resume.c
Normal file
236
src/worker-resume.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 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 <gnutls/x509.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 <vpn.h>
|
||||
#include "ipc.h"
|
||||
#include <cookies.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
|
||||
static int send_resume_fetch_req(worker_st * ws, const struct cmd_resume_fetch_req_st* r,
|
||||
int delete)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
if (delete != 0)
|
||||
cmd = RESUME_DELETE_REQ;
|
||||
else
|
||||
cmd = RESUME_FETCH_REQ;
|
||||
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = (void*)r;
|
||||
iov[1].iov_len = sizeof(*r);
|
||||
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
return(sendmsg(ws->cmd_fd, &hdr, 0));
|
||||
}
|
||||
|
||||
static int send_resume_store_req(worker_st * ws, const struct cmd_resume_store_req_st* r)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
cmd = RESUME_STORE_REQ;
|
||||
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = (void*)r;
|
||||
iov[1].iov_len = sizeof(*r);
|
||||
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
return(sendmsg(ws->cmd_fd, &hdr, 0));
|
||||
}
|
||||
|
||||
static int recv_resume_fetch_reply(worker_st *ws, struct cmd_resume_fetch_reply_st* resp)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd = 0;
|
||||
struct msghdr hdr;
|
||||
int ret;
|
||||
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = resp;
|
||||
iov[1].iov_len = sizeof(*resp);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
ret = recvmsg( ws->cmd_fd, &hdr, 0);
|
||||
if (ret < sizeof(*resp)+1) {
|
||||
oclog(ws, LOG_ERR, "Received incorrect data (%d, expected %d) from main", ret, (int)sizeof(*resp)+1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cmd != RESUME_FETCH_REP) {
|
||||
oclog(ws, LOG_ERR, "Received unexpected response (%d, expected %d) from main", (int)cmd, (int)RESUME_FETCH_REP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(resp->reply) {
|
||||
case REP_RESUME_OK:
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* sends an authentication request to main thread and waits for
|
||||
* a reply.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static gnutls_datum_t resume_db_fetch(void *dbf, gnutls_datum_t key)
|
||||
{
|
||||
worker_st *ws = dbf;
|
||||
struct cmd_resume_fetch_req_st areq;
|
||||
struct cmd_resume_fetch_reply_st *arep;
|
||||
gnutls_datum_t r = { NULL, 0 };
|
||||
int ret;
|
||||
|
||||
if (key.size > GNUTLS_MAX_SESSION_ID) {
|
||||
oclog(ws, LOG_DEBUG, "Session ID size exceeds the maximum %u", key.size);
|
||||
return r;
|
||||
}
|
||||
|
||||
areq.session_id_size = key.size;
|
||||
memcpy(areq.session_id, key.data, key.size);
|
||||
|
||||
oclog(ws, LOG_DEBUG, "Sending resumption request");
|
||||
|
||||
ret = send_resume_fetch_req(ws, &areq, 0);
|
||||
if (ret < 0)
|
||||
return r;
|
||||
|
||||
arep = malloc(sizeof(*arep));
|
||||
if (arep == NULL)
|
||||
return r;
|
||||
|
||||
ret = recv_resume_fetch_reply(ws, arep);
|
||||
if (ret < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
r.data = gnutls_malloc(arep->session_data_size);
|
||||
if (r.data == NULL)
|
||||
goto cleanup;
|
||||
|
||||
r.size = arep->session_data_size;
|
||||
memcpy(r.data, arep->session_data, r.size);
|
||||
|
||||
cleanup:
|
||||
free(arep);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
resume_db_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data)
|
||||
{
|
||||
worker_st *ws = dbf;
|
||||
struct cmd_resume_store_req_st areq;
|
||||
int ret;
|
||||
|
||||
if (data.size > MAX_SESSION_DATA_SIZE) {
|
||||
oclog(ws, LOG_DEBUG, "Session data size exceeds the maximum %u", data.size);
|
||||
return GNUTLS_E_DB_ERROR;
|
||||
}
|
||||
|
||||
if (key.size > GNUTLS_MAX_SESSION_ID) {
|
||||
oclog(ws, LOG_DEBUG, "Session ID size exceeds the maximum %u", key.size);
|
||||
return GNUTLS_E_DB_ERROR;
|
||||
}
|
||||
|
||||
areq.session_id_size = key.size;
|
||||
areq.session_data_size = data.size;
|
||||
|
||||
memcpy(areq.session_id, key.data, key.size);
|
||||
memcpy(areq.session_data, data.data, data.size);
|
||||
|
||||
ret = send_resume_store_req(ws, &areq);
|
||||
if (ret < 0) {
|
||||
return GNUTLS_E_DB_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sends an authentication request to main thread and waits for
|
||||
* a reply.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static int resume_db_delete(void *dbf, gnutls_datum_t key)
|
||||
{
|
||||
worker_st *ws = dbf;
|
||||
struct cmd_resume_fetch_req_st areq;
|
||||
int ret;
|
||||
|
||||
if (key.size > GNUTLS_MAX_SESSION_ID) {
|
||||
oclog(ws, LOG_DEBUG, "Session ID size exceeds the maximum %u", key.size);
|
||||
return GNUTLS_E_DB_ERROR;
|
||||
}
|
||||
|
||||
areq.session_id_size = key.size;
|
||||
memcpy(areq.session_id, key.data, key.size);
|
||||
|
||||
oclog(ws, LOG_DEBUG, "Sending resumption request");
|
||||
|
||||
ret = send_resume_fetch_req(ws, &areq, 1);
|
||||
if (ret < 0)
|
||||
return GNUTLS_E_DB_ERROR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_resume_db_funcs(gnutls_session_t session)
|
||||
{
|
||||
gnutls_db_set_retrieve_function (session, resume_db_fetch);
|
||||
gnutls_db_set_remove_function (session, resume_db_delete);
|
||||
gnutls_db_set_store_function (session, resume_db_store);
|
||||
}
|
||||
@@ -42,8 +42,9 @@
|
||||
#include <time.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <worker-auth.h>
|
||||
#include "ipc.h"
|
||||
#include <cookies.h>
|
||||
#include <worker.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
#include <http-parser/http_parser.h>
|
||||
@@ -283,7 +284,6 @@ gnutls_datum_t sid = { ws->session_id, sizeof(ws->session_id) };
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
ret =
|
||||
gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
|
||||
ws->creds->xcred);
|
||||
@@ -342,7 +342,9 @@ void vpn_server(struct worker_st* ws)
|
||||
|
||||
gnutls_certificate_server_set_request(session, ws->config->cert_req);
|
||||
gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) (long)ws->conn_fd);
|
||||
set_resume_db_funcs(session);
|
||||
gnutls_session_set_ptr(session, ws);
|
||||
gnutls_db_set_ptr (session, ws);
|
||||
|
||||
do {
|
||||
ret = gnutls_handshake(session);
|
||||
|
||||
22
src/worker.h
Normal file
22
src/worker.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef WORKER_H
|
||||
#define WORKER_H
|
||||
|
||||
#include <config.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
int auth_cookie(worker_st *ws, void* cookie, size_t cookie_size);
|
||||
|
||||
int get_auth_handler(worker_st *server);
|
||||
int post_old_auth_handler(worker_st *server);
|
||||
int post_new_auth_handler(worker_st *server);
|
||||
|
||||
void set_resume_db_funcs(gnutls_session_t);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user