summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSam Hartman <hartmans@painless-security.com>2014-02-11 21:17:19 -0500
committerSam Hartman <hartmans@painless-security.com>2014-02-11 21:17:19 -0500
commitd78a0c6725823419bf54d4f9d45ddd402caaa7a0 (patch)
tree4e8a86ad5d9a4658e1350ecb2aff19a5786452ed /lib
parent7b065194a99aa15b10ff1e69547eb1b44d5399a8 (diff)
parentf18e7f2ab31160c00a7b363542fc4cea57d0fa14 (diff)
Merge tag 'libradsec-0.0.5' into debian
libradsec-0.0.5 Conflicts: lib/conf.c lib/radius/Makefile.am
Diffstat (limited to 'lib')
-rw-r--r--lib/CHANGES17
-rw-r--r--lib/HACKING6
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/README5
-rw-r--r--lib/conf.c2
-rw-r--r--lib/configure.ac30
-rw-r--r--lib/conn.c25
-rw-r--r--lib/event.c17
-rw-r--r--lib/examples/Makefile.am2
-rw-r--r--lib/examples/client-blocking.c3
-rw-r--r--lib/include/radsec/radsec.h7
-rw-r--r--lib/radius/Makefile.am3
-rw-r--r--lib/radsec.c10
-rw-r--r--lib/radsecproxy/Makefile.am2
-rw-r--r--lib/radsecproxy/tlscommon.c90
-rw-r--r--lib/radsecproxy/tlscommon.h3
-rw-r--r--lib/request.c12
-rw-r--r--lib/tests/Makefile.am2
-rw-r--r--lib/tls.c136
-rw-r--r--lib/tls.h12
-rw-r--r--lib/udp.c4
21 files changed, 246 insertions, 146 deletions
diff --git a/lib/CHANGES b/lib/CHANGES
new file mode 100644
index 0000000..928dfbe
--- /dev/null
+++ b/lib/CHANGES
@@ -0,0 +1,17 @@
+Changes between 0.0.4 and 0.0.5
+
+ - When POSIX thread support is detected at configure and build time
+ libradsec will be more safe to use by programs that call it from
+ more than one thread simultaneously.
+
+ - The initialisation of the OpenSSL PRNG has been improved.
+
+User visible changes between 0.0.1 and 0.0.4
+
+ - TLS support is now enabled by default. Use --disable-tls to
+ disable it.
+
+ - Support for TLS-PSK has been added (--enable-tls-psk).
+
+ - The RADIUS dictionaries are now compiled into the library and are
+ no longer read from disk.
diff --git a/lib/HACKING b/lib/HACKING
index a92f0f9..8278238 100644
--- a/lib/HACKING
+++ b/lib/HACKING
@@ -1,10 +1,10 @@
HACKING file for libradsec (in Emacs -*- org -*- mode).
-Status as of libradsec-0.0.4.dev (2013-05-06).
+Status as of libradsec-0.0.5 (2014-02-03).
* Build instructions
sh autogen.sh
-./configure #--enable-tls
+./configure
make
examples/client -r examples/client.conf blocking-tls; echo $?
@@ -37,7 +37,7 @@ examples/client -r examples/client.conf blocking-tls; echo $?
- Application chooses allocation regime.
-Note that as of 0.0.2.dev libradsec suffers from way too much focus on
+Note that as of 0.0.4 libradsec suffers from way too much focus on
the behaviour of a blocking client and is totally useless as a server.
Not only does it lack most of the functions needed for writing a
server but it also contains at least one architectural mishap which
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d5b2bff..251c5b9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -19,7 +19,7 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = radius radsecproxy include . examples
DIST_SUBDIRS = $(SUBDIRS) tests
-INCLUDES = -I$(srcdir)/include
+AM_CPPFLAGS = -I$(srcdir)/include
AM_CFLAGS = -Wall -Werror -g
lib_LTLIBRARIES = libradsec.la
@@ -62,7 +62,7 @@ libradsec_la_SOURCES += \
udp.h \
util.h
-EXTRA_DIST = HACKING LICENSE libradsec.spec radsec.sym
+EXTRA_DIST = CHANGES HACKING LICENSE libradsec.spec radsec.sym
EXTRA_libradsec_la_DEPENDENCIES = radsec.sym
AM_DISTCHECK_CONFIGURE_FLAGS = --enable-tls --enable-tls-psk
diff --git a/lib/README b/lib/README
index 111c570..4c0d277 100644
--- a/lib/README
+++ b/lib/README
@@ -14,7 +14,7 @@ LICENSE file.
Libradsec depends on
- libconfuse
- libevent2
-- openssl (if configured with --enable-tls)
+- openssl (unless configured with --disable-tls)
To compile the library and the examples, do something like
@@ -26,8 +26,7 @@ There are a couple of options that can be used when configuring. See
./configure --help
-for the full list. Worth mentioning here is --enable-tls and
---enable-tls-psk.
+for the full list. Worth mentioning here is --enable-tls-psk.
If the preprocessor has a hard time finding some of the header files
are, try setting environment variable CPPFLAGS at configure
diff --git a/lib/conf.c b/lib/conf.c
index 9dfc4c6..4e0df31 100644
--- a/lib/conf.c
+++ b/lib/conf.c
@@ -31,7 +31,7 @@
pskhexstr = STRING # Transport pre-shared key, ASCII hex form.
pskid = STRING
pskex = "PSK"|"DHE_PSK"|"RSA_PSK"
- disable_hostname_check = yes|no
+ disable_hostname_check = "yes"|"no"
}
# client specific realm config options
diff --git a/lib/configure.ac b/lib/configure.ac
index ab775e4..d99bab4 100644
--- a/lib/configure.ac
+++ b/lib/configure.ac
@@ -1,7 +1,7 @@
# -*- Autoconf -*- script for libradsec.
AC_PREREQ([2.63])
-AC_INIT([libradsec], [0.0.4.dev], [linus+libradsec@nordu.net])
+AC_INIT([libradsec], [0.0.5], [linus+libradsec@nordu.net])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([radsec.c])
AC_CONFIG_AUX_DIR([build-aux])
@@ -17,19 +17,25 @@ AC_CHECK_LIB([confuse], [cfg_init],,
AC_MSG_ERROR([required library libconfuse not found]))
AC_CHECK_LIB([event_core], [event_get_version],,
AC_MSG_ERROR([required library libevent_core not found]))
+AH_TEMPLATE([HAVE_PTHREADS], [POSIX threads are available on this system])
+AC_SEARCH_LIBS([pthread_create], [pthread], AC_DEFINE([HAVE_PTHREADS]))
# Enable-knobs.
-## Enable TLS (RadSec).
+## Enable TLS (RadSec), default on.
+want_tls=yes
AH_TEMPLATE([RS_ENABLE_TLS], [TLS (RadSec) enabled])
-AH_TEMPLATE([RADPROT_TLS], []) dnl Legacy.
-AC_ARG_ENABLE([tls], AS_HELP_STRING([--enable-tls], [enable TLS (RadSec)]),
- [AC_CHECK_LIB([event_openssl], [bufferevent_openssl_socket_new],,
- AC_MSG_ERROR([required library event_openssl not found]))
- AC_DEFINE([RS_ENABLE_TLS])
- AC_DEFINE([RADPROT_TLS])]) dnl Legacy.
-AM_CONDITIONAL([RS_ENABLE_TLS], [test "${enable_tls+set}" = set])
-### Define WITHOUT_OPENSSL for radius/client.h.
-if test -z "$enable_tls"; then
+AH_TEMPLATE([RADPROT_TLS], [])
+AC_ARG_ENABLE([tls],
+ AS_HELP_STRING([--disable-tls], [disable TLS (RadSec)]),
+ [want_tls=$enableval])
+AM_CONDITIONAL([RS_ENABLE_TLS], [test $want_tls = yes])
+if test $want_tls = yes; then
+ AC_CHECK_LIB([event_openssl], [bufferevent_openssl_socket_new],,
+ AC_MSG_ERROR([required library event_openssl not found]))
+ AC_DEFINE([RS_ENABLE_TLS])
+ AC_DEFINE([RADPROT_TLS])
+else
+ # Define WITHOUT_OPENSSL for radius/client.h.
CPPFLAGS="$CPPFLAGS -DWITHOUT_OPENSSL"
fi
## Enable TLS-PSK (preshared keys).
@@ -43,7 +49,7 @@ AM_CONDITIONAL([RS_ENABLE_TLS_PSK], [test "${enable_tls_psk+set}" = set])
# Checks for header files.
AC_CHECK_HEADERS(
[sys/time.h time.h netdb.h netinet/in.h stdint.h stdlib.h strings.h string.h \
- sys/socket.h unistd.h syslog.h sys/select.h fcntl.h arpa/inet.h])
+ sys/socket.h unistd.h syslog.h sys/select.h fcntl.h arpa/inet.h pthread.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
diff --git a/lib/conn.c b/lib/conn.c
index 499c330..970a071 100644
--- a/lib/conn.c
+++ b/lib/conn.c
@@ -307,20 +307,23 @@ rs_conn_receive_packet (struct rs_connection *conn,
evutil_gai_strerror (err));
rs_debug (("%s: event loop done\n", __func__));
- if ((pkt->flags & RS_PACKET_RECEIVED) == 0
- || (req_msg
- && packet_verify_response (pkt->conn, pkt, req_msg) != RSE_OK))
+ if ((pkt->flags & RS_PACKET_RECEIVED) != 0)
{
- if (rs_err_conn_peek_code (pkt->conn) == RSE_OK)
- /* No packet and no error on the stack _should_ mean that the
- server hung up on us. */
- rs_err_conn_push (pkt->conn, RSE_DISCO, "no response");
- return rs_err_conn_peek_code (conn);
+ /* If the caller passed a request, check the response. */
+ if (req_msg)
+ err = packet_verify_response (pkt->conn, pkt, req_msg);
+
+ /* If the response was OK and the caller wants it, hand it
+ over, else free it. */
+ if (err == RSE_OK && pkt_out)
+ *pkt_out = pkt;
+ else
+ rs_packet_destroy (pkt);
}
+ else
+ err = rs_err_conn_peek_code (pkt->conn);
- if (pkt_out)
- *pkt_out = pkt;
- return RSE_OK;
+ return err;
}
void
diff --git a/lib/event.c b/lib/event.c
index c625850..a532da9 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -92,6 +92,21 @@ event_retransmit_timeout_cb (int fd, short event, void *data)
rs_debug (("%s: retransmission timeout on %p (fd %d) sending to %p\n",
__func__, conn, conn->fd, conn->active_peer));
rs_err_conn_push_fl (conn, RSE_TIMEOUT_IO, __FILE__, __LINE__, NULL);
+
+ /* Disable/delete read and write events. Timing out on reading
+ might f.ex. trigger resending of a message. It'd be
+ surprising to end up reading without having enabled/created a
+ read event in that case. */
+ if (conn->bev) /* TCP. */
+ bufferevent_disable (conn->bev, EV_WRITE|EV_READ);
+ else /* UDP. */
+ {
+ if (conn->wev)
+ event_del (conn->wev);
+ if (conn->rev)
+ event_del (conn->rev);
+ }
+
event_loopbreak (conn);
}
}
@@ -143,7 +158,7 @@ event_init_bufferevent (struct rs_connection *conn, struct rs_peer *peer)
#if defined (RS_ENABLE_TLS)
else if (conn->realm->type == RS_CONN_TYPE_TLS)
{
- if (rs_tls_init (conn))
+ if (tls_init_conn (conn))
return -1;
/* Would be convenient to pass BEV_OPT_CLOSE_ON_FREE but things
seem to break when be_openssl_ctrl() (in libevent) calls
diff --git a/lib/examples/Makefile.am b/lib/examples/Makefile.am
index f300627..fa1c835 100644
--- a/lib/examples/Makefile.am
+++ b/lib/examples/Makefile.am
@@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS = foreign
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)
AM_CFLAGS = -Wall -Werror -g
noinst_PROGRAMS = client
diff --git a/lib/examples/client-blocking.c b/lib/examples/client-blocking.c
index cce00bf..a50ee8a 100644
--- a/lib/examples/client-blocking.c
+++ b/lib/examples/client-blocking.c
@@ -26,8 +26,7 @@ blocking_client (const char *config_fn, const char *configuration,
r = rs_context_create (&h);
if (r)
{
- assert(r == RSE_NOMEM);
- assert (!"out of RAM -- unable to create libradsec context");
+ assert (!"unable to create libradsec context");
}
#if !defined (USE_CONFIG_FILE)
diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h
index bc061e0..1d718a0 100644
--- a/lib/include/radsec/radsec.h
+++ b/lib/include/radsec/radsec.h
@@ -168,10 +168,15 @@ typedef const struct value_pair rs_const_avp;
that the context must not be freed before all other libradsec
objects have been freed.
+ If support for POSIX threads was detected at configure and build
+ time \a rs_context_create will use mutexes to protect multiple
+ threads from stomping on each other in OpenSSL.
+
\a ctx Address of pointer to a struct rs_context. This is the
output of this function.
- \return RSE_OK (0) on success or RSE_NOMEM on out of memory. */
+ \return RSE_OK (0) on success, RSE_SSLERR on TLS library
+ initialisation error and RSE_NOMEM on out of memory. */
int rs_context_create(struct rs_context **ctx);
/** Free a context. Note that the context must not be freed before
diff --git a/lib/radius/Makefile.am b/lib/radius/Makefile.am
index 9aafed7..ba09db0 100644
--- a/lib/radius/Makefile.am
+++ b/lib/radius/Makefile.am
@@ -2,8 +2,7 @@ AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
BUILT_SOURCES = dictionaries.c
-
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)
AM_CFLAGS = -Wall -g
noinst_LTLIBRARIES = libradsec-radius.la
diff --git a/lib/radsec.c b/lib/radsec.c
index efd2dc3..83ce6c5 100644
--- a/lib/radsec.c
+++ b/lib/radsec.c
@@ -21,6 +21,7 @@
#include "debug.h"
#include "radsecproxy/debug.h"
#if defined (RS_ENABLE_TLS)
+#include "tls.h"
#include <regex.h>
#include "radsecproxy/list.h"
#include "radsecproxy/radsecproxy.h"
@@ -32,14 +33,15 @@ rs_context_create (struct rs_context **ctx)
{
struct rs_context *h;
+#if defined (RS_ENABLE_TLS)
+ if (tls_init ())
+ return RSE_SSLERR;
+#endif
+
h = calloc (1, sizeof(*h));
if (h == NULL)
return RSE_NOMEM;
-#if defined (RS_ENABLE_TLS)
- ssl_init ();
-#endif
-
debug_init ("libradsec"); /* radsecproxy compat, FIXME: remove */
if (ctx != NULL)
diff --git a/lib/radsecproxy/Makefile.am b/lib/radsecproxy/Makefile.am
index 962f367..dc5ffc4 100644
--- a/lib/radsecproxy/Makefile.am
+++ b/lib/radsecproxy/Makefile.am
@@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)
AM_CFLAGS = -Wall -Werror -g
noinst_LTLIBRARIES = libradsec-radsecproxy.la
diff --git a/lib/radsecproxy/tlscommon.c b/lib/radsecproxy/tlscommon.c
index 002788d..a31fa32 100644
--- a/lib/radsecproxy/tlscommon.c
+++ b/lib/radsecproxy/tlscommon.c
@@ -37,23 +37,6 @@
#include "hostport_types.h"
#include "radsecproxy.h"
-static struct hash *tlsconfs = NULL;
-
-void ssl_init(void) {
- time_t t;
- pid_t pid;
-
- SSL_load_error_strings();
- SSL_library_init();
-
- while (!RAND_status()) {
- t = time(NULL);
- pid = getpid();
- RAND_seed((unsigned char *)&t, sizeof(time_t));
- RAND_seed((unsigned char *)&pid, sizeof(pid));
- }
-}
-
static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) {
int pwdlen = strlen(userdata);
if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */
@@ -280,15 +263,6 @@ static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
return ctx;
}
-struct tls *tlsgettls(char *alt1, char *alt2) {
- struct tls *t;
-
- t = hash_read(tlsconfs, alt1, strlen(alt1));
- if (!t)
- t = hash_read(tlsconfs, alt2, strlen(alt2));
- return t;
-}
-
SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) {
struct timeval now;
@@ -476,70 +450,6 @@ int cnregexp(X509 *cert, const char *exact, const regex_t *regex) {
return 0;
}
-/* this is a bit sloppy, should not always accept match to any */
-int certnamecheck(X509 *cert, struct list *hostports) {
- struct list_node *entry;
- struct hostportres *hp;
- int r;
- uint8_t type = 0; /* 0 for DNS, AF_INET for IPv4, AF_INET6 for IPv6 */
- struct in6_addr addr;
-
- for (entry = list_first(hostports); entry; entry = list_next(entry)) {
- hp = (struct hostportres *)entry->data;
- if (hp->prefixlen != 255) {
- /* we disable the check for prefixes */
- return 1;
- }
- if (inet_pton(AF_INET, hp->host, &addr))
- type = AF_INET;
- else if (inet_pton(AF_INET6, hp->host, &addr))
- type = AF_INET6;
- else
- type = 0;
-
- r = type ? subjectaltnameaddr(cert, type, &addr) : subjectaltnameregexp(cert, GEN_DNS, hp->host, NULL);
- if (r) {
- if (r > 0) {
- debug(DBG_DBG, "certnamecheck: Found subjectaltname matching %s %s", type ? "address" : "host", hp->host);
- return 1;
- }
- debug(DBG_WARN, "certnamecheck: No subjectaltname matching %s %s", type ? "address" : "host", hp->host);
- } else {
- if (cnregexp(cert, hp->host, NULL)) {
- debug(DBG_DBG, "certnamecheck: Found cn matching host %s", hp->host);
- return 1;
- }
- debug(DBG_WARN, "certnamecheck: cn not matching host %s", hp->host);
- }
- }
- return 0;
-}
-
-int verifyconfcert(X509 *cert, struct clsrvconf *conf) {
- if (conf->certnamecheck) {
- if (!certnamecheck(cert, conf->hostports)) {
- debug(DBG_WARN, "verifyconfcert: certificate name check failed");
- return 0;
- }
- debug(DBG_WARN, "verifyconfcert: certificate name check ok");
- }
- if (conf->certcnregex) {
- if (cnregexp(cert, NULL, conf->certcnregex) < 1) {
- debug(DBG_WARN, "verifyconfcert: CN not matching regex");
- return 0;
- }
- debug(DBG_DBG, "verifyconfcert: CN matching regex");
- }
- if (conf->certuriregex) {
- if (subjectaltnameregexp(cert, GEN_URI, NULL, conf->certuriregex) < 1) {
- debug(DBG_WARN, "verifyconfcert: subjectaltname URI not matching regex");
- return 0;
- }
- debug(DBG_DBG, "verifyconfcert: subjectaltname URI matching regex");
- }
- return 1;
-}
-
/* Local Variables: */
/* c-file-style: "stroustrup" */
/* End: */
diff --git a/lib/radsecproxy/tlscommon.h b/lib/radsecproxy/tlscommon.h
index da2092e..5a6d262 100644
--- a/lib/radsecproxy/tlscommon.h
+++ b/lib/radsecproxy/tlscommon.h
@@ -26,14 +26,11 @@ struct tls {
};
#if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
-void ssl_init();
-struct tls *tlsgettls(char *alt1, char *alt2);
SSL_CTX *tlsgetctx(uint8_t type, struct tls *t);
X509 *verifytlscert(SSL *ssl);
int subjectaltnameaddr(X509 *cert, int family, const struct in6_addr *addr);
int subjectaltnameregexp(X509 *cert, int type, const char *exact, const regex_t *regex);
int cnregexp(X509 *cert, const char *exact, const regex_t *regex);
-int verifyconfcert(X509 *cert, struct clsrvconf *conf);
#endif
#if defined (__cplusplus)
diff --git a/lib/request.c b/lib/request.c
index 3a8b6dd..40ac56d 100644
--- a/lib/request.c
+++ b/lib/request.c
@@ -119,17 +119,19 @@ rs_request_send (struct rs_request *request, struct rs_packet **resp_msg)
resp_msg);
if (r == RSE_OK)
break; /* Success. */
-
- if (r != RSE_TIMEOUT_CONN && r != RSE_TIMEOUT_IO)
- break; /* Error. */
}
- else if (r != RSE_TIMEOUT_CONN && r != RSE_TIMEOUT_IO)
+ if (r != RSE_TIMEOUT_CONN && r != RSE_TIMEOUT_IO)
break; /* Error. */
+ /* Timing out reading or writing. Pop the timeout error from the
+ stack and continue the loop. */
+ rs_err_conn_pop (request->conn);
+
gettimeofday (&now, NULL);
if (++count > MRC || timercmp (&now, &end, >))
{
- r = RSE_TIMEOUT;
+ r = rs_err_conn_push_fl (request->conn, RSE_TIMEOUT,
+ __FILE__, __LINE__, NULL);
break; /* Timeout. */
}
diff --git a/lib/tests/Makefile.am b/lib/tests/Makefile.am
index dc15264..09f9d28 100644
--- a/lib/tests/Makefile.am
+++ b/lib/tests/Makefile.am
@@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS = foreign
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)
AM_CFLAGS = -Wall -Werror -g
TESTS = test-udp
diff --git a/lib/tls.c b/lib/tls.c
index 62b281f..ba3cab5 100644
--- a/lib/tls.c
+++ b/lib/tls.c
@@ -6,11 +6,19 @@
#endif
#include <stdlib.h>
+#include <unistd.h>
#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#if defined HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
+#include <openssl/rand.h>
+#include <openssl/crypto.h>
#include <radsec/radsec.h>
#include <radsec/radsec-impl.h>
@@ -18,6 +26,8 @@
#include "radsecproxy/list.h"
#include "radsecproxy/radsecproxy.h"
+#include "tls.h"
+
static struct tls *
_get_tlsconf (struct rs_connection *conn, const struct rs_realm *realm)
{
@@ -112,8 +122,132 @@ psk_client_cb (SSL *ssl,
}
#endif /* RS_ENABLE_TLS_PSK */
+/** Read \a buf_len bytes from one of the random devices into \a
+ buf. Return 0 on success and -1 on failure. */
+static int
+load_rand_ (uint8_t *buf, size_t buf_len)
+{
+ static const char *fns[] = {"/dev/urandom", "/dev/random", NULL};
+ int i;
+
+ if (buf_len > SSIZE_MAX)
+ return -1;
+
+ for (i = 0; fns[i] != NULL; i++)
+ {
+ size_t nread = 0;
+ int fd = open (fns[i], O_RDONLY);
+ if (fd < 0)
+ continue;
+ while (nread != buf_len)
+ {
+ ssize_t r = read (fd, buf + nread, buf_len - nread);
+ if (r < 0)
+ return -1;
+ if (r == 0)
+ break;
+ nread += r;
+ }
+ close (fd);
+ if (nread != buf_len)
+ return -1;
+ return 0;
+ }
+ return -1;
+}
+
+/** Initialise OpenSSL's PRNG by possibly invoking RAND_poll() and by
+ feeding RAND_seed() data from one of the random devices. If either
+ succeeds, we're happy and return 0. */
+static int
+init_openssl_rand_ (void)
+{
+ long openssl_version = 0;
+ int openssl_random_init_flag = 0;
+ int our_random_init_flag = 0;
+ uint8_t buf[32];
+
+ /* Older OpenSSL has a crash bug in RAND_poll (when a file it opens
+ gets a file descriptor with a number higher than FD_SETSIZE) so
+ use it only for newer versions. */
+ openssl_version = SSLeay ();
+ if (openssl_version >= OPENSSL_V (0,9,8,'c'))
+ openssl_random_init_flag = RAND_poll ();
+
+ our_random_init_flag = !load_rand_ (buf, sizeof(buf));
+ if (our_random_init_flag)
+ RAND_seed (buf, sizeof(buf));
+ memset (buf, 0, sizeof(buf)); /* FIXME: What if memset() is optimised out? */
+
+ if (!openssl_random_init_flag && !our_random_init_flag)
+ return -1;
+ if (!RAND_bytes (buf, sizeof(buf)))
+ return -1;
+ return 0;
+}
+
+#if defined HAVE_PTHREADS
+/** Array of pthread_mutex_t for OpenSSL. Allocated and initialised in
+ \a init_locking_ and never freed. */
+static pthread_mutex_t *s_openssl_mutexes = NULL;
+/** Number of pthread_mutex_t's allocated at s_openssl_mutexes. */
+static int s_openssl_mutexes_count = 0;
+
+/** Callback for OpenSSL when a lock is to be held or released. */
+static void
+openssl_locking_cb_ (int mode, int i, const char *file, int line)
+{
+ if (s_openssl_mutexes == NULL || i >= s_openssl_mutexes_count)
+ return;
+ if (mode & CRYPTO_LOCK)
+ pthread_mutex_lock (&s_openssl_mutexes[i]);
+ else
+ pthread_mutex_unlock (&s_openssl_mutexes[i]);
+}
+
+/** Initialise any locking needed for being thread safe. Libradsec has
+ all its own state in one or more struct rs_context and doesn't
+ need locks but libraries used by libradsec may need protection. */
+static int
+init_locking_ ()
+{
+ int i, n;
+ n = CRYPTO_num_locks ();
+
+ s_openssl_mutexes = calloc (n, sizeof(pthread_mutex_t));
+ if (s_openssl_mutexes == NULL)
+ return -RSE_NOMEM;
+ for (i = 0; i < n; i++)
+ pthread_mutex_init (&s_openssl_mutexes[i], NULL);
+ s_openssl_mutexes_count = n;
+
+ return 0;
+}
+#endif /* HAVE_PTHREADS */
+
+/** Initialise the TLS library. Return 0 on success, -1 on failure. */
+int
+tls_init ()
+{
+ SSL_load_error_strings ();
+#if defined HAVE_PTHREADS
+ if (CRYPTO_get_locking_callback () == NULL)
+ {
+ assert (s_openssl_mutexes_count == 0);
+ /* Allocate and initialise mutexes. We will never free
+ these. FIXME: Is there a portable way of having a function
+ invoked when a solib is unloaded? -ln */
+ if (init_locking_ ())
+ return -1;
+ CRYPTO_set_locking_callback (openssl_locking_cb_);
+ }
+#endif /* HAVE_PTHREADS */
+ SSL_library_init ();
+ return init_openssl_rand_ ();
+}
+
int
-rs_tls_init (struct rs_connection *conn)
+tls_init_conn (struct rs_connection *conn)
{
struct rs_context *ctx = NULL;
struct tls *tlsconf = NULL;
diff --git a/lib/tls.h b/lib/tls.h
index 4707b93..51f2a64 100644
--- a/lib/tls.h
+++ b/lib/tls.h
@@ -5,9 +5,19 @@
extern "C" {
#endif
-int rs_tls_init (struct rs_connection *conn);
+int tls_init (void);
+int tls_init_conn (struct rs_connection *conn);
int tls_verify_cert (struct rs_connection *conn);
+#define OPENSSL_VER(a,b,c,d,e) \
+ (((a)<<28) | \
+ ((b)<<20) | \
+ ((c)<<12) | \
+ ((d)<< 4) | \
+ (e))
+#define OPENSSL_V(a,b,c,d) \
+ OPENSSL_VER((a),(b),(c),(d)-'a'+1,0xf)
+
#if defined (__cplusplus)
}
#endif
diff --git a/lib/udp.c b/lib/udp.c
index 36af084..c00f215 100644
--- a/lib/udp.c
+++ b/lib/udp.c
@@ -91,7 +91,7 @@ _evcb (evutil_socket_t fd, short what, void *user_data)
{
/* FIXME: Really shouldn't happen since we've been told
that fd is readable! */
- rs_debug (("%s: EAGAIN reading UDP packet -- wot?"));
+ rs_debug (("%s: EAGAIN reading UDP packet -- wot?\n"));
goto err_out;
}
@@ -121,6 +121,8 @@ _evcb (evutil_socket_t fd, short what, void *user_data)
Don't touch it afterwards -- it might have been freed. */
if (pkt->conn->callbacks.received_cb)
pkt->conn->callbacks.received_cb (pkt, pkt->conn->user_data);
+ else
+ rs_debug (("%s: no received-callback -- dropping packet\n", __func__));
}
else if (what & EV_WRITE)
{