diff options
-rw-r--r-- | dtls.c | 42 | ||||
-rw-r--r-- | dtls.h | 3 | ||||
-rw-r--r-- | radsecproxy.c | 156 | ||||
-rw-r--r-- | radsecproxy.h | 7 | ||||
-rw-r--r-- | udp.c | 48 | ||||
-rw-r--r-- | udp.h | 4 | ||||
-rw-r--r-- | util.c | 27 | ||||
-rw-r--r-- | util.h | 2 |
8 files changed, 171 insertions, 118 deletions
@@ -32,6 +32,9 @@ #include "radsecproxy.h" #include "dtls.h" +static int client4_sock = -1; +static int client6_sock = -1; + int udp2bio(int s, struct queue *q, int cnt) { unsigned char *buf; BIO *rbio; @@ -470,3 +473,42 @@ void *dtlsclientrd(void *arg) { free(buf); } } + +void addclientdtls(struct client *client) { + client->replyq = newqueue(); + client->rbios = newqueue(); +} + +void addserverextradtls(struct clsrvconf *conf) { + switch (conf->addrinfo->ai_family) { + case AF_INET: + if (client4_sock < 0) { + client4_sock = bindtoaddr(getsrcprotores(RAD_DTLS), AF_INET, 0, 1); + if (client4_sock < 0) + debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); + } + conf->servers->sock = client4_sock; + break; + case AF_INET6: + if (client6_sock < 0) { + client6_sock = bindtoaddr(getsrcprotores(RAD_DTLS), AF_INET6, 0, 1); + if (client6_sock < 0) + debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); + } + conf->servers->sock = client6_sock; + break; + default: + debugx(1, DBG_ERR, "addserver: unsupported address family"); + } +} + +void initextradtls() { + pthread_t cl4th, cl6th; + + if (client4_sock >= 0) + if (pthread_create(&cl4th, NULL, udpdtlsclientrd, (void *)&client4_sock)) + debugx(1, DBG_ERR, "pthread_create failed"); + if (client6_sock >= 0) + if (pthread_create(&cl6th, NULL, udpdtlsclientrd, (void *)&client6_sock)) + debugx(1, DBG_ERR, "pthread_create failed"); +} @@ -12,3 +12,6 @@ void *dtlsservernew(void *arg); void *dtlsclientrd(void *arg); void *udpdtlsclientrd(void *arg); int clientradputdtls(struct server *server, unsigned char *rad); +void addclientdtls(struct client *client); +void addserverextradtls(struct clsrvconf *conf); +void initextradtls(); diff --git a/radsecproxy.c b/radsecproxy.c index 63dba64..8f76aaa 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -75,11 +75,6 @@ struct list *realms, *tlsconfs, *rewriteconfs; static struct addrinfo *srcprotores[4] = { NULL, NULL, NULL, NULL }; -static struct queue *udp_server_replyq = NULL; -static int udp_client4_sock = -1; -static int udp_client6_sock = -1; -static int dtls_client4_sock = -1; -static int dtls_client6_sock = -1; static pthread_mutex_t tlsconfs_lock; static pthread_mutex_t *ssl_locks = NULL; static long *ssl_lock_count; @@ -106,8 +101,11 @@ static const struct protodefs protodefs[] = { udpserverrd, /* listener */ &options.sourceudp, /* srcaddrport */ NULL, /* connecter */ - udpclientrd, /* clientreader */ - clientradputudp /* clientradput */ + NULL, /* clientconnreader */ + clientradputudp, /* clientradput */ + addclientudp, /* addclient */ + addserverextraudp, /* addserverextra */ + initextraudp /* initextra */ }, { "tls", /* TLS, assuming RAD_TLS defined as 1 */ "mysecret", /* secretdefault */ @@ -120,8 +118,11 @@ static const struct protodefs protodefs[] = { tlslistener, /* listener */ &options.sourcetls, /* srcaddrport */ tlsconnect, /* connecter */ - tlsclientrd, /* clientreader */ - clientradputtls /* clientradput */ + tlsclientrd, /* clientconnreader */ + clientradputtls, /* clientradput */ + NULL, /* addclient */ + NULL, /* addserverextra */ + NULL /* initextra */ }, { "tcp", /* TCP, assuming RAD_TCP defined as 2 */ NULL, /* secretdefault */ @@ -134,8 +135,11 @@ static const struct protodefs protodefs[] = { tcplistener, /* listener */ &options.sourcetcp, /* srcaddrport */ tcpconnect, /* connecter */ - tcpclientrd, /* clientreader */ - clientradputtcp /* clientradput */ + tcpclientrd, /* clientconnreader */ + clientradputtcp, /* clientradput */ + NULL, /* addclient */ + NULL, /* addserverextra */ + NULL /* initextra */ }, { "dtls", /* DTLS, assuming RAD_DTLS defined as 3 */ "mysecret", /* secretdefault */ @@ -148,8 +152,11 @@ static const struct protodefs protodefs[] = { udpdtlsserverrd, /* listener */ &options.sourcedtls, /* srcaddrport */ dtlsconnect, /* connecter */ - dtlsclientrd, /* clientreader */ - clientradputdtls /* clientradput */ + dtlsclientrd, /* clientconnreader */ + clientradputdtls, /* clientradput */ + addclientdtls, /* addclient */ + addserverextradtls, /* addserverextra */ + initextradtls /* initextra */ }, { NULL } @@ -307,33 +314,6 @@ int resolvepeer(struct clsrvconf *conf, int ai_flags) { return 1; } -int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only) { - int s, on = 1; - struct addrinfo *res; - - for (res = addrinfo; res; res = res->ai_next) { - if (family != AF_UNSPEC && family != res->ai_family) - continue; - s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s < 0) { - debug(DBG_WARN, "bindtoaddr: socket failed"); - continue; - } - if (reuse) - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); -#ifdef IPV6_V6ONLY - if (v6only) - setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); -#endif - - if (!bind(s, res->ai_addr, res->ai_addrlen)) - return s; - debug(DBG_WARN, "bindtoaddr: bind failed"); - close(s); - } - return -1; -} - char *parsehostport(char *s, struct clsrvconf *conf, char *default_port) { char *p, *field; int ipv6 = 0; @@ -490,11 +470,11 @@ struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_ } /* returns next config of given type, or NULL */ -struct clsrvconf *find_conf_type(uint8_t type, struct list *confs, struct list_node **cur) { +struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur) { struct list_node *entry; struct clsrvconf *conf; - for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) { + for (entry = (cur && *cur ? list_next(*cur) : list_first(clconfs)); entry; entry = list_next(entry)) { conf = (struct clsrvconf *)entry->data; if (conf->type == type) { if (cur) @@ -558,9 +538,10 @@ struct client *addclient(struct clsrvconf *conf) { memset(new, 0, sizeof(struct client)); new->conf = conf; - new->replyq = conf->type == RAD_UDP ? udp_server_replyq : newqueue(); - if (conf->type == RAD_DTLS) - new->rbios = newqueue(); + if (conf->pdef->addclient) + conf->pdef->addclient(new); + else + new->replyq = newqueue(); list_push(conf->clients, new); return new; } @@ -645,54 +626,9 @@ int addserver(struct clsrvconf *conf) { freeclsrvres(res); } - switch (type) { - case RAD_UDP: - switch (conf->addrinfo->ai_family) { - case AF_INET: - if (udp_client4_sock < 0) { - udp_client4_sock = bindtoaddr(srcprotores[RAD_UDP], AF_INET, 0, 1); - if (udp_client4_sock < 0) - debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); - } - conf->servers->sock = udp_client4_sock; - break; - case AF_INET6: - if (udp_client6_sock < 0) { - udp_client6_sock = bindtoaddr(srcprotores[RAD_UDP], AF_INET6, 0, 1); - if (udp_client6_sock < 0) - debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); - } - conf->servers->sock = udp_client6_sock; - break; - default: - debugx(1, DBG_ERR, "addserver: unsupported address family"); - } - break; - case RAD_DTLS: - switch (conf->addrinfo->ai_family) { - case AF_INET: - if (dtls_client4_sock < 0) { - dtls_client4_sock = bindtoaddr(srcprotores[RAD_DTLS], AF_INET, 0, 1); - if (dtls_client4_sock < 0) - debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); - } - conf->servers->sock = dtls_client4_sock; - break; - case AF_INET6: - if (dtls_client6_sock < 0) { - dtls_client6_sock = bindtoaddr(srcprotores[RAD_DTLS], AF_INET6, 0, 1); - if (dtls_client6_sock < 0) - debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); - } - conf->servers->sock = dtls_client6_sock; - break; - default: - debugx(1, DBG_ERR, "addserver: unsupported address family"); - } - break; - default: - conf->servers->sock = -1; - } + conf->servers->sock = -1; + if (conf->pdef->addserverextra) + conf->pdef->addserverextra(conf); conf->servers->requests = calloc(MAX_REQUESTS, sizeof(struct request)); if (!conf->servers->requests) { @@ -2166,7 +2102,7 @@ void *clientwr(void *arg) { if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 6 : 0, "clientwr")) goto errexit; server->connectionok = 1; - if (pthread_create(&clientrdth, NULL, conf->pdef->clientreader, (void *)server)) { + if (pthread_create(&clientrdth, NULL, conf->pdef->clientconnreader, (void *)server)) { debug(DBG_ERR, "clientwr: pthread_create failed"); goto errexit; } @@ -3506,12 +3442,13 @@ void *sighandler(void *arg) { } int main(int argc, char **argv) { - pthread_t sigth, udpclient4rdth, udpclient6rdth, udpserverwrth, dtlsclient4rdth, dtlsclient6rdth; + pthread_t sigth; sigset_t sigset; struct list_node *entry; uint8_t foreground = 0, pretend = 0, loglevel = 0; char *configfile = NULL; struct clsrvconf *srvconf; + int i; debug_init("radsecproxy"); debug_set_level(DEBUG_LEVEL); @@ -3563,34 +3500,21 @@ int main(int argc, char **argv) { freeaddrinfo(srcprotores[RAD_UDP]); srcprotores[RAD_UDP] = NULL; } + + for (i = 0; protodefs[i].name; i++) + if (protodefs[i].initextra) + protodefs[i].initextra(); - if (udp_client4_sock >= 0) - if (pthread_create(&udpclient4rdth, NULL, protodefs[RAD_UDP].clientreader, (void *)&udp_client4_sock)) - debugx(1, DBG_ERR, "pthread_create failed"); - if (udp_client6_sock >= 0) - if (pthread_create(&udpclient6rdth, NULL, protodefs[RAD_UDP].clientreader, (void *)&udp_client6_sock)) - debugx(1, DBG_ERR, "pthread_create failed"); - - if (dtls_client4_sock >= 0) - if (pthread_create(&dtlsclient4rdth, NULL, udpdtlsclientrd, (void *)&dtls_client4_sock)) - debugx(1, DBG_ERR, "pthread_create failed"); - if (dtls_client6_sock >= 0) - if (pthread_create(&dtlsclient6rdth, NULL, udpdtlsclientrd, (void *)&dtls_client6_sock)) - debugx(1, DBG_ERR, "pthread_create failed"); - - if (find_conf_type(RAD_TCP, clconfs, NULL)) + if (find_clconf_type(RAD_TCP, NULL)) createlisteners(RAD_TCP, options.listentcp); - if (find_conf_type(RAD_TLS, clconfs, NULL)) + if (find_clconf_type(RAD_TLS, NULL)) createlisteners(RAD_TLS, options.listentls); - if (find_conf_type(RAD_DTLS, clconfs, NULL)) + if (find_clconf_type(RAD_DTLS, NULL)) createlisteners(RAD_DTLS, options.listendtls); - if (find_conf_type(RAD_UDP, clconfs, NULL)) { - udp_server_replyq = newqueue(); - if (pthread_create(&udpserverwrth, NULL, udpserverwr, (void *)udp_server_replyq)) - debugx(1, DBG_ERR, "pthread_create failed"); + if (find_clconf_type(RAD_UDP, NULL)) { createlisteners(RAD_UDP, options.listenudp); if (options.listenaccudp) createlisteners(RAD_UDP, options.listenaccudp); diff --git a/radsecproxy.h b/radsecproxy.h index c2e9425..f3c0742 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -187,8 +187,11 @@ struct protodefs { void *(*listener)(void*); char **srcaddrport; int (*connecter)(struct server *, struct timeval *, int, char *); - void *(*clientreader)(void*); + void *(*clientconnreader)(void*); int (*clientradput)(struct server *, unsigned char *); + void (*addclient)(struct client *); + void (*addserverextra)(struct clsrvconf *); + void (*initextra)(); }; #define RADLEN(x) ntohs(((uint16_t *)(x))[1]) @@ -205,9 +208,11 @@ struct protodefs { struct addrinfo *getsrcprotores(uint8_t type); struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur); struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur); +struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur); struct client *addclient(struct clsrvconf *conf); void removeclient(struct client *client); void removeclientrqs(struct client *client); +struct queue *newqueue(); int radsrv(struct request *rq); X509 *verifytlscert(SSL *ssl); int verifyconfcert(X509 *cert, struct clsrvconf *conf); @@ -31,6 +31,10 @@ #include "radsecproxy.h" #include "tls.h" +static int client4_sock = -1; +static int client6_sock = -1; +static struct queue *server_replyq = NULL; + /* exactly one of client and server must be non-NULL */ /* return who we received from in *client or *server */ /* return from in sa if not NULL */ @@ -194,3 +198,47 @@ void *udpserverwr(void *arg) { free(reply); } } + +void addclientudp(struct client *client) { + client->replyq = server_replyq; +} + +void addserverextraudp(struct clsrvconf *conf) { + switch (conf->addrinfo->ai_family) { + case AF_INET: + if (client4_sock < 0) { + client4_sock = bindtoaddr(getsrcprotores(RAD_UDP), AF_INET, 0, 1); + if (client4_sock < 0) + debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); + } + conf->servers->sock = client4_sock; + break; + case AF_INET6: + if (client6_sock < 0) { + client6_sock = bindtoaddr(getsrcprotores(RAD_UDP), AF_INET6, 0, 1); + if (client6_sock < 0) + debugx(1, DBG_ERR, "addserver: failed to create client socket for server %s", conf->host); + } + conf->servers->sock = client6_sock; + break; + default: + debugx(1, DBG_ERR, "addserver: unsupported address family"); + } +} + +void initextraudp() { + pthread_t cl4th, cl6th, srvth; + + if (client4_sock >= 0) + if (pthread_create(&cl4th, NULL, udpclientrd, (void *)&client4_sock)) + debugx(1, DBG_ERR, "pthread_create failed"); + if (client6_sock >= 0) + if (pthread_create(&cl6th, NULL, udpclientrd, (void *)&client6_sock)) + debugx(1, DBG_ERR, "pthread_create failed"); + + if (find_clconf_type(RAD_UDP, NULL)) { + server_replyq = newqueue(); + if (pthread_create(&srvth, NULL, udpserverwr, (void *)server_replyq)) + debugx(1, DBG_ERR, "pthread_create failed"); + } +} @@ -9,4 +9,6 @@ int clientradputudp(struct server *server, unsigned char *rad); void *udpclientrd(void *arg); void *udpserverrd(void *arg); -void *udpserverwr(void *arg); +void addclientudp(struct client *client); +void addserverextraudp(struct clsrvconf *conf); +void initextraudp(); @@ -98,6 +98,33 @@ char *addr2string(struct sockaddr *addr, socklen_t len) { return addr_buf[i]; } +int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only) { + int s, on = 1; + struct addrinfo *res; + + for (res = addrinfo; res; res = res->ai_next) { + if (family != AF_UNSPEC && family != res->ai_family) + continue; + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s < 0) { + debug(DBG_WARN, "bindtoaddr: socket failed"); + continue; + } + if (reuse) + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + #ifdef IPV6_V6ONLY + if (v6only) + setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); +#endif + + if (!bind(s, res->ai_addr, res->ai_addrlen)) + return s; + debug(DBG_WARN, "bindtoaddr: bind failed"); + close(s); + } + return -1; +} + int connectport(int type, char *host, char *port) { struct addrinfo hints, *res0, *res; int s = -1; @@ -1,6 +1,8 @@ #include <sys/socket.h> +#include <netdb.h> char *stringcopy(const char *s, int len); char *addr2string(struct sockaddr *addr, socklen_t len); void printfchars(char *prefixfmt, char *prefix, char *charfmt, char *chars, int len); int connectport(int type, char *host, char *port); +int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only); |