summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--radsecproxy.c214
-rw-r--r--radsecproxy.h7
-rw-r--r--util.c12
3 files changed, 145 insertions, 88 deletions
diff --git a/radsecproxy.c b/radsecproxy.c
index bcb4301..51202e4 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -58,6 +58,7 @@
#include <openssl/hmac.h>
#include "radsecproxy.h"
+static struct options options;
static struct client clients[MAX_PEERS];
static struct server servers[MAX_PEERS];
@@ -66,10 +67,9 @@ static int server_count = 0;
static struct replyq udp_server_replyq;
static int udp_server_sock = -1;
-static char *udp_server_port = DEFAULT_UDP_PORT;
static pthread_mutex_t *ssl_locks;
static long *ssl_lock_count;
-static SSL_CTX *ssl_ctx_cl;
+static SSL_CTX *ssl_ctx = NULL;
extern int optind;
extern char *optarg;
@@ -86,8 +86,14 @@ void ssl_locking_callback(int mode, int type, const char *file, int line) {
pthread_mutex_unlock(&ssl_locks[type]);
}
-void ssl_locks_setup() {
+void ssl_init() {
int i;
+ unsigned long error;
+
+ if (!options.tlscertificatefile || !options.tlscertificatekeyfile) {
+ printf("TLSCertificateFile and TLSCertificateKeyFile must be specified for TLS\n");
+ exit(1);
+ }
ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
@@ -95,10 +101,36 @@ void ssl_locks_setup() {
ssl_lock_count[i] = 0;
pthread_mutex_init(&ssl_locks[i], NULL);
}
-
CRYPTO_set_id_callback(ssl_thread_id);
CRYPTO_set_locking_callback(ssl_locking_callback);
-}
+
+ SSL_load_error_strings();
+ SSL_library_init();
+
+ while (!RAND_status()) {
+ time_t t = time(NULL);
+ pid_t pid = getpid();
+ RAND_seed((unsigned char *)&t, sizeof(time_t));
+ RAND_seed((unsigned char *)&pid, sizeof(pid));
+ }
+
+ ssl_ctx = SSL_CTX_new(TLSv1_method());
+ if (!ssl_ctx) {
+ printf("failed to initialise ssl");
+ exit(1);
+ }
+
+ if (!SSL_CTX_use_certificate_file(ssl_ctx, options.tlscertificatefile, SSL_FILETYPE_PEM)) {
+ while ((error = ERR_get_error()))
+ err("SSL: %s", ERR_error_string(error, NULL));
+ errx("Failed to load certificate");
+ }
+ if (!SSL_CTX_use_PrivateKey_file(ssl_ctx, options.tlscertificatekeyfile, SSL_FILETYPE_PEM)) {
+ while ((error = ERR_get_error()))
+ err("SSL: %s", ERR_error_string(error, NULL));
+ errx("Failed to load private key");
+ }
+}
void printauth(char *s, unsigned char *t) {
int i;
@@ -299,7 +331,7 @@ void tlsconnect(struct server *server, struct timeval *when, char *text) {
if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0)
continue;
SSL_free(server->peer.ssl);
- server->peer.ssl = SSL_new(ssl_ctx_cl);
+ server->peer.ssl = SSL_new(ssl_ctx);
SSL_set_fd(server->peer.ssl, server->sock);
if (SSL_connect(server->peer.ssl) > 0)
break;
@@ -1217,11 +1249,11 @@ void *udpserverrd(void *arg) {
struct client *fr;
pthread_t udpserverwrth;
- if ((udp_server_sock = bindport(SOCK_DGRAM, udp_server_port)) < 0) {
+ if ((udp_server_sock = bindport(SOCK_DGRAM, options.udpserverport)) < 0) {
printf("udpserverrd: socket/bind failed\n");
exit(1);
}
- printf("udpserverrd: listening on UDP port %s\n", udp_server_port);
+ printf("udpserverrd: listening on UDP port %s\n", options.udpserverport);
if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
errx("pthread_create failed");
@@ -1328,7 +1360,7 @@ void *tlsserverrd(void *arg) {
pthread_exit(NULL);
}
-int tlslistener(SSL_CTX *ssl_ctx) {
+int tlslistener() {
pthread_t tlsserverth;
int s, snew;
struct sockaddr_storage from;
@@ -1395,11 +1427,7 @@ char *parsehostport(char *s, struct peer *peer) {
printf("missing host/address\n");
exit(1);
}
- peer->host = malloc(p - field + 1);
- if (!peer->host)
- errx("malloc failed");
- memcpy(peer->host, field, p - field);
- peer->host[p - field] = '\0';
+ peer->host = stringcopy(field, p - field);
if (ipv6) {
p++;
if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n') {
@@ -1415,13 +1443,9 @@ char *parsehostport(char *s, struct peer *peer) {
printf("syntax error, : but no following port\n");
exit(1);
}
- peer->port = malloc(p - field + 1);
- if (!peer->port)
- errx("malloc failed");
- memcpy(peer->port, field, p - field);
- peer->port[p - field] = '\0';
+ peer->port = stringcopy(field, p - field);
} else
- peer->port = NULL;
+ peer->port = stringcopy(peer->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT, 0);
return p;
}
@@ -1435,14 +1459,10 @@ char *parserealmlist(char *s, struct server *server) {
n++;
l = p - s;
if (!l) {
- server->realms = NULL;
- return p;
+ printf("realm list must be specified\n");
+ exit(1);
}
- server->realmdata = malloc(l + 1);
- if (!server->realmdata)
- errx("malloc failed");
- memcpy(server->realmdata, s, l);
- server->realmdata[l] = '\0';
+ server->realmdata = stringcopy(s, l);
server->realms = malloc((1+n) * sizeof(char *));
if (!server->realms)
errx("malloc failed");
@@ -1508,15 +1528,9 @@ void getconfig(const char *serverfile, const char *clientfile) {
peer->type = *p;
for (p++; *p == ' ' || *p == '\t'; p++);
p = parsehostport(p, peer);
- if (!peer->port)
- peer->port = (peer->type == 'U' ? DEFAULT_UDP_PORT : DEFAULT_TLS_PORT);
for (; *p == ' ' || *p == '\t'; p++);
if (serverfile) {
p = parserealmlist(p, server);
- if (!server->realms) {
- printf("realm list must be specified\n");
- exit(1);
- }
for (; *p == ' ' || *p == '\t'; p++);
}
field = p;
@@ -1527,13 +1541,9 @@ void getconfig(const char *serverfile, const char *clientfile) {
printf("secret must be specified for UDP\n");
exit(1);
}
- peer->secret = DEFAULT_TLS_SECRET;
+ peer->secret = stringcopy(DEFAULT_TLS_SECRET, 0);
} else {
- peer->secret = malloc(p - field + 1);
- if (!peer->secret)
- errx("malloc failed");
- memcpy(peer->secret, field, p - field);
- peer->secret[p - field] = '\0';
+ peer->secret = stringcopy(field, p - field);
/* check that rest of line only white space */
for (; *p == ' ' || *p == '\t'; p++);
if (*p && *p != '\n') {
@@ -1586,6 +1596,62 @@ void getconfig(const char *serverfile, const char *clientfile) {
fclose(f);
}
+void getmainconfig(const char *configfile) {
+ FILE *f;
+ char line[1024];
+ char *p, *opt, *endopt, *val, *endval;
+
+ printf("opening file %s for reading\n", configfile);
+ f = fopen(configfile, "r");
+ if (!f)
+ errx("getmainconfig failed to open %s for reading", configfile);
+
+ memset(&options, 0, sizeof(options));
+
+ while (fgets(line, 1024, f)) {
+ for (p = line; *p == ' ' || *p == '\t'; p++);
+ if (!*p || *p == '#' || *p == '\n')
+ continue;
+ opt = p++;
+ for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++);
+ endopt = p - 1;
+ for (; *p == ' ' || *p == '\t'; p++);
+ if (!*p || *p == '\n') {
+ endopt[1] = '\0';
+ printf("error in %s, option %s has no value\n", configfile, opt);
+ exit(1);
+ }
+ val = p;
+ for (; *p && *p != '\n'; p++)
+ if (*p != ' ' && *p != '\t')
+ endval = p;
+ endopt[1] = '\0';
+ endval[1] = '\0';
+ printf("getmainconfig: %s = %s\n", opt, val);
+
+ if (!strcasecmp(opt, "TLSCertificateFile")) {
+ options.tlscertificatefile = stringcopy(val, 0);
+ continue;
+ }
+ if (!strcasecmp(opt, "TLSCertificateKeyFile")) {
+ options.tlscertificatekeyfile = stringcopy(val, 0);
+ continue;
+ }
+ if (!strcasecmp(opt, "UDPServerPort")) {
+ options.udpserverport = stringcopy(val, 0);
+ continue;
+ }
+
+ printf("error in %s, unknown option %s\n", configfile, opt);
+ exit(1);
+ }
+ fclose(f);
+
+ if (!options.udpserverport)
+ options.udpserverport = stringcopy(DEFAULT_UDP_PORT, 0);
+}
+
+#if 0
void parseargs(int argc, char **argv) {
int c;
@@ -1605,20 +1671,18 @@ void parseargs(int argc, char **argv) {
printf("radsecproxy [ -p UDP-port ]\n");
exit(1);
}
-
+#endif
+
int main(int argc, char **argv) {
- SSL_CTX *ssl_ctx_srv;
- unsigned long error;
pthread_t udpserverth;
// pthread_attr_t joinable;
int i;
- parseargs(argc, argv);
+ // parseargs(argc, argv);
+ getmainconfig("radsecproxy.conf");
getconfig("servers.conf", NULL);
getconfig(NULL, "clients.conf");
- ssl_locks_setup();
-
// pthread_attr_init(&joinable);
// pthread_attr_setdetachstate(&joinable, PTHREAD_CREATE_JOINABLE);
@@ -1630,53 +1694,27 @@ int main(int argc, char **argv) {
errx("pthread_create failed");
break;
}
-
- /* SSL setup */
- SSL_load_error_strings();
- SSL_library_init();
- while (!RAND_status()) {
- time_t t = time(NULL);
- pid_t pid = getpid();
- RAND_seed((unsigned char *)&t, sizeof(time_t));
- RAND_seed((unsigned char *)&pid, sizeof(pid));
- }
-
- /* initialise client part and start clients */
- ssl_ctx_cl = SSL_CTX_new(TLSv1_client_method());
- if (!ssl_ctx_cl)
- errx("no ssl ctx");
-
- for (i = 0; i < server_count; i++) {
+ /* only initialise ssl here if at least one TLS server defined */
+ for (i = 0; i < server_count; i++)
+ if (servers[i].peer.type == 'T') {
+ ssl_init();
+ break;
+ }
+
+ for (i = 0; i < server_count; i++)
if (pthread_create(&servers[i].clientth, NULL, clientwr, (void *)&servers[i]))
errx("pthread_create failed");
- }
+ /* start listener if at least one TLS client defined */
for (i = 0; i < client_count; i++)
- if (clients[i].peer.type == 'T')
- break;
-
- if (i == client_count) {
- printf("No TLS clients defined, not starting TLS listener\n");
- /* just hang around doing nothing, anything to do here? */
- for (;;)
- sleep(1000);
- }
-
- /* setting up server/daemon part */
- ssl_ctx_srv = SSL_CTX_new(TLSv1_server_method());
- if (!ssl_ctx_srv)
- errx("no ssl ctx");
- if (!SSL_CTX_use_certificate_file(ssl_ctx_srv, "/tmp/server.pem", SSL_FILETYPE_PEM)) {
- while ((error = ERR_get_error()))
- err("SSL: %s", ERR_error_string(error, NULL));
- errx("Failed to load certificate");
- }
- if (!SSL_CTX_use_PrivateKey_file(ssl_ctx_srv, "/tmp/server.key", SSL_FILETYPE_PEM)) {
- while ((error = ERR_get_error()))
- err("SSL: %s", ERR_error_string(error, NULL));
- errx("Failed to load private key");
- }
+ if (clients[i].peer.type == 'T') {
+ if (!ssl_ctx)
+ ssl_init();
+ return tlslistener();
+ }
- return tlslistener(ssl_ctx_srv);
+ /* just hang around doing nothing, anything to do here? */
+ for (;;)
+ sleep(1000);
}
diff --git a/radsecproxy.h b/radsecproxy.h
index b4393d4..e6dca52 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -42,6 +42,12 @@
#define RAD_Attr_Length 1
#define RAD_Attr_Value 2
+struct options {
+ char *tlscertificatefile;
+ char *tlscertificatekeyfile;
+ char *udpserverport;
+};
+
/* requests that a client will send */
struct request {
unsigned char *buf;
@@ -101,6 +107,7 @@ struct server {
void errx(char *format, ...);
void err(char *format, ...);
+char *stringcopy(char *s, int len);
char *addr2string(struct sockaddr *addr, socklen_t len);
int bindport(int type, char *port);
int connectport(int type, char *host, char *port);
diff --git a/util.c b/util.c
index 7ca29c7..e4372a3 100644
--- a/util.c
+++ b/util.c
@@ -45,6 +45,18 @@ void err(char *format, ...) {
fprintf(stderr, "\n");
}
+char *stringcopy(char *s, int len) {
+ char *r;
+ if (!len)
+ len = strlen(s);
+ r = malloc(len + 1);
+ if (!r)
+ errx("stringcopy: malloc failed");
+ memcpy(r, s, len);
+ r[len] = '\0';
+ return r;
+}
+
char *addr2string(struct sockaddr *addr, socklen_t len) {
struct sockaddr_in6 *sa6;
struct sockaddr_in sa4;