diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | radsecproxy.c | 170 | ||||
| -rw-r--r-- | tcp.c | 1 | ||||
| -rw-r--r-- | udp.c | 196 | ||||
| -rw-r--r-- | udp.h | 12 | 
6 files changed, 213 insertions, 170 deletions
| @@ -1,6 +1,6 @@  CFLAGS = -g -Wall -pedantic -pthread  LDFLAGS = -lssl -OBJ = util.o debug.o list.o gconfig.o tcp.o tls.o dtls.o radsecproxy.o +OBJ = util.o debug.o list.o gconfig.o udp.o tcp.o tls.o dtls.o radsecproxy.o  all: radsecproxy diff --git a/Makefile.am b/Makefile.am index 0bf27aa..505791b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,7 @@ radsecproxy_SOURCES = radsecproxy.c \                        util.c \                        debug.c \                        list.c \ +		      udp.c \  		      tcp.c \  		      tls.c \  		      dtls.c \ @@ -13,6 +14,7 @@ radsecproxy_SOURCES = radsecproxy.c \                        debug.h \                        util.h \                        list.h \ +		      udp.h \  		      tcp.h \  		      tls.h \  		      dtls.h diff --git a/radsecproxy.c b/radsecproxy.c index 1a9fc54..63dba64 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -64,6 +64,7 @@  #include "util.h"  #include "gconfig.h"  #include "radsecproxy.h" +#include "udp.h"  #include "tcp.h"  #include "tls.h"  #include "dtls.h" @@ -92,11 +93,6 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char  void freerealm(struct realm *realm);  void freeclsrvconf(struct clsrvconf *conf);  void freerqdata(struct request *rq); -void *udpserverrd(void *arg); -void *udpclientrd(void *arg); -int clientradputudp(struct server *server, unsigned char *rad); -X509 *verifytlscert(SSL *ssl); -int radsrv(struct request *rq);  static const struct protodefs protodefs[] = {      {   "udp", /* UDP, assuming RAD_UDP defined as 0 */ @@ -728,83 +724,6 @@ int addserver(struct clsrvconf *conf) {      return 0;  } -/* 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 */ -unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) { -    int cnt, len; -    unsigned char buf[4], *rad = NULL; -    struct sockaddr_storage from; -    socklen_t fromlen = sizeof(from); -    struct clsrvconf *p; -    struct list_node *node; -    fd_set readfds; -     -    for (;;) { -	if (rad) { -	    free(rad); -	    rad = NULL; -	} -	FD_ZERO(&readfds); -        FD_SET(s, &readfds); -	if (select(s + 1, &readfds, NULL, NULL, NULL) < 1) -	    continue; -	cnt = recvfrom(s, buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen); -	if (cnt == -1) { -	    debug(DBG_WARN, "radudpget: recv failed"); -	    continue; -	} -	if (cnt < 20) { -	    debug(DBG_WARN, "radudpget: length too small"); -	    recv(s, buf, 4, 0); -	    continue; -	} -	 -	p = find_conf(RAD_UDP, (struct sockaddr *)&from, client ? clconfs : srvconfs, NULL); -	if (!p) { -	    debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, fromlen)); -	    recv(s, buf, 4, 0); -	    continue; -	} -	 -	len = RADLEN(buf); -	if (len < 20) { -	    debug(DBG_WARN, "radudpget: length too small"); -	    recv(s, buf, 4, 0); -	    continue; -	} -	     -	rad = malloc(len); -	if (!rad) { -	    debug(DBG_ERR, "radudpget: malloc failed"); -	    recv(s, buf, 4, 0); -	    continue; -	} -	 -	cnt = recv(s, rad, len, MSG_TRUNC); -	debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen)); - -	if (cnt < len) { -	    debug(DBG_WARN, "radudpget: packet smaller than length field in radius header"); -	    continue; -	} -	if (cnt > len) -	    debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len); - -	if (client) { -	    node = list_first(p->clients); -	    *client = node ? (struct client *)node->data : addclient(p); -	    if (!*client) -		continue; -	} else if (server) -	    *server = p->servers; -	break; -    } -    if (sa) -	*sa = from; -    return rad; -} -  int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) {      int loc, i, l, n, r = 0;      char *v; @@ -993,44 +912,6 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf) {      return 1;  } -int clientradputudp(struct server *server, unsigned char *rad) { -    size_t len; -    struct sockaddr_storage sa; -    struct sockaddr *sap; -    struct clsrvconf *conf = server->conf; -    in_port_t *port = NULL; -     -    len = RADLEN(rad); -     -    if (*rad == RAD_Accounting_Request) { -	sap = (struct sockaddr *)&sa; -	memcpy(sap, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen); -    } else -	sap = conf->addrinfo->ai_addr; -     -    switch (sap->sa_family) { -    case AF_INET: -	port = &((struct sockaddr_in *)sap)->sin_port; -	break; -    case AF_INET6: -	port = &((struct sockaddr_in6 *)sap)->sin6_port; -	break; -    default: -	return 0; -    } - -    if (*rad == RAD_Accounting_Request) -	*port = htons(ntohs(*port) + 1); -     -    if (sendto(server->sock, rad, len, 0, sap, conf->addrinfo->ai_addrlen) >= 0) { -	debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, ntohs(*port)); -	return 1; -    } - -    debug(DBG_WARN, "clientradputudp: send failed"); -    return 0; -} -  int radsign(unsigned char *rad, unsigned char *sec) {      static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;      static unsigned char first = 1; @@ -2244,19 +2125,6 @@ int replyh(struct server *server, unsigned char *buf) {      return 1;  } -void *udpclientrd(void *arg) { -    struct server *server; -    unsigned char *buf; -    int *s = (int *)arg; -     -    for (;;) { -	server = NULL; -	buf = radudpget(*s, NULL, &server, NULL); -	if (!replyh(server, buf)) -	    free(buf); -    } -} -  /* code for removing state not finished */  void *clientwr(void *arg) {      struct server *server = (struct server *)arg; @@ -2429,40 +2297,6 @@ void *clientwr(void *arg) {      return NULL;  } -void *udpserverwr(void *arg) { -    struct queue *replyq = udp_server_replyq; -    struct reply *reply; -     -    for (;;) { -	pthread_mutex_lock(&replyq->mutex); -	while (!(reply = (struct reply *)list_shift(replyq->entries))) { -	    debug(DBG_DBG, "udp server writer, waiting for signal"); -	    pthread_cond_wait(&replyq->cond, &replyq->mutex); -	    debug(DBG_DBG, "udp server writer, got signal"); -	} -	pthread_mutex_unlock(&replyq->mutex); - -	if (sendto(reply->toudpsock, reply->buf, RADLEN(reply->buf), 0, -		   (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0) -	    debug(DBG_WARN, "sendudp: send failed"); -	free(reply->buf); -	free(reply); -    } -} - -void *udpserverrd(void *arg) { -    struct request rq; -    int *sp = (int *)arg; -     -    for (;;) { -	memset(&rq, 0, sizeof(struct request)); -	rq.buf = radudpget(*sp, &rq.from, NULL, &rq.fromsa); -	rq.fromudpsock = *sp; -	radsrv(&rq); -    } -    free(sp); -} -  void createlistener(uint8_t type, char *arg) {      pthread_t th;      struct clsrvconf *listenres; @@ -3755,7 +3589,7 @@ int main(int argc, char **argv) {      if (find_conf_type(RAD_UDP, clconfs, NULL)) {  	udp_server_replyq = newqueue(); -	if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL)) +	if (pthread_create(&udpserverwrth, NULL, udpserverwr, (void *)udp_server_replyq))  	    debugx(1, DBG_ERR, "pthread_create failed");  	createlisteners(RAD_UDP, options.listenudp);  	if (options.listenaccudp) @@ -25,7 +25,6 @@  #include <regex.h>  #include <pthread.h>  #include <openssl/ssl.h> -#include <openssl/err.h>  #include "debug.h"  #include "list.h"  #include "util.h" @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include <signal.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#ifdef SYS_SOLARIS9 +#include <fcntl.h> +#endif +#include <sys/time.h> +#include <sys/types.h> +#include <sys/select.h> +#include <ctype.h> +#include <sys/wait.h> +#include <arpa/inet.h> +#include <regex.h> +#include <pthread.h> +#include <openssl/ssl.h> +#include "debug.h" +#include "list.h" +#include "util.h" +#include "radsecproxy.h" +#include "tls.h" + +/* 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 */ +unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) { +    int cnt, len; +    unsigned char buf[4], *rad = NULL; +    struct sockaddr_storage from; +    socklen_t fromlen = sizeof(from); +    struct clsrvconf *p; +    struct list_node *node; +    fd_set readfds; +     +    for (;;) { +	if (rad) { +	    free(rad); +	    rad = NULL; +	} +	FD_ZERO(&readfds); +        FD_SET(s, &readfds); +	if (select(s + 1, &readfds, NULL, NULL, NULL) < 1) +	    continue; +	cnt = recvfrom(s, buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen); +	if (cnt == -1) { +	    debug(DBG_WARN, "radudpget: recv failed"); +	    continue; +	} +	if (cnt < 20) { +	    debug(DBG_WARN, "radudpget: length too small"); +	    recv(s, buf, 4, 0); +	    continue; +	} +	 +	p = client +	    ? find_clconf(RAD_UDP, (struct sockaddr *)&from, NULL) +	    : find_srvconf(RAD_UDP, (struct sockaddr *)&from, NULL); +	if (!p) { +	    debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, fromlen)); +	    recv(s, buf, 4, 0); +	    continue; +	} +	 +	len = RADLEN(buf); +	if (len < 20) { +	    debug(DBG_WARN, "radudpget: length too small"); +	    recv(s, buf, 4, 0); +	    continue; +	} +	     +	rad = malloc(len); +	if (!rad) { +	    debug(DBG_ERR, "radudpget: malloc failed"); +	    recv(s, buf, 4, 0); +	    continue; +	} +	 +	cnt = recv(s, rad, len, MSG_TRUNC); +	debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen)); + +	if (cnt < len) { +	    debug(DBG_WARN, "radudpget: packet smaller than length field in radius header"); +	    continue; +	} +	if (cnt > len) +	    debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len); + +	if (client) { +	    node = list_first(p->clients); +	    *client = node ? (struct client *)node->data : addclient(p); +	    if (!*client) +		continue; +	} else if (server) +	    *server = p->servers; +	break; +    } +    if (sa) +	*sa = from; +    return rad; +} + +int clientradputudp(struct server *server, unsigned char *rad) { +    size_t len; +    struct sockaddr_storage sa; +    struct sockaddr *sap; +    struct clsrvconf *conf = server->conf; +    in_port_t *port = NULL; +     +    len = RADLEN(rad); +     +    if (*rad == RAD_Accounting_Request) { +	sap = (struct sockaddr *)&sa; +	memcpy(sap, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen); +    } else +	sap = conf->addrinfo->ai_addr; +     +    switch (sap->sa_family) { +    case AF_INET: +	port = &((struct sockaddr_in *)sap)->sin_port; +	break; +    case AF_INET6: +	port = &((struct sockaddr_in6 *)sap)->sin6_port; +	break; +    default: +	return 0; +    } + +    if (*rad == RAD_Accounting_Request) +	*port = htons(ntohs(*port) + 1); +     +    if (sendto(server->sock, rad, len, 0, sap, conf->addrinfo->ai_addrlen) >= 0) { +	debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, ntohs(*port)); +	return 1; +    } + +    debug(DBG_WARN, "clientradputudp: send failed"); +    return 0; +} + +void *udpclientrd(void *arg) { +    struct server *server; +    unsigned char *buf; +    int *s = (int *)arg; +     +    for (;;) { +	server = NULL; +	buf = radudpget(*s, NULL, &server, NULL); +	if (!replyh(server, buf)) +	    free(buf); +    } +} + +void *udpserverrd(void *arg) { +    struct request rq; +    int *sp = (int *)arg; +     +    for (;;) { +	memset(&rq, 0, sizeof(struct request)); +	rq.buf = radudpget(*sp, &rq.from, NULL, &rq.fromsa); +	rq.fromudpsock = *sp; +	radsrv(&rq); +    } +    free(sp); +} + +void *udpserverwr(void *arg) { +    struct queue *replyq = (struct queue *)arg; +    struct reply *reply; +     +    for (;;) { +	pthread_mutex_lock(&replyq->mutex); +	while (!(reply = (struct reply *)list_shift(replyq->entries))) { +	    debug(DBG_DBG, "udp server writer, waiting for signal"); +	    pthread_cond_wait(&replyq->cond, &replyq->mutex); +	    debug(DBG_DBG, "udp server writer, got signal"); +	} +	pthread_mutex_unlock(&replyq->mutex); + +	if (sendto(reply->toudpsock, reply->buf, RADLEN(reply->buf), 0, +		   (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0) +	    debug(DBG_WARN, "sendudp: send failed"); +	free(reply->buf); +	free(reply); +    } +} @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +int clientradputudp(struct server *server, unsigned char *rad); +void *udpclientrd(void *arg); +void *udpserverrd(void *arg); +void *udpserverwr(void *arg); | 
