diff options
| -rw-r--r-- | lib/event.c | 2 | ||||
| -rw-r--r-- | lib/examples/client-blocking.c | 3 | ||||
| -rw-r--r-- | lib/radsec.c | 10 | ||||
| -rw-r--r-- | lib/radsecproxy/tlscommon.c | 15 | ||||
| -rw-r--r-- | lib/radsecproxy/tlscommon.h | 1 | ||||
| -rw-r--r-- | lib/tls.c | 81 | ||||
| -rw-r--r-- | lib/tls.h | 12 | 
7 files changed, 99 insertions, 25 deletions
| diff --git a/lib/event.c b/lib/event.c index b572184..a532da9 100644 --- a/lib/event.c +++ b/lib/event.c @@ -158,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/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/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/tlscommon.c b/lib/radsecproxy/tlscommon.c index 002788d..e7b53bf 100644 --- a/lib/radsecproxy/tlscommon.c +++ b/lib/radsecproxy/tlscommon.c @@ -39,21 +39,6 @@  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 */ diff --git a/lib/radsecproxy/tlscommon.h b/lib/radsecproxy/tlscommon.h index da2092e..ddfba2d 100644 --- a/lib/radsecproxy/tlscommon.h +++ b/lib/radsecproxy/tlscommon.h @@ -26,7 +26,6 @@ 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); @@ -6,11 +6,15 @@  #endif  #include <stdlib.h> +#include <unistd.h>  #include <assert.h> +#include <fcntl.h> +#include <limits.h>  #include <openssl/ssl.h>  #include <openssl/err.h>  #include <openssl/bn.h>  #include <openssl/x509v3.h> +#include <openssl/rand.h>  #include <radsec/radsec.h>  #include <radsec/radsec-impl.h> @@ -18,6 +22,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 +118,81 @@ 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; +} + +/** Initialise the TLS library. Return 0 on success, -1 on failure. */ +int +tls_init (void) +{ +  SSL_load_error_strings (); +  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; @@ -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 | 
