Skip to content

Commit

Permalink
reject config if overlaping clients have different tls settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabian Mauchle committed Oct 23, 2018
1 parent 212ac5a commit 9bd13df
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 25 deletions.
72 changes: 48 additions & 24 deletions hostport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions hostport.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
16 changes: 15 additions & 1 deletion radsecproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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");
Expand Down

0 comments on commit 9bd13df

Please sign in to comment.