From 9bd13dfbae29af14a218b1b5659544095b1c952b Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Tue, 23 Oct 2018 15:54:03 +0200 Subject: [PATCH] reject config if overlaping clients have different tls settings --- hostport.c | 72 ++++++++++++++++++++++++++++++++++----------------- hostport.h | 1 + radsecproxy.c | 16 +++++++++++- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/hostport.c b/hostport.c index ec6b4ef..18a570f 100644 --- a/hostport.c +++ b/hostport.c @@ -244,7 +244,7 @@ static int prefixmatch(void *a1, void *a2, uint8_t len) { return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]); } -int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport) { +int _internal_addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t prefixlen, uint8_t checkport) { struct sockaddr_in6 *sa6 = NULL; struct in_addr *a4 = NULL; struct addrinfo *res; @@ -255,36 +255,60 @@ int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkp sa6 = (struct sockaddr_in6 *)addr; if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12]; - sa6 = NULL; - } + sa6 = NULL; + } } else - a4 = &((struct sockaddr_in *)addr)->sin_addr; + a4 = &((struct sockaddr_in *)addr)->sin_addr; for (entry = list_first(hostports); entry; entry = list_next(entry)) { - hp = (struct hostportres *)entry->data; - for (res = hp->addrinfo; res; res = res->ai_next) - if (hp->prefixlen == 255) { - if ((a4 && res->ai_family == AF_INET && - !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4) && - (!checkport || ((struct sockaddr_in *)res->ai_addr)->sin_port == - ((struct sockaddr_in *)addr)->sin_port)) || - (sa6 && res->ai_family == AF_INET6 && - !memcmp(&sa6->sin6_addr, - &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16) && - (!checkport || ((struct sockaddr_in6 *)res->ai_addr)->sin6_port == - ((struct sockaddr_in6 *)addr)->sin6_port))) - return 1; - } else { - if ((a4 && res->ai_family == AF_INET && - prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, hp->prefixlen)) || - (sa6 && res->ai_family == AF_INET6 && - prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, hp->prefixlen))) - return 1; - } + hp = (struct hostportres *)entry->data; + for (res = hp->addrinfo; res; res = res->ai_next) { + if (hp->prefixlen >= (res->ai_family == AF_INET ? 32 : 128) && prefixlen >= (a4 ? 32 : 128)) { + if ((a4 && res->ai_family == AF_INET && + !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4) && + (!checkport || ((struct sockaddr_in *)res->ai_addr)->sin_port == + ((struct sockaddr_in *)addr)->sin_port)) || + + (sa6 && res->ai_family == AF_INET6 && + !memcmp(&sa6->sin6_addr, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16) && + (!checkport || ((struct sockaddr_in6 *)res->ai_addr)->sin6_port == + ((struct sockaddr_in6 *)addr)->sin6_port))) + + return 1; + } else if (hp->prefixlen <= prefixlen) { + if ((a4 && res->ai_family == AF_INET && + prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, hp->prefixlen)) || + (sa6 && res->ai_family == AF_INET6 && + prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, hp->prefixlen))) + + return 1; + } + } } return 0; } +int hostportmatches(struct list *hostports, struct list *matchhostports, uint8_t checkport) { + struct list_node *entry; + struct hostportres *match; + struct addrinfo *res; + + for (entry = list_first(matchhostports); entry; entry = list_next(entry)) { + match = (struct hostportres *)entry->data; + + for (res = match->addrinfo; res; res = res->ai_next) { + if (_internal_addressmatches(hostports, res->ai_addr, match->prefixlen, checkport)) + return 1; + } + } + return 0; +} + +int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport) { + return _internal_addressmatches(hostports, addr, 255, checkport); +} + int connecttcphostlist(struct list *hostports, struct addrinfo *src) { int s; struct list_node *entry; diff --git a/hostport.h b/hostport.h index 1bfeee4..7d0ae6a 100644 --- a/hostport.h +++ b/hostport.h @@ -16,6 +16,7 @@ void freehostports(struct list *hostports); int resolvehostport(struct hostportres *hp, int af, int socktype, uint8_t passive); int resolvehostports(struct list *hostports, int af, int socktype); struct addrinfo *resolvepassiveaddrinfo(char *hostport, int af, char *default_port, int socktype); +int hostportmatches(struct list *hostports, struct list *matchhostports, uint8_t checkport); int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport); int connecttcphostlist(struct list *hostports, struct addrinfo *src); diff --git a/radsecproxy.c b/radsecproxy.c index 1c6fd54..e8d7527 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -2758,10 +2758,11 @@ int config_hostaf(const char *desc, int ipv4only, int ipv6only, int *af) { } int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { - struct clsrvconf *conf; + struct clsrvconf *conf, *existing; char *conftype = NULL, *rewriteinalias = NULL; long int dupinterval = LONG_MIN, addttl = LONG_MIN; uint8_t ipv4only = 0, ipv6only = 0; + struct list_node *entry; debug(DBG_DBG, "confclient_cb called for %s", block); @@ -2874,6 +2875,19 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char debugx(1, DBG_ERR, "malloc failed"); } + if (conf->tlsconf) { + for (entry = list_first(clconfs); entry; entry = list_next(entry)) { + existing = (struct clsrvconf *)entry->data; + + if (existing->type == conf->type && + existing->tlsconf != conf->tlsconf && + hostportmatches(existing->hostports, conf->hostports, 0)) { + + debugx(1, DBG_ERR, "error in block %s, overlapping clients must reference the same tls block", block); + } + } + } + conf->lock = malloc(sizeof(pthread_mutex_t)); if (!conf->lock) debugx(1, DBG_ERR, "malloc failed");