diff options
-rw-r--r-- | radsecproxy.c | 95 | ||||
-rw-r--r-- | radsecproxy.conf-example | 8 | ||||
-rw-r--r-- | radsecproxy.h | 2 | ||||
-rw-r--r-- | util.c | 27 |
4 files changed, 85 insertions, 47 deletions
diff --git a/radsecproxy.c b/radsecproxy.c index 59d207a..3956da0 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -61,6 +61,8 @@ static int server_udp_count = 0; static int server_tls_count = 0; static int server_count = 0; +static struct peer *tcp_server_listen; +static struct peer *udp_server_listen; static struct replyq udp_server_replyq; static int udp_server_sock = -1; static pthread_mutex_t *ssl_locks; @@ -190,12 +192,13 @@ void printauth(char *s, unsigned char *t) { printf("\n"); } -int resolvepeer(struct peer *peer) { +int resolvepeer(struct peer *peer, int ai_flags) { struct addrinfo hints, *addrinfo; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = (peer->type == 'T' ? SOCK_STREAM : SOCK_DGRAM); hints.ai_family = AF_UNSPEC; + hints.ai_flags = ai_flags; if (getaddrinfo(peer->host, peer->port, &hints, &addrinfo)) { err("resolvepeer: can't resolve %s port %s", peer->host, peer->port); return 0; @@ -226,6 +229,25 @@ int connecttoserver(struct addrinfo *addrinfo) { return s; } +int bindtoaddr(struct addrinfo *addrinfo) { + int s, on = 1; + struct addrinfo *res; + + for (res = addrinfo; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s < 0) { + err("bindtoaddr: socket failed"); + continue; + } + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (!bind(s, res->ai_addr, res->ai_addrlen)) + return s; + err("bindtoaddr: bind failed"); + close(s); + } + return -1; +} + /* returns the client with matching address, or NULL */ /* if client argument is not NULL, we only check that one client */ struct client *find_client(char type, struct sockaddr *addr, struct client *client) { @@ -1378,12 +1400,12 @@ void *udpserverrd(void *arg) { struct server *to; struct client *fr; pthread_t udpserverwrth; - - if ((udp_server_sock = bindport(SOCK_DGRAM, options.udpserverport)) < 0) { + + if ((udp_server_sock = bindtoaddr(udp_server_listen->addrinfo)) < 0) { printf("udpserverrd: socket/bind failed\n"); exit(1); } - printf("udpserverrd: listening on UDP port %s\n", options.udpserverport); + printf("udpserverrd: listening for UDP on host %s port %s\n", udp_server_listen->host, udp_server_listen->port); if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL)) errx("pthread_create failed"); @@ -1500,18 +1522,20 @@ int tlslistener() { size_t fromlen = sizeof(from); struct client *client; - if ((s = bindport(SOCK_STREAM, DEFAULT_TLS_PORT)) < 0) { + if ((s = bindtoaddr(tcp_server_listen->addrinfo)) < 0) { printf("tlslistener: socket/bind failed\n"); exit(1); } listen(s, 0); - printf("listening for incoming TLS on port %s\n", DEFAULT_TLS_PORT); + printf("listening for incoming TCP on address %s port %s\n", tcp_server_listen->host, tcp_server_listen->port); for (;;) { snew = accept(s, (struct sockaddr *)&from, &fromlen); - if (snew < 0) - errx("accept failed"); + if (snew < 0) { + err("accept failed"); + continue; + } printf("incoming TLS connection from %s\n", addr2string((struct sockaddr *)&from, fromlen)); client = find_client('T', (struct sockaddr *)&from, NULL); @@ -1730,8 +1754,8 @@ void getconfig(const char *serverfile, const char *clientfile) { } } - if ((serverfile && !resolvepeer(&server->peer)) || - (clientfile && !resolvepeer(&client->peer))) { + if ((serverfile && !resolvepeer(&server->peer, 0)) || + (clientfile && !resolvepeer(&client->peer, 0))) { printf("failed to resolve host %s port %s, exiting\n", peer->host, peer->port); exit(1); } @@ -1773,6 +1797,33 @@ void getconfig(const char *serverfile, const char *clientfile) { fclose(f); } +struct peer *server_create(char type) { + struct peer *server; + char *conf; + + server = malloc(sizeof(struct peer)); + if (!server) + errx("malloc failed"); + memset(server, 0, sizeof(struct peer)); + server->type = type; + conf = (type == 'T' ? options.listentcp : options.listenudp); + if (conf) { + parsehostport(conf, server); + if (!strcmp(server->host, "*")) { + free(server->host); + server->host = NULL; + } + } else if (type == 'T') + server->port = stringcopy(DEFAULT_TLS_PORT, 0); + else + server->port = stringcopy(options.udpserverport ? options.udpserverport : DEFAULT_UDP_PORT, 0); + if (!resolvepeer(server, AI_PASSIVE)) { + printf("failed to resolve host %s port %s, exiting\n", server->host, server->port); + exit(1); + } + return server; +} + void getmainconfig(const char *configfile) { FILE *f; char line[1024]; @@ -1826,14 +1877,18 @@ void getmainconfig(const char *configfile) { options.udpserverport = stringcopy(val, 0); continue; } - + if (!strcasecmp(opt, "ListenUDP")) { + options.listenudp = stringcopy(val, 0); + continue; + } + if (!strcasecmp(opt, "ListenTCP")) { + options.listentcp = 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 @@ -1871,10 +1926,12 @@ int main(int argc, char **argv) { /* pthread_attr_init(&joinable); */ /* pthread_attr_setdetachstate(&joinable, PTHREAD_CREATE_JOINABLE); */ - if (client_udp_count) + if (client_udp_count) { + udp_server_listen = server_create('U'); if (pthread_create(&udpserverth, NULL /*&joinable*/, udpserverrd, NULL)) errx("pthread_create failed"); - + } + if (client_tls_count || server_tls_count) ssl_ctx = ssl_init(); @@ -1882,9 +1939,11 @@ int main(int argc, char **argv) { if (pthread_create(&servers[i].clientth, NULL, clientwr, (void *)&servers[i])) errx("pthread_create failed"); - if (client_tls_count) + if (client_tls_count) { + tcp_server_listen = server_create('T'); return tlslistener(); - + } + /* just hang around doing nothing, anything to do here? */ for (;;) sleep(1000); diff --git a/radsecproxy.conf-example b/radsecproxy.conf-example index 94321c0..2648e78 100644 --- a/radsecproxy.conf-example +++ b/radsecproxy.conf-example @@ -12,5 +12,9 @@ TLSCertificateKeyFile /etc/hostcertkey/host.example.com.key.pem # Optionally specify password if key is encrypted (not very secure) TLSCertificateKeyPassword follow the white rabbit -# You can optionally specify a non-standard UDP port to listen -#UDPServerPort 1814 +# You can optionally specify addresses and ports to listen on +# Max one of each, below are just multiple examples +#ListenUDP *:1814 +#listenUDP localhost +#listenTCP 10.10.10.10:2084 +#ListenTCP [2001:700:1:7:215:f2ff:fe35:307d]:2084 diff --git a/radsecproxy.h b/radsecproxy.h index 9a71de3..e1ffb53 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -54,6 +54,8 @@ struct options { char *tlscertificatekeyfile; char *tlscertificatekeypassword; char *udpserverport; + char *listenudp; + char *listentcp; }; /* requests that our client will send */ @@ -83,33 +83,6 @@ char *addr2string(struct sockaddr *addr, socklen_t len) { return addr_buf[i]; } -int bindport(int type, char *port) { - struct addrinfo hints, *res0, *res; - int s, one = 1; - - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = type; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_PASSIVE; - - if (getaddrinfo(NULL, port, &hints, &res0) != 0) { - err("bindport: can't resolve port %s", port); - return -1; - } - for (res = res0; res; res = res->ai_next) { - s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s >= 0) { - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - if (bind(s, res->ai_addr, res->ai_addrlen) == 0) - break; - close(s); - s = -1; - } - } - freeaddrinfo(res0); - return s; -} - int connectport(int type, char *host, char *port) { struct addrinfo hints, *res0, *res; int s; |