NOTE: Clean up of resources not yet sane. Expect resource leakages.
NOTE: Most failure cases are not handled properly. With the wind at
your back and the sun shining, it might work.
* copyright notice and this permission notice appear in all copies.
*/
-struct hostportres {
- char *host;
- char *port;
- uint8_t prefixlen;
- struct addrinfo *addrinfo;
-};
+#include "hostport_types.h"
struct hostportres *newhostport(char *hostport, char *default_port, uint8_t prefixok);
int addhostport(struct list **hostports, char **hostport, char *portdefault, uint8_t prefixok);
--- /dev/null
+struct hostportres {
+ char *host;
+ char *port;
+ uint8_t prefixlen;
+ struct addrinfo *addrinfo;
+};
debug.c \
err.c \
packet.c \
+ radsec.c \
request.c \
- radsec.c
+ tls.c
+
+libradsec_la_SOURCES += \
+ rsp_debug.c \
+ rsp_hash.c \
+ rsp_list.c \
+ rsp_tlscommon.c \
+ rsp_util.c
+
libradsec_la_LDFLAGS = -version-info 0:0:0
-libradsec_la_CFLAGS = $(CFLAGS) #-DDEBUG -DDEBUG_LEVENT
+libradsec_la_CFLAGS = $(CFLAGS) -DDEBUG -DDEBUG_LEVENT
/* See the file COPYING for licensing information. */
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <freeradius/libradius.h>
#include <radsec/radsec.h>
#include <radsec/radsec-impl.h>
+/* See the file COPYING for licensing information. */
+
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <confuse.h>
#include <string.h>
#include <radsec/radsec.h>
#if 0
# example of client config
config NAME {
- type = "UDP|TCP|TLS|DTLS"
+ type = "UDP"|"TCP"|"TLS"|"DTLS"
+ cacertfile = STRING
+ #cacertpath = STRING
+ certfile = STRING
+ certkeyfile = STRING
server {
hostname = STRING
service = STRING
cfg_opt_t config_opts[] =
{
CFG_STR ("type", "UDP", CFGF_NONE),
+ CFG_STR ("cacertfile", NULL, CFGF_NONE),
+ /*CFG_STR ("cacertpath", NULL, CFGF_NONE),*/
+ CFG_STR ("certfile", NULL, CFGF_NONE),
+ CFG_STR ("certkeyfile", NULL, CFGF_NONE),
CFG_SEC ("server", server_opts, CFGF_MULTI),
CFG_END ()
};
ctx->realms = r;
cfg_config = cfg_getnsec (cfg, "config", i);
r->name = strdup (cfg_title (cfg_config));
+
typestr = cfg_getstr (cfg_config, "type");
if (!strcmp (typestr, "UDP"))
r->type = RS_CONN_TYPE_UDP;
return rs_err_ctx_push_fl (ctx, RSE_CONFIG, __FILE__, __LINE__,
"%s: invalid connection type", typestr);
+ r->cacertfile = cfg_getstr (cfg_config, "cacertfile");
+ /*r->cacertpath = cfg_getstr (cfg_config, "cacertpath");*/
+ r->certfile = cfg_getstr (cfg_config, "certfile");
+ r->certkeyfile = cfg_getstr (cfg_config, "certkeyfile");
+
/* Add peers, one per server stanza. */
for (j = 0; j < cfg_size (cfg_config, "server"); j++)
{
if (!p)
return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
NULL);
+ p->realm = r;
cfg_server = cfg_getnsec (cfg_config, "server", j);
_rs_resolv (&p->addr, r->type, cfg_getstr (cfg_server, "hostname"),
# Checks for programs.
AC_PROG_CC
+# Enable-knobs.
+AH_TEMPLATE([RS_ENABLE_TLS], [TLS (RadSec) enabled])
+AH_TEMPLATE([RADPROT_TLS], [])
+AC_ARG_ENABLE([tls], AS_HELP_STRING([--enable-tls], [enable TLS (RadSec)]),
+ [AC_DEFINE([RS_ENABLE_TLS])
+ AC_DEFINE([RADPROT_TLS])])
+
# Checks for libraries.
AC_CHECK_LIB([confuse], [cfg_init],,
AC_MSG_ERROR([required library libconfuse not found]))
AC_MSG_ERROR([required library libevent_core not found]))
AC_CHECK_LIB([freeradius-radius], [rad_alloc],,
AC_MSG_ERROR([required library libfreeradius-radius not found]))
+dnl TODO: Only do this if --enable-tls or --enable-dtls.
+#AC_CHECK_LIB([ssl], [SSL_new],,
+# AC_MSG_ERROR([required library libssl not found]))
+AC_CHECK_LIB([event_openssl], [bufferevent_openssl_socket_new],,
+ AC_MSG_ERROR([required library event_openssl not found]))
# Checks for header files.
-AC_CHECK_HEADERS([netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h unistd.h])
+AC_CHECK_HEADERS(
+ [netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
AC_TYPE_UINT8_T
# Checks for library functions.
-AC_FUNC_MALLOC
-AC_FUNC_REALLOC
AC_CHECK_FUNCS([memset socket strdup strerror strrchr])
AC_CONFIG_FILES([Makefile
/* See the file COPYING for licensing information. */
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <assert.h>
+#include <event2/event.h>
#include <radsec/radsec.h>
#include <radsec/radsec-impl.h>
struct evutil_addrinfo hints, *res = NULL;
memset (&hints, 0, sizeof(struct evutil_addrinfo));
- hints.ai_family = AF_UNSPEC; /* v4 or v6. */
+ hints.ai_family = AF_INET; /* IPv4 only. TODO: Set AF_UNSPEC. */
hints.ai_flags = AI_ADDRCONFIG;
switch (type)
{
/* See the file COPYING for licensing information. */
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#include <freeradius/libradius.h>
#include <radsec/radsec.h>
/* See the file COPYING for licensing information. */
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#include <string.h>
#include <assert.h>
const char *_errtxt[] = {
"SUCCESS", /* 0 RSE_OK */
- "NOMEM", /* 1 RSE_NOMEM */
- "NYI -- not yet implemented", /* 2 RSE_NOSYS */
+ "out of memory", /* 1 RSE_NOMEM */
+ "not yet implemented", /* 2 RSE_NOSYS */
"invalid handle" /* 3 RSE_INVALID_CTX */
"invalid connection" /* 4 RSE_INVALID_CONN */
"connection type mismatch" /* 5 RSE_CONN_TYPE_MISMATCH */
"libevent error" /* 9 RSE_EVENT */
"connection error" /* 10 RSE_CONNERR */
"invalid configuration file" /* 11 RSE_CONFIG */
- "authentication failed" /* RSE_BADAUTH */
- "ERR 13" /* RSE_ */
- "ERR 14" /* RSE_ */
+ "authentication failed" /* 12 RSE_BADAUTH */
+ "internal error" /* 13 RSE_INTERNAL */
+ "SSL error" /* 14 RSE_SSLERR */
"ERR 15" /* RSE_ */
"ERR 16" /* RSE_ */
"ERR 17" /* RSE_ */
-config blocking {
+config blocking-udp {
type = "UDP"
server {
hostname = "localhost"
tries = 10 /* optional */
}
}
+config blocking-tls {
+ type = "TLS"
+
+ cacertfile = "/home/linus/nordberg-ca.crt"
+ #cacertpath =
+ certfile = "/home/linus/p/radsecproxy/src/maatuska.nordberg.se.crt"
+ certkeyfile = "/home/linus/p/radsecproxy/src/maatuska.nordberg.se.key"
+ #certkeypwd = "passphrase"
+ #cacheexpiry = <seconds>
+ #crlcheck = "on" | "off"
+ #policyoids = ?
+
+ server {
+ hostname = "localhost"
+ service = "4433"
+ secret = "sikrit"
+ timeout = 1 /* optional */
+ tries = 10 /* optional */
+ }
+}
#include <freeradius/libradius.h>
#include <event2/util.h>
+#if defined(RS_ENABLE_TLS)
+#include <openssl/ssl.h>
+#endif
/* Constants. */
#define RS_HEADER_LEN 4
struct rs_peer {
struct rs_connection *conn;
+ struct rs_realm *realm;
struct evutil_addrinfo *addr;
int fd; /* Socket. */
char is_connecting; /* FIXME: replace with a single state member */
struct rs_realm {
char *name;
enum rs_conn_type type;
+ char *cacertfile;
+ char *cacertpath;
+ char *certfile;
+ char *certkeyfile;
struct rs_peer *peers;
struct rs_realm *next;
};
struct rs_error *err;
int nextid;
int user_dispatch_flag : 1; /* User does the dispatching. */
+#if defined(RS_ENABLE_TLS)
+ SSL_CTX *tls_ctx;
+ SSL *tls_ssl;
+#endif
};
struct rs_packet {
RSE_CONNERR = 10,
RSE_CONFIG = 11,
RSE_BADAUTH = 12,
+ RSE_INTERNAL = 13,
+ RSE_SSLERR = 14,
RSE_SOME_ERROR = 21,
};
/* See the file COPYING for licensing information. */
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <freeradius/libradius.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
+#if defined RS_ENABLE_TLS
+#include <event2/bufferevent_ssl.h>
+#include <openssl/err.h>
+#endif
#include <radsec/radsec.h>
#include <radsec/radsec-impl.h>
+#include "tls.h"
#if defined DEBUG
#include <netdb.h>
#include <sys/socket.h>
struct rs_packet *pkt = (struct rs_packet *)ctx;
struct rs_connection *conn;
struct rs_peer *p;
- int err;
+ unsigned long err;
assert (pkt);
assert (pkt->conn);
p->is_connected = 1;
if (conn->callbacks.connected_cb)
conn->callbacks.connected_cb (conn->user_data);
-
#if defined (DEBUG)
fprintf (stderr, "%s: connected\n", __func__);
#endif
/* Packet will be freed in write callback. */
}
else if (events & BEV_EVENT_ERROR)
- rs_err_conn_push_fl (pkt->conn, RSE_CONNERR, __FILE__, __LINE__, NULL);
+ {
+#if defined RS_ENABLE_TLS
+ if (conn->tls_ssl) /* FIXME: correct check? */
+ {
+ for (err = bufferevent_get_openssl_error (conn->bev);
+ err;
+ err = bufferevent_get_openssl_error (conn->bev))
+ {
+ fprintf (stderr, "%s: openssl error: %s\n", __func__,
+ ERR_error_string (err, NULL)); /* DEBUG, until verified that pushed errors will actually be handled */
+ rs_err_conn_push_fl (pkt->conn, RSE_SSLERR, __FILE__, __LINE__,
+ "%d", err);
+ }
+ }
+#endif
+ rs_err_conn_push_fl (pkt->conn, RSE_CONNERR, __FILE__, __LINE__, NULL);
+ fprintf (stderr, "%s: BEV_EVENT_ERROR\n", __func__); /* DEBUG, until verified that pushed errors will actually be handled */
+ }
}
static void
static int
_init_bev (struct rs_connection *conn, struct rs_peer *peer)
{
- if (!conn->bev)
+ if (conn->bev)
+ return RSE_OK;
+
+ switch (conn->type)
{
+ case RS_CONN_TYPE_UDP:
+ case RS_CONN_TYPE_TCP:
conn->bev = bufferevent_socket_new (conn->evb, peer->fd, 0);
if (!conn->bev)
return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
"bufferevent_socket_new");
+ break;
+ case RS_CONN_TYPE_TLS:
+ if (rs_tls_init (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
+ SSL_set_bio() after BIO_new_socket() with flag=1. */
+ conn->bev =
+ bufferevent_openssl_socket_new (conn->evb, peer->fd, conn->tls_ssl,
+ BUFFEREVENT_SSL_CONNECTING, 0);
+ if (!conn->bev)
+ return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_openssl_socket_new");
+
+ break;
+ case RS_CONN_TYPE_DTLS:
+ return rs_err_conn_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
+ "%s: NYI", __func__);
+ default:
+ return rs_err_conn_push_fl (conn, RSE_INTERNAL, __FILE__, __LINE__,
+ "%s: invalid connection type: %d", __func__,
+ conn->type);
}
+
return RSE_OK;
}
/* See the file COPYING for licensing information. */
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <event2/util.h>
#include <radsec/radsec.h>
#include <radsec/radsec-impl.h>
+#if defined RS_ENABLE_TLS
+#include <regex.h>
+#include "rsp_list.h"
+#include "../radsecproxy.h"
+#endif
+#include "rsp_debug.h"
int
rs_context_create(struct rs_context **ctx, const char *dict)
}
free (buf1);
free (buf2);
+#if defined RS_ENABLE_TLS
+ ssl_init ();
+#endif
#if defined (DEBUG)
fr_log_fp = stderr;
fr_debug_flag = 1;
#endif
+ debug_init ("libradsec"); /* radsecproxy compat, FIXME: remove */
memset (h, 0, sizeof(struct rs_context));
fr_randinit (&h->fr_randctx, 0);
/* See the file COPYING for licensing information. */
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <time.h>
#include <assert.h>
#include <event2/event.h>
static void
_rs_req_connected(void *user_data)
{
- struct rs_request *request = (struct rs_request *)user_data;
+ //struct rs_request *request = (struct rs_request *)user_data;
}
static void
_rs_req_disconnected(void *user_data)
{
- struct rs_request *request = (struct rs_request *)user_data;
+ //struct rs_request *request = (struct rs_request *)user_data;
}
static void
_rs_req_packet_received(const struct rs_packet *pkt, void *user_data)
{
- struct rs_request *request = (struct rs_request *)user_data;
+ //struct rs_request *request = (struct rs_request *)user_data;
}
static void
_rs_req_packet_sent(void *user_data)
{
- struct rs_request *request = (struct rs_request *)user_data;
+ //struct rs_request *request = (struct rs_request *)user_data;
}
int
#include <syslog.h>
#include <errno.h>
#include <assert.h>
-#include "debug.h"
-#include "util.h"
+#include "rsp_debug.h"
+#include "rsp_util.h"
static char *debug_ident = NULL;
static uint8_t debug_level = DBG_INFO;
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
-#include "list.h"
-#include "hash.h"
+#include "rsp_list.h"
+#include "rsp_hash.h"
/* allocates and initialises hash structure; returns NULL if malloc fails */
struct hash *hash_create() {
* copyright notice and this permission notice appear in all copies.
*/
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <stdlib.h>
#include <string.h>
-#include "list.h"
+#include "rsp_list.h"
/* allocates and initialises list structure; returns NULL if malloc fails */
struct list *list_create() {
* copyright notice and this permission notice appear in all copies.
*/
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
#include <signal.h>
#include <sys/socket.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/x509v3.h>
-#include "debug.h"
-#include "list.h"
-#include "hash.h"
-#include "util.h"
-#include "hostport.h"
-#include "radsecproxy.h"
+#include "rsp_debug.h"
+#include "rsp_list.h"
+#include "rsp_hash.h"
+#include "rsp_util.h"
+#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 */
return 0;
}
- calist = conf->cacertfile ? SSL_load_client_CA_file(conf->cacertfile) : NULL;
+ calist = conf->cacertfile ? SSL_load_client_CA_file(conf->cacertfile) : NULL;
+
if (!conf->cacertfile || calist) {
if (conf->cacertpath) {
if (!calist)
#ifdef RADPROT_TLS
case RAD_TLS:
ctx = SSL_CTX_new(TLSv1_method());
-#ifdef DEBUG
- SSL_CTX_set_info_callback(ctx, ssl_info_callback);
-#endif
break;
#endif
#ifdef RADPROT_DTLS
case RAD_DTLS:
ctx = SSL_CTX_new(DTLSv1_method());
-#ifdef DEBUG
- SSL_CTX_set_info_callback(ctx, ssl_info_callback);
-#endif
SSL_CTX_set_read_ahead(ctx, 1);
break;
#endif
}
if (!ctx) {
debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name);
+ while ((error = ERR_get_error()))
+ debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
return NULL;
}
+#ifdef DEBUG
+ SSL_CTX_set_info_callback(ctx, ssl_info_callback);
+#endif
if (conf->certkeypwd) {
SSL_CTX_set_default_passwd_cb_userdata(ctx, conf->certkeypwd);
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
}
- if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) ||
- !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) ||
- !SSL_CTX_check_private_key(ctx)) {
- while ((error = ERR_get_error()))
- debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
- debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS in TLS context %s", conf->name);
- SSL_CTX_free(ctx);
- return NULL;
+ if (conf->certfile || conf->certkeyfile) {
+ if (!SSL_CTX_use_certificate_chain_file(ctx, conf->certfile) ||
+ !SSL_CTX_use_PrivateKey_file(ctx, conf->certkeyfile, SSL_FILETYPE_PEM) ||
+ !SSL_CTX_check_private_key(ctx)) {
+ while ((error = ERR_get_error()))
+ debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
+ debug(DBG_ERR, "tlscreatectx: Error initialising SSL/TLS (certfile issues) in TLS context %s", conf->name);
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
}
if (conf->policyoids) {
return 1;
}
+#if 0
int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
struct tls *conf;
long int expiry = LONG_MIN;
free(conf);
return 0;
}
+#endif
int addmatchcertattr(struct clsrvconf *conf) {
char *v;
};
#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);
#include <errno.h>
#include <sys/select.h>
#include <stdarg.h>
-#include "debug.h"
-#include "util.h"
+#include "rsp_debug.h"
+#include "rsp_util.h"
char *stringcopy(const char *s, int len) {
char *r;
--- /dev/null
+/* See the file COPYING for licensing information. */
+
+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <openssl/ssl.h>
+#include <radsec/radsec.h>
+#include <radsec/radsec-impl.h>
+
+#include <regex.h>
+#include "rsp_list.h"
+#include "../radsecproxy.h"
+
+static struct tls *
+_get_tlsconf (const struct rs_context *ctx, const struct rs_realm *realm)
+{
+ struct tls *c = rs_malloc (ctx, sizeof (struct tls));
+
+ if (c)
+ {
+ memset (c, 0, sizeof (struct tls));
+ /* TODO: Make sure old radsecproxy code doesn't free these all
+ of a sudden, or strdup them. */
+ c->name = realm->name;
+ c->cacertfile = realm->cacertfile;
+ c->cacertpath = NULL; /* NYI */
+ c->certfile = realm->certfile;
+ c->certkeyfile = realm->certkeyfile;
+ c->certkeypwd = NULL; /* NYI */
+ c->cacheexpiry = 0; /* NYI */
+ c->crlcheck = 0; /* NYI */
+ c->policyoids = (char **) NULL; /* NYI */
+ }
+
+ return c;
+}
+
+int
+rs_tls_init (struct rs_connection *conn)
+{
+ struct rs_context *ctx;
+ struct tls *tlsconf;
+ SSL_CTX *ssl_ctx;
+ SSL *ssl;
+ assert (conn->ctx);
+ ctx = conn->ctx;
+
+ tlsconf = _get_tlsconf (ctx, conn->active_peer->realm);
+ assert (tlsconf);
+ ssl_ctx = tlsgetctx (RADPROT_TLS, tlsconf);
+ if (!ssl_ctx)
+ {
+ /* TODO: check radsecproxy error */
+ return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
+ NULL);
+ }
+
+ ssl = SSL_new (ssl_ctx);
+ if (!ssl)
+ {
+ /* TODO: check and report SSL error */
+ /* TODO: free ssl_ctx */
+ return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
+ NULL);
+ }
+
+ conn->tls_ctx = ssl_ctx;
+ conn->tls_ssl = ssl;
+ rs_free (ctx, tlsconf);
+ return RSE_OK;
+}
--- /dev/null
+int rs_tls_init (struct rs_connection *conn);
struct server *servers;
};
-#include "tlscommon.h"
+#include "rsp_tlscommon.h"
struct client {
struct clsrvconf *conf;