]> git.pld-linux.org Git - packages/radsecproxy.git/blob - git.patch
- sync with upstream git
[packages/radsecproxy.git] / git.patch
1 diff --git a/ChangeLog b/ChangeLog
2 index c1943fb..d6552db 100644
3 --- a/ChangeLog
4 +++ b/ChangeLog
5 @@ -1,3 +1,20 @@
6 +unreleased changes
7 +       New features:
8 +       - Optionally log accounting requests when respoinding directly (#72)
9 +       - SNI support for outgoing connections (#90)
10 +
11 +       Misc:
12 +       - Don't require server type to be set by dyndisc scripts
13 +       - OpenSSL 3.0 compatibility (#70)
14 +       
15 +       Bug Fixes:
16 +       - Fix refused startup with openssl <1.1 (#82)
17 +       - Fix compiler issue for Fedora 33 on s390x (#84)
18 +       - Fix small memory leak in config parser
19 +       - Fix lazy certificate check when connecting to TLS servers
20 +       - Fix connect is aborted if first host in list has invalid certificate
21 +       - Fix setstacksize for glibc 2.34 (#91)
22 +
23  2021-05-28 1.9.0
24         New features:
25         - Accept multiple source* configs for IPv4/v6
26 diff --git a/README b/README
27 index 20700fa..5074c77 100644
28 --- a/README
29 +++ b/README
30 @@ -8,11 +8,12 @@ flexible, while at the same time to be small, efficient and easy to configure.
31  Official packages are available:
32  
33  Debian: apt-get install radsecproxy
34 +CentOS/RHEL/Rocky: yum install epel-release; yum install radsecproxy
35  Fedora: dnf install radsecproxy
36  FreeBSD: pkg install radsecproxy
37  NetBSD: pkgin install radsecproxy
38  
39 -Or built it from this rouce on most Unix like systems by simply typing
40 +Or built it from this source on most Unix like systems by simply typing
41  
42      ./configure && make
43  
44 diff --git a/configure.ac b/configure.ac
45 index 630fcac..d486e47 100644
46 --- a/configure.ac
47 +++ b/configure.ac
48 @@ -11,6 +11,12 @@ AC_PROG_RANLIB
49  AC_CHECK_FUNCS([mallopt])
50  AC_REQUIRE_AUX_FILE([tap-driver.sh])
51  
52 +m4_version_prereq(2.70, [], [AC_PROG_CC_C99])
53 +if test "$ac_cv_prog_cc_c99" = "no"; then
54 +  echo "requires C99 compatible compiler"
55 +  exit -1
56 +fi
57 +
58  udp=yes
59  AC_ARG_ENABLE(udp,
60    [  --enable-udp whether to enable UDP transport: yes/no; default yes ],
61 diff --git a/dtls.c b/dtls.c
62 index 09aa9ee..15835d6 100644
63 --- a/dtls.c
64 +++ b/dtls.c
65 @@ -142,6 +142,7 @@ int dtlsread(SSL *ssl, unsigned char *buf, int num, int timeout, pthread_mutex_t
66                      continue;
67                  case SSL_ERROR_ZERO_RETURN:
68                      debug(DBG_DBG, "dtlsread: got ssl shutdown");
69 +                    /* fallthrough */
70                  default:
71                      while ((error = ERR_get_error()))
72                          debug(DBG_ERR, "dtlsread: SSL: %s", ERR_error_string(error, NULL));
73 @@ -305,10 +306,11 @@ void *dtlsservernew(void *arg) {
74      struct timeval timeout;
75      struct addrinfo tmpsrvaddr;
76      char tmp[INET6_ADDRSTRLEN], *subj;
77 +    struct hostportres *hp;
78  
79      debug(DBG_WARN, "dtlsservernew: incoming DTLS connection from %s", addr2string((struct sockaddr *)&params->addr, tmp, sizeof(tmp)));
80  
81 -    conf = find_clconf(handle, (struct sockaddr *)&params->addr, NULL);
82 +    conf = find_clconf(handle, (struct sockaddr *)&params->addr, NULL, &hp);
83      if (!conf)
84          goto exit;
85  
86 @@ -342,7 +344,7 @@ void *dtlsservernew(void *arg) {
87      accepted_tls = conf->tlsconf;
88  
89      while (conf) {
90 -        if (accepted_tls == conf->tlsconf && verifyconfcert(cert, conf)) {
91 +        if (accepted_tls == conf->tlsconf && verifyconfcert(cert, conf, NULL)) {
92              subj = getcertsubject(cert);
93              if(subj) {
94                  debug(DBG_WARN, "dtlsservernew: DTLS connection from %s, client %s, subject %s up",
95 @@ -362,9 +364,10 @@ void *dtlsservernew(void *arg) {
96              }
97              goto exit;
98          }
99 -        conf = find_clconf(handle, (struct sockaddr *)&params->addr, &cur);
100 +        conf = find_clconf(handle, (struct sockaddr *)&params->addr, &cur, &hp);
101      }
102 -    debug(DBG_WARN, "dtlsservernew: ignoring request, no matching TLS client");
103 +    debug(DBG_WARN, "dtlsservernew: ignoring request, no matching TLS client for %s", 
104 +        addr2string((struct sockaddr *)&params->addr, tmp, sizeof(tmp)));
105  
106      if (cert)
107      X509_free(cert);
108 @@ -467,7 +470,7 @@ void *dtlslistener(void *arg) {
109              continue;
110          }
111  
112 -        conf = find_clconf(handle, (struct sockaddr *)&from, NULL);
113 +        conf = find_clconf(handle, (struct sockaddr *)&from, NULL, NULL);
114          if (!conf) {
115              debug(DBG_INFO, "dtlslistener: got UDP from unknown peer %s, ignoring", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)));
116              if (recv(s, buf, 4, 0) == -1)
117 @@ -486,6 +489,7 @@ void *dtlslistener(void *arg) {
118              ssl = SSL_new(ctx);
119              if (!ssl) {
120                  pthread_mutex_unlock(&conf->tlsconf->lock);
121 +                debug(DBG_ERR, "dtlslistener: failed to create SSL connection");
122                  continue;
123              }
124              bio = BIO_new_dgram(s, BIO_NOCLOSE);
125 @@ -514,12 +518,28 @@ void *dtlslistener(void *arg) {
126              } else {
127                  free(params);
128              }
129 +        } else {
130 +            unsigned long error;
131 +            while ((error = ERR_get_error()))
132 +                debug(DBG_ERR, "dtlslistener: DTLS_listen failed: %s", ERR_error_string(error, NULL));
133 +            debug(DBG_ERR, "dtlslistener: DTLS_listen failed from %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)));
134          }
135          pthread_mutex_unlock(&conf->tlsconf->lock);
136      }
137      return NULL;
138  }
139  
140 +static void cleanup_connection(struct server *server) {
141 +    if (server->ssl)
142 +        SSL_shutdown(server->ssl);
143 +    if (server->sock >= 0)
144 +        close(server->sock);
145 +    server->sock = -1;
146 +    if (server->ssl)
147 +        SSL_free(server->ssl);
148 +    server->ssl = NULL;
149 +}
150 +
151  int dtlsconnect(struct server *server, int timeout, char *text) {
152      struct timeval socktimeout, now, start;
153      time_t wait;
154 @@ -531,6 +551,7 @@ int dtlsconnect(struct server *server, int timeout, char *text) {
155      BIO *bio;
156      struct addrinfo *source = NULL;
157      char *subj;
158 +    struct list_node *entry;
159  
160      debug(DBG_DBG, "dtlsconnect: called from %s", text);
161      pthread_mutex_lock(&server->lock);
162 @@ -540,8 +561,6 @@ int dtlsconnect(struct server *server, int timeout, char *text) {
163  
164      pthread_mutex_unlock(&server->lock);
165  
166 -    hp = (struct hostportres *)list_first(server->conf->hostports)->data;
167 -
168      if(server->conf->source) {
169          source = resolvepassiveaddrinfo(server->conf->source, AF_UNSPEC, NULL, protodefs.socktype);
170          if(!source)
171 @@ -552,13 +571,7 @@ int dtlsconnect(struct server *server, int timeout, char *text) {
172  
173      for (;;) {
174          /* ensure previous connection is properly closed */
175 -        if (server->ssl)
176 -            SSL_shutdown(server->ssl);
177 -        if (server->sock >= 0)
178 -            close(server->sock);
179 -        if (server->ssl)
180 -            SSL_free(server->ssl);
181 -        server->ssl = NULL;
182 +        cleanup_connection(server);
183  
184          wait = connect_wait(start, server->connecttime, firsttry);
185          gettimeofday(&now, NULL);
186 @@ -567,55 +580,84 @@ int dtlsconnect(struct server *server, int timeout, char *text) {
187              if (source) freeaddrinfo(source);
188              return 0;
189          }
190 -        debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait);
191 +        if (wait) debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait);
192          sleep(wait);
193          firsttry = 0;
194  
195 -        debug(DBG_INFO, "dtlsconnect: connecting to %s port %s", hp->host, hp->port);
196 +        for (entry = list_first(server->conf->hostports); entry; entry = list_next(entry)) {
197 +            hp = (struct hostportres *)entry->data;
198 +            debug(DBG_INFO, "dtlsconnect: trying to open DTLS connection to server %s (%s port %s)", server->conf->name, hp->host, hp->port);
199 +            if ((server->sock = bindtoaddr(source ? source : srcres, hp->addrinfo->ai_family, 0)) < 0) {
200 +                debug(DBG_ERR, "dtlsconnect: faild to bind socket for server %s (%s port %s)", server->conf->name, hp->host, hp->port);
201 +                goto concleanup;
202 +            }
203 +            if (connect(server->sock, hp->addrinfo->ai_addr, hp->addrinfo->ai_addrlen)) {
204 +                debug(DBG_ERR, "dtlsconnect: faild to connect socket for server %s (%s port %s)", server->conf->name, hp->host, hp->port);
205 +                goto concleanup;
206 +            }
207  
208 -        if ((server->sock = bindtoaddr(source ? source : srcres, hp->addrinfo->ai_family, 0)) < 0)
209 -            continue;
210 -        if (connect(server->sock, hp->addrinfo->ai_addr, hp->addrinfo->ai_addrlen))
211 -            continue;
212 +            pthread_mutex_lock(&server->conf->tlsconf->lock);
213 +            if (!(ctx = tlsgetctx(handle, server->conf->tlsconf))){
214 +                pthread_mutex_unlock(&server->conf->tlsconf->lock);
215 +                debug(DBG_ERR, "dtlsconnect: failed to get TLS context for server %s", server->conf->name);
216 +                goto concleanup;
217 +            }
218  
219 -        pthread_mutex_lock(&server->conf->tlsconf->lock);
220 -        if (!(ctx = tlsgetctx(handle, server->conf->tlsconf))){
221 +            server->ssl = SSL_new(ctx);
222              pthread_mutex_unlock(&server->conf->tlsconf->lock);
223 -            continue;
224 -        }
225 +            if (!server->ssl) {
226 +                debug(DBG_ERR, "dtlsconnect: failed to create SSL conneciton for server %s", server->conf->name);
227 +                goto concleanup;
228 +            }
229  
230 -        server->ssl = SSL_new(ctx);
231 -        pthread_mutex_unlock(&server->conf->tlsconf->lock);
232 -        if (!server->ssl)
233 -            continue;
234 +            if (server->conf->sni) {
235 +                struct in6_addr tmp;
236 +                char *servername = server->conf->sniservername ? server->conf->sniservername : 
237 +                    (inet_pton(AF_INET, hp->host, &tmp) || inet_pton(AF_INET6, hp->host, &tmp)) ? NULL : hp->host;
238 +                if (servername && !tlssetsni(server->ssl, servername)) {
239 +                    debug(DBG_ERR, "tlsconnect: set SNI %s failed", servername);
240 +                    goto concleanup;
241 +                }
242 +            }
243  
244 -        bio = BIO_new_dgram(server->sock, BIO_CLOSE);
245 -        BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, hp->addrinfo->ai_addr);
246 -        SSL_set_bio(server->ssl, bio, bio);
247 -        if (sslconnecttimeout(server->ssl, 5) <= 0) {
248 -            while ((error = ERR_get_error()))
249 -                debug(DBG_ERR, "dtlsconnect: SSL connect to %s failed: %s", server->conf->name, ERR_error_string(error, NULL));
250 -            debug(DBG_ERR, "dtlsconnect: SSL connect to %s failed", server->conf->name);
251 -            continue;
252 -        }
253 -        socktimeout.tv_sec = 5;
254 -        socktimeout.tv_usec = 0;
255 -        if (BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &socktimeout) == -1)
256 -            debug(DBG_WARN, "dtlsconnect: BIO_CTRL_DGRAM_SET_RECV_TIMEOUT failed");
257 +            bio = BIO_new_dgram(server->sock, BIO_CLOSE);
258 +            BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, hp->addrinfo->ai_addr);
259 +            SSL_set_bio(server->ssl, bio, bio);
260 +            if (sslconnecttimeout(server->ssl, 5) <= 0) {
261 +                while ((error = ERR_get_error()))
262 +                    debug(DBG_ERR, "dtlsconnect: SSL connect to %s failed: %s", server->conf->name, ERR_error_string(error, NULL));
263 +                debug(DBG_ERR, "dtlsconnect: SSL connect to %s (%s port %s) failed", server->conf->name, hp->host, hp->port);
264 +                goto concleanup;
265 +            }
266 +            socktimeout.tv_sec = 5;
267 +            socktimeout.tv_usec = 0;
268 +            if (BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &socktimeout) == -1)
269 +                debug(DBG_WARN, "dtlsconnect: BIO_CTRL_DGRAM_SET_RECV_TIMEOUT failed");
270 +
271 +            cert = verifytlscert(server->ssl);
272 +            if (!cert) {
273 +                debug(DBG_ERR, "tlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port);
274 +                goto concleanup;
275 +            }
276  
277 -        cert = verifytlscert(server->ssl);
278 -        if (!cert)
279 -            continue;
280 -        if (verifyconfcert(cert, server->conf)) {
281 -            subj = getcertsubject(cert);
282 -            if(subj) {
283 -                debug(DBG_WARN, "dtlsconnect: DTLS connection to %s, subject %s up", server->conf->name, subj);
284 -                free(subj);
285 +            if (verifyconfcert(cert, server->conf, hp)) {
286 +                subj = getcertsubject(cert);
287 +                if(subj) {
288 +                    debug(DBG_WARN, "dtlsconnect: DTLS connection to %s (%s port %s), subject %s up", server->conf->name, hp->host, hp->port, subj);
289 +                    free(subj);
290 +                }
291 +                X509_free(cert);
292 +                break;
293 +            } else {
294 +                debug(DBG_ERR, "tlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port);
295              }
296              X509_free(cert);
297 -            break;
298 +
299 +concleanup:
300 +            /* ensure previous connection is properly closed */
301 +            cleanup_connection(server);
302          }
303 -        X509_free(cert);
304 +        if (server->ssl) break;
305      }
306  
307      pthread_mutex_lock(&server->lock);
308 diff --git a/hostport.c b/hostport.c
309 index 6408505..d0651d4 100644
310 --- a/hostport.c
311 +++ b/hostport.c
312 @@ -222,7 +222,7 @@ int resolvehostports(struct list *hostports, int af, int socktype) {
313  }
314  
315  struct addrinfo *resolvepassiveaddrinfo(char **hostport, int af, char *default_port, int socktype) {
316 -    struct addrinfo *ai = NULL, *last_ai;
317 +    struct addrinfo *ai = NULL, *last_ai = NULL;
318      int i;
319      char *any[2] = {"*", NULL};
320  
321 @@ -258,7 +258,7 @@ static int prefixmatch(void *a1, void *a2, uint8_t len) {
322      return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]);
323  }
324  
325 -int _internal_addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t prefixlen, uint8_t checkport) {
326 +int _internal_addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t prefixlen, uint8_t checkport, struct hostportres **hpreturn) {
327      struct sockaddr_in6 *sa6 = NULL;
328      struct in_addr *a4 = NULL;
329      struct addrinfo *res;
330 @@ -287,16 +287,20 @@ int _internal_addressmatches(struct list *hostports, struct sockaddr *addr, uint
331                      !memcmp(&sa6->sin6_addr,
332                      &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16) &&
333                      (!checkport || ((struct sockaddr_in6 *)res->ai_addr)->sin6_port ==
334 -                    ((struct sockaddr_in6 *)addr)->sin6_port)))
335 +                    ((struct sockaddr_in6 *)addr)->sin6_port))) {
336  
337 +                    if (hpreturn) *hpreturn = hp;
338                      return 1;
339 +                }
340              } else if (hp->prefixlen <= prefixlen) {
341                  if ((a4 && res->ai_family == AF_INET &&
342                      prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, hp->prefixlen)) ||
343                      (sa6 && res->ai_family == AF_INET6 &&
344 -                    prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, hp->prefixlen)))
345 +                    prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, hp->prefixlen))) {
346  
347 +                    if (hpreturn) *hpreturn = hp;
348                      return 1;
349 +                }
350              }
351          }
352      }
353 @@ -312,18 +316,18 @@ int hostportmatches(struct list *hostports, struct list *matchhostports, uint8_t
354          match = (struct hostportres *)entry->data;
355  
356          for (res = match->addrinfo; res; res = res->ai_next) {
357 -            if (_internal_addressmatches(hostports, res->ai_addr, match->prefixlen, checkport))
358 +            if (_internal_addressmatches(hostports, res->ai_addr, match->prefixlen, checkport, NULL))
359                  return 1;
360          }
361      }
362      return 0;
363  }
364  
365 -int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport) {
366 -    return _internal_addressmatches(hostports, addr, 255, checkport);
367 +int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport, struct hostportres **hp) {
368 +    return _internal_addressmatches(hostports, addr, 255, checkport, hp);
369  }
370  
371 -int connecttcphostlist(struct list *hostports,  struct addrinfo *src) {
372 +int connecttcphostlist(struct list *hostports,  struct addrinfo *src, struct hostportres** hpreturn) {
373      int s;
374      struct list_node *entry;
375      struct hostportres *hp = NULL;
376 @@ -333,6 +337,7 @@ int connecttcphostlist(struct list *hostports,  struct addrinfo *src) {
377         debug(DBG_WARN, "connecttcphostlist: trying to open TCP connection to %s port %s", hp->host, hp->port);
378         if ((s = connecttcp(hp->addrinfo, src, list_count(hostports) > 1 ? 5 : 30)) >= 0) {
379             debug(DBG_WARN, "connecttcphostlist: TCP connection to %s port %s up", hp->host, hp->port);
380 +        if (hpreturn) *hpreturn = hp;
381             return s;
382         }
383      }
384 diff --git a/hostport.h b/hostport.h
385 index 9069ecd..a554a77 100644
386 --- a/hostport.h
387 +++ b/hostport.h
388 @@ -2,6 +2,9 @@
389   * Copyright (c) 2012, NORDUnet A/S */
390  /* See LICENSE for licensing information. */
391  
392 +#ifndef _HOSTPORT_H
393 +#define _HOSTPORT_H
394 +
395  struct hostportres {
396      char *host;
397      char *port;
398 @@ -17,9 +20,10 @@ int resolvehostport(struct hostportres *hp, int af, int socktype, uint8_t passiv
399  int resolvehostports(struct list *hostports, int af, int socktype);
400  struct addrinfo *resolvepassiveaddrinfo(char **hostport, int af, char *default_port, int socktype);
401  int hostportmatches(struct list *hostports, struct list *matchhostports, uint8_t checkport);
402 -int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport);
403 -int connecttcphostlist(struct list *hostports,  struct addrinfo *src);
404 +int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport, struct hostportres **hp);
405 +int connecttcphostlist(struct list *hostports,  struct addrinfo *src, struct hostportres **hpreturn);
406  
407 +#endif /* _HOSTPORT_H */
408  /* Local Variables: */
409  /* c-file-style: "stroustrup" */
410  /* End: */
411 diff --git a/list.h b/list.h
412 index f015b9d..c8c4531 100644
413 --- a/list.h
414 +++ b/list.h
415 @@ -35,7 +35,7 @@ int list_push(struct list *list, void *data);
416  /* removes first entry from list and returns data */
417  void *list_shift(struct list *list);
418  
419 -/* removes first entry with matching data pointer */
420 +/* removes all entries with matching data pointer */
421  void list_removedata(struct list *list, void *data);
422  
423  /* returns first node */
424 diff --git a/raddict.h b/raddict.h
425 new file mode 100644
426 index 0000000..8a9c598
427 --- /dev/null
428 +++ b/raddict.h
429 @@ -0,0 +1,42 @@
430 +#ifndef _RADDICT_H
431 +#define _RADDICT_H
432 +
433 +const char* RAD_Attr_Acct_Terminate_Cause_Dict[] = {
434 +        [1] = "User-Request",
435 +        "Lost-Carrier",
436 +        "Lost-Service",
437 +        "Idle-Timeout",
438 +        "Session-Timeout",
439 +        "Admin-Reset",
440 +        "Admin-Reboot",
441 +        "Port-Error",
442 +        "NAS-Error",
443 +        "NAS-Request",
444 +        "NAS-Reboot",
445 +        "Port-Unneeded",
446 +        "Port-Preempted",
447 +        "Port-Suspended",
448 +        "Service-Unavailable",
449 +        "Callback",
450 +        "User-Error",
451 +        "Host-Request",
452 +};
453 +
454 +const char* RAD_Attr_Acct_Status_Type_Dict[] = {
455 +        [1] = "Start",
456 +        [2] = "Stop",
457 +        [3] = "Interim-Update",
458 +        [7] = "Accounting-On",
459 +        [8] = "Accounting-Off",
460 +        [9] = "Tunnel-Start",
461 +        [10] = "Tunnel-Stop",
462 +        [11] = "Tunnel-Reject",
463 +        [12] = "Tunnel-Link-Start",
464 +        [13] = "Tunnel-Link-Stop",
465 +        [14] = "Tunnel-Link-Reject",
466 +        [15] = "Failed",
467 +};
468 +
469 +#define RAD_Attr_Dict_Undef "UNKNOWN"
470 +
471 +#endif /*_RADDICT_H*/
472 diff --git a/radmsg.c b/radmsg.c
473 index 5f49237..afd7c60 100644
474 --- a/radmsg.c
475 +++ b/radmsg.c
476 @@ -15,6 +15,8 @@
477  #include <pthread.h>
478  #include <nettle/hmac.h>
479  #include <openssl/rand.h>
480 +#include "raddict.h"
481 +#include "util.h"
482  
483  #define RADLEN(x) ntohs(((uint16_t *)(x))[1])
484  
485 @@ -414,6 +416,28 @@ int resizeattr(struct tlv *attr, uint8_t newlen) {
486      return 0;
487  }
488  
489 +const char* attrval2strdict(struct tlv *attr) {
490 +    uint32_t val;
491 +
492 +    if(!attr) return NULL;
493 +    val = tlv2longint(attr);
494 +    switch (attr->t) {
495 +        case RAD_Attr_Acct_Status_Type:
496 +            if(val < sizeof(RAD_Attr_Acct_Status_Type_Dict)/sizeof(RAD_Attr_Acct_Status_Type_Dict[0]))
497 +                return RAD_Attr_Acct_Status_Type_Dict[val] ? RAD_Attr_Acct_Status_Type_Dict[val] : RAD_Attr_Dict_Undef;
498 +            break;
499 +
500 +        case RAD_Attr_Acct_Terminate_Cause:
501 +            if(val < sizeof(RAD_Attr_Acct_Terminate_Cause_Dict)/sizeof(RAD_Attr_Acct_Terminate_Cause_Dict[0]))
502 +                return RAD_Attr_Acct_Terminate_Cause_Dict[val] ? RAD_Attr_Acct_Terminate_Cause_Dict[val] : RAD_Attr_Dict_Undef;
503 +            break;
504 +
505 +        default:
506 +            break;
507 +    }
508 +    return NULL;
509 +}
510 +
511  /* Local Variables: */
512  /* c-file-style: "stroustrup" */
513  /* End: */
514 diff --git a/radmsg.h b/radmsg.h
515 index 1738c8e..634cf13 100644
516 --- a/radmsg.h
517 +++ b/radmsg.h
518 @@ -21,16 +21,37 @@
519  #define RAD_Attr_User_Name 1
520  #define RAD_Attr_User_Password 2
521  #define RAD_Attr_CHAP_Password 3
522 +#define RAD_Attr_NAS_IP_Address 4
523 +#define RAD_Attr_Framed_IP_Address 8
524  #define RAD_Attr_Reply_Message 18
525  #define RAD_Attr_Vendor_Specific 26
526 +#define RAD_Attr_Called_Station_Id 30
527  #define RAD_Attr_Calling_Station_Id 31
528  #define RAD_Attr_Proxy_State 33
529 +#define RAD_Attr_Acct_Status_Type 40
530 +#define RAD_Attr_Acct_Input_Octets 42
531 +#define RAD_Attr_Acct_Output_Octets 43
532 +#define RAD_Attr_Acct_Session_Id 44
533 +#define RAD_Attr_Acct_Session_Time 46
534 +#define RAD_Attr_Acct_Input_Packets 47
535 +#define RAD_Attr_Acct_Output_Packets 48
536 +#define RAD_Attr_Acct_Terminate_Cause 49
537 +#define RAD_Attr_Event_Timestamp 55
538  #define RAD_Attr_CHAP_Challenge 60
539  #define RAD_Attr_Tunnel_Password 69
540  #define RAD_Attr_Message_Authenticator 80
541  #define RAD_Attr_CUI 89
542  #define RAD_Attr_Operator_Name 126
543  
544 +#define RAD_Acct_Status_Start 1
545 +#define RAD_Acct_Status_Stop 2
546 +#define RAD_Acct_Status_Alive 3
547 +#define RAD_Acct_Status_Interim_Update 3
548 +#define RAD_Acct_Status_Accounting_On 7
549 +#define RAD_Acct_Status_Accounting_Off 8
550 +#define RAD_Acct_Status_Failed 15
551 +
552 +
553  #define RAD_VS_ATTR_MS_MPPE_Send_Key 16
554  #define RAD_VS_ATTR_MS_MPPE_Recv_Key 17
555  
556 @@ -63,6 +84,16 @@ int attrvalidate(unsigned char *attrs, int length);
557  struct tlv *makevendortlv(uint32_t vendor, struct tlv *attr);
558  int resizeattr(struct tlv *attr, uint8_t newlen);
559  
560 +/**
561 + * convert the attribute value to its string representation form the dictionary 
562 + * (see raddict.h)
563 + * 
564 + * @param attr the attribute to convert
565 + * @return the string representation or NULL, if the attribute/value is not in the 
566 + * dictionary
567 + */
568 +const char* attrval2strdict(struct tlv *attr);
569 +
570  #endif /*_RADMSG_H*/
571  
572  /* Local Variables: */
573 diff --git a/radsecproxy.c b/radsecproxy.c
574 index c755acb..75f5ef3 100644
575 --- a/radsecproxy.c
576 +++ b/radsecproxy.c
577 @@ -121,13 +121,13 @@ int prefixmatch(void *a1, void *a2, uint8_t len) {
578  }
579  
580  /* returns next config with matching address, or NULL */
581 -struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *confs, struct list_node **cur, uint8_t server_p) {
582 +struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *confs, struct list_node **cur, uint8_t server_p, struct hostportres **hp) {
583      struct list_node *entry;
584      struct clsrvconf *conf;
585  
586      for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) {
587         conf = (struct clsrvconf *)entry->data;
588 -       if (conf->type == type && addressmatches(conf->hostports, addr, server_p)) {
589 +       if (conf->type == type && addressmatches(conf->hostports, addr, server_p, hp)) {
590             if (cur)
591                 *cur = entry;
592             return conf;
593 @@ -136,12 +136,12 @@ struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *co
594      return NULL;
595  }
596  
597 -struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur) {
598 -    return find_conf(type, addr, clconfs, cur, 0);
599 +struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur, struct hostportres **hp) {
600 +    return find_conf(type, addr, clconfs, cur, 0, hp);
601  }
602  
603  struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur) {
604 -    return find_conf(type, addr, srvconfs, cur, 1);
605 +    return find_conf(type, addr, srvconfs, cur, 1, NULL);
606  }
607  
608  /* returns next config of given type, or NULL */
609 @@ -1241,6 +1241,49 @@ void rmclientrq(struct request *rq, uint8_t id) {
610      }
611  }
612  
613 +static void log_accounting_resp(struct client *from, struct radmsg *msg, char *user) {
614 +    char tmp[INET6_ADDRSTRLEN];
615 +    const char* status_type = attrval2strdict(radmsg_gettype(msg, RAD_Attr_Acct_Status_Type));
616 +    char* nas_ip_address = tlv2ipv4addr(radmsg_gettype(msg, RAD_Attr_NAS_IP_Address));
617 +    char* framed_ip_address = tlv2ipv4addr(radmsg_gettype(msg, RAD_Attr_Framed_IP_Address));
618 +
619 +    time_t event_timestamp_i = tlv2longint(radmsg_gettype(msg, RAD_Attr_Event_Timestamp));
620 +    char event_timestamp[32]; /* timestamp should be at most 21 bytes, leave a few spare */
621 +
622 +    uint8_t *session_id = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Acct_Session_Id));
623 +    uint8_t *called_station_id = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Called_Station_Id));
624 +    uint8_t *calling_station_id = radattr2ascii(radmsg_gettype(msg, RAD_Attr_Calling_Station_Id));
625 +    const char* terminate_cause = attrval2strdict(radmsg_gettype(msg, RAD_Attr_Acct_Terminate_Cause));
626 +
627 +    strftime(event_timestamp, sizeof(event_timestamp), "%FT%TZ", gmtime(&event_timestamp_i));
628 +
629 +    debug(DBG_NOTICE, "Accounting %s (id %d) at %s from client %s (%s): { SID=%s, User-Name=%s, Ced-S-Id=%s, Cing-S-Id=%s, NAS-IP=%s, Framed-IP=%s, Sess-Time=%u, In-Packets=%u, In-Octets=%u, Out-Packets=%u, Out-Octets=%u, Terminate-Cause=%s }",
630 +        status_type ? status_type : "UNKNOWN",
631 +        msg->id,
632 +        event_timestamp_i ? event_timestamp : "UNKNOWN",
633 +        from->conf->name,
634 +        addr2string(from->addr, tmp, sizeof(tmp)),
635 +
636 +        session_id ? session_id : (uint8_t*)"",
637 +        user,
638 +        called_station_id ? called_station_id : (uint8_t*)"",
639 +        calling_station_id ? calling_station_id : (uint8_t*)"",
640 +        nas_ip_address ? nas_ip_address : "0.0.0.0",
641 +        framed_ip_address ? framed_ip_address : "0.0.0.0",
642 +        tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Session_Time)),
643 +        tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Input_Packets)),
644 +        tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Input_Octets)),
645 +        tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Output_Packets)),
646 +        tlv2longint(radmsg_gettype(msg, RAD_Attr_Acct_Output_Octets)),
647 +        terminate_cause ? terminate_cause : ""
648 +    );
649 +    free(framed_ip_address);
650 +    free(nas_ip_address);
651 +    free(session_id);
652 +    free(called_station_id);
653 +    free(calling_station_id);
654 +}
655 +
656  /* Called from server readers, handling incoming requests from
657   * clients. */
658  /* returns 0 if validation/authentication fails, else 1 */
659 @@ -1321,13 +1364,15 @@ int radsrv(struct request *rq) {
660      }
661  
662      if (!to) {
663 -       if (realm->message && msg->code == RAD_Access_Request) {
664 -           debug(DBG_INFO, "radsrv: sending %s (id %d) to %s (%s) for %s", radmsgtype2string(RAD_Access_Reject), msg->id, from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)), userascii);
665 -           respond(rq, RAD_Access_Reject, realm->message, 1, 1);
666 -       } else if (realm->accresp && msg->code == RAD_Accounting_Request) {
667 -           respond(rq, RAD_Accounting_Response, NULL, 1, 0);
668 -       }
669 -       goto exit;
670 +        if (realm->message && msg->code == RAD_Access_Request) {
671 +            debug(DBG_INFO, "radsrv: sending %s (id %d) to %s (%s) for %s", radmsgtype2string(RAD_Access_Reject), msg->id, from->conf->name, addr2string(from->addr, tmp, sizeof(tmp)), userascii);
672 +            respond(rq, RAD_Access_Reject, realm->message, 1, 1);
673 +        } else if (realm->accresp && msg->code == RAD_Accounting_Request) {
674 +            if (realm->acclog) 
675 +                log_accounting_resp(from, msg, (char *)userascii);
676 +            respond(rq, RAD_Accounting_Response, NULL, 1, 0);
677 +        }
678 +        goto exit;
679      }
680  
681      if ((to->conf->loopprevention == 1
682 @@ -1592,7 +1637,7 @@ void *clientwr(void *arg) {
683      if (server->dynamiclookuparg && !dynamicconfig(server)) {
684          dynconffail = 1;
685          server->state = RSP_SERVER_STATE_FAILING;
686 -        debug(DBG_WARN, "%s: dynamicconfig(%s: %s) failed, sleeping %ds",
687 +        debug(DBG_WARN, "%s: dynamicconfig(%s: %s) failed, Not trying again for %ds",
688                __func__, server->conf->name, server->dynamiclookuparg, ZZZ);
689          goto errexitwait;
690      }
691 @@ -1600,7 +1645,7 @@ void *clientwr(void *arg) {
692       * either as part of static configuration setup or by
693       * dynamicconfig() above?  */
694      if (!resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype)) {
695 -        debug(DBG_WARN, "%s: resolve failed, sleeping %ds", __func__, ZZZ);
696 +        debug(DBG_WARN, "%s: resolve failed, Not trying again for %ds", __func__, ZZZ);
697          server->state = RSP_SERVER_STATE_FAILING;
698          goto errexitwait;
699      }
700 @@ -1615,7 +1660,7 @@ void *clientwr(void *arg) {
701          if (!conf->pdef->connecter(server, server->dynamiclookuparg ? 5 : 0, "clientwr")) {
702              server->state = RSP_SERVER_STATE_FAILING;
703              if (server->dynamiclookuparg) {
704 -                debug(DBG_WARN, "%s: connect failed, sleeping %ds", __func__, ZZZ);
705 +                debug(DBG_WARN, "%s: connect failed, giving up. Not trying again for %ds", __func__, ZZZ);
706                  goto errexitwait;
707              }
708              goto errexit;
709 @@ -1927,7 +1972,7 @@ void freerealm(struct realm *realm) {
710      free(realm);
711  }
712  
713 -struct realm *addrealm(struct list *realmlist, char *value, char **servers, char **accservers, char *message, uint8_t accresp) {
714 +struct realm *addrealm(struct list *realmlist, char *value, char **servers, char **accservers, char *message, uint8_t accresp, uint8_t acclog) {
715      int n;
716      struct realm *realm;
717      char *s, *regex = NULL;
718 @@ -1991,6 +2036,7 @@ struct realm *addrealm(struct list *realmlist, char *value, char **servers, char
719      }
720      realm->message = message;
721      realm->accresp = accresp;
722 +    realm->acclog = acclog;
723  
724      if (regcomp(&realm->regex, regex ? regex : value + 1, REG_EXTENDED | REG_ICASE | REG_NOSUB)) {
725         debug(DBG_ERR, "addrealm: failed to compile regular expression %s", regex ? regex : value + 1);
726 @@ -2111,7 +2157,7 @@ struct realm *adddynamicrealmserver(struct realm *realm, char *id) {
727      if (!realm->subrealms)
728         return NULL;
729  
730 -    newrealm = addrealm(realm->subrealms, realmname, NULL, NULL, stringcopy(realm->message, 0), realm->accresp);
731 +    newrealm = addrealm(realm->subrealms, realmname, NULL, NULL, stringcopy(realm->message, 0), realm->accresp, realm->acclog);
732      if (!newrealm) {
733         list_destroy(realm->subrealms);
734         realm->subrealms = NULL;
735 @@ -2223,6 +2269,7 @@ void freeclsrvconf(struct clsrvconf *conf) {
736      freematchcertattr(conf);
737      free(conf->confrewritein);
738      free(conf->confrewriteout);
739 +    free(conf->sniservername);
740      if (conf->rewriteusername) {
741         if (conf->rewriteusername->regex)
742             regfree(conf->rewriteusername->regex);
743 @@ -2316,7 +2363,8 @@ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
744         !mergeconfstring(&dst->confrewriteusername, &src->confrewriteusername) ||
745         !mergeconfstring(&dst->dynamiclookupcommand, &src->dynamiclookupcommand) ||
746         !mergeconfstring(&dst->fticks_viscountry, &src->fticks_viscountry) ||
747 -       !mergeconfstring(&dst->fticks_visinst, &src->fticks_visinst))
748 +       !mergeconfstring(&dst->fticks_visinst, &src->fticks_visinst) ||
749 +    !mergeconfstring(&dst->sniservername, &src->sniservername))
750         return 0;
751      if (src->pdef)
752         dst->pdef = src->pdef;
753 @@ -2327,6 +2375,7 @@ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
754      if (src->retrycount != 255)
755         dst->retrycount = src->retrycount;
756      dst->blockingstartup = src->blockingstartup;
757 +    dst->sni = src->sni;
758      return 1;
759  }
760  
761 @@ -2416,7 +2465,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
762                  ? tlsgettls(conf->tls, NULL)
763                  : tlsgettls("defaultClient", "default");
764          if (!conf->tlsconf)
765 -            debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
766 +            debugx(1, DBG_ERR, "error in block %s, tls context not defined", block);
767          if (matchcertattrs) {
768              for (i=0; matchcertattrs[i]; i++){
769                  if (!addmatchcertattr(conf, matchcertattrs[i])) {
770 @@ -2485,7 +2534,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
771                  existing->tlsconf != conf->tlsconf &&
772                  hostportmatches(existing->hostports, conf->hostports, 0)) {
773  
774 -                debugx(1, DBG_ERR, "error in block %s, overlapping clients must reference the same tls block", block);
775 +                debugx(1, DBG_ERR, "error in block %s, masked by overlapping (equal or less specific IP/prefix) client %s with different tls block", block, existing->name);
776              }
777          }
778      }
779 @@ -2573,8 +2622,12 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
780      if (resconf) {
781          conf->statusserver = resconf->statusserver;
782          conf->certnamecheck = resconf->certnamecheck;
783 +        conf->blockingstartup = resconf->blockingstartup;
784 +        conf->type = resconf->type;
785 +        conf->sni = resconf->sni;
786      } else {
787          conf->certnamecheck = 1;
788 +        conf->sni = options.sni;
789      }
790  
791      if (!getgenericconfig(cf, block,
792 @@ -2601,6 +2654,8 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
793              "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand,
794              "LoopPrevention", CONF_BLN, &conf->loopprevention,
795              "BlockingStartup", CONF_BLN, &conf->blockingstartup,
796 +            "SNI", CONF_BLN, &conf->sni,
797 +            "SNIservername", CONF_STR, &conf->sniservername,
798              NULL
799             )) {
800         debug(DBG_ERR, "configuration error");
801 @@ -2621,16 +2676,20 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
802      }
803  
804      if (!conftype) {
805 -       debug(DBG_ERR, "error in block %s, option type missing", block);
806 -       goto errexit;
807 -    }
808 -    conf->type = protoname2int(conftype);
809 -    if (conf->type == 255) {
810 -       debug(DBG_ERR, "error in block %s, unknown transport %s", block, conftype);
811 -       goto errexit;
812 +        if (!resconf) {
813 +            debug(DBG_ERR, "error in block %s, option type missing", block);
814 +            goto errexit;
815 +        }
816 +    } else {
817 +        conf->type = protoname2int(conftype);
818 +        if (conf->type == 255) {
819 +            debug(DBG_ERR, "error in block %s, unknown transport %s", block, conftype);
820 +            goto errexit;
821 +        }
822 +        free(conftype);
823 +        conftype = NULL;
824 +        conf->pdef = protodefs[conf->type];
825      }
826 -    free(conftype);
827 -    conftype = NULL;
828  
829      conf->hostaf = AF_UNSPEC;
830      if (config_hostaf("top level", options.ipv4only, options.ipv6only, &conf->hostaf))
831 @@ -2638,8 +2697,6 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
832      if (config_hostaf(block, ipv4only, ipv6only, &conf->hostaf))
833          goto errexit;
834  
835 -    conf->pdef = protodefs[conf->type];
836 -
837      if (!conf->confrewritein)
838         conf->confrewritein = rewriteinalias;
839      else
840 @@ -2683,8 +2740,12 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
841              conf->statusserver = RSP_STATSRV_AUTO;
842          else
843              debugx(1, DBG_ERR, "config error in blocck %s: invalid StatusServer value: %s", block, statusserver);
844 +        free(statusserver);
845      }
846  
847 +    if(conf->sniservername)
848 +        conf->sni = 1;
849 +
850      if (resconf) {
851          if (!mergesrvconf(resconf, conf))
852              goto errexit;
853 @@ -2769,7 +2830,7 @@ int confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, cha
854  
855  int confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
856      char **servers = NULL, **accservers = NULL, *msg = NULL;
857 -    uint8_t accresp = 0;
858 +    uint8_t accresp = 0, acclog = 0;
859  
860      debug(DBG_DBG, "confrealm_cb called for %s", block);
861  
862 @@ -2778,11 +2839,12 @@ int confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
863                           "accountingServer", CONF_MSTR, &accservers,
864                           "ReplyMessage", CONF_STR, &msg,
865                           "AccountingResponse", CONF_BLN, &accresp,
866 +              "AccountingLog", CONF_BLN, &acclog,
867                           NULL
868             ))
869         debugx(1, DBG_ERR, "configuration error");
870  
871 -    addrealm(realms, val, servers, accservers, msg, accresp);
872 +    addrealm(realms, val, servers, accservers, msg, accresp, acclog);
873      return 1;
874  }
875  
876 @@ -2871,6 +2933,7 @@ void getmainconfig(const char *configfile) {
877          "FTicksPrefix", CONF_STR, &options.fticksprefix,
878          "IPv4Only", CONF_BLN, &options.ipv4only,
879          "IPv6Only", CONF_BLN, &options.ipv6only,
880 +        "SNI", CONF_BLN, &options.sni,
881             NULL
882             ))
883         debugx(1, DBG_ERR, "configuration error");
884 @@ -3031,6 +3094,7 @@ int createpidfile(const char *pidfile) {
885  int radsecproxy_main(int argc, char **argv) {
886      pthread_t sigth;
887      sigset_t sigset;
888 +    size_t stacksize;
889      struct list_node *entry;
890      uint8_t foreground = 0, pretend = 0, loglevel = 0;
891      char *configfile = NULL, *pidfile = NULL;
892 @@ -3042,8 +3106,13 @@ int radsecproxy_main(int argc, char **argv) {
893  
894      if (pthread_attr_init(&pthread_attr))
895         debugx(1, DBG_ERR, "pthread_attr_init failed");
896 -    if (pthread_attr_setstacksize(&pthread_attr, PTHREAD_STACK_SIZE))
897 -       debugx(1, DBG_ERR, "pthread_attr_setstacksize failed");
898 +#if defined(PTHREAD_STACK_MIN)
899 +    stacksize = THREAD_STACK_SIZE > PTHREAD_STACK_MIN ? THREAD_STACK_SIZE : PTHREAD_STACK_MIN;
900 +#else
901 +    stacksize = THREAD_STACK_SIZE;
902 +#endif
903 +    if (pthread_attr_setstacksize(&pthread_attr, stacksize))
904 +        debug(DBG_WARN, "pthread_attr_setstacksize failed! Using system default. Memory footprint might be increased!");
905  #if defined(HAVE_MALLOPT)
906      if (mallopt(M_TRIM_THRESHOLD, 4 * 1024) != 1)
907         debugx(1, DBG_ERR, "mallopt failed");
908 diff --git a/radsecproxy.conf-example b/radsecproxy.conf-example
909 index 1730e55..3b2dd64 100644
910 --- a/radsecproxy.conf-example
911 +++ b/radsecproxy.conf-example
912 @@ -203,6 +203,8 @@ server radius.example.com {
913  # statusserver is optional, can be on or off. Off is default
914         tcpKeepalive on
915  # tcp and tls connections also support TCP keepalives.
916 +# Optionally specify the SNI for the outgoing connection
917 +#       sni www.example.com
918  }
919  #server radius.example.com {
920  #      type    dtls
921 diff --git a/radsecproxy.conf.5.in b/radsecproxy.conf.5.in
922 index 87482c1..ebedd6c 100644
923 --- a/radsecproxy.conf.5.in
924 +++ b/radsecproxy.conf.5.in
925 @@ -297,6 +297,15 @@ clients and servers. At most one of IPv4Only and IPv6Only can be enabled.
926  Note that this can be overridden in client and server blocks, see below.
927  .RE
928  
929 +.BR "SNI (" on | off )
930 +.RS
931 +Server Name Indication (SNI) is an extension to the TLS protocol.  It allows a
932 +client to indicate which hostname it is trying to connect to at the start of
933 +the TLS handshake. Enabling this will use the extension for all TLS and DTLS
934 +servers which specify a hostname (not IP address). This can be overridden in 
935 +server blocks, see below.
936 +.RE
937 +
938  .BI "Include " file
939  .RS
940  This is not a normal configuration option; it can be specified multiple times.
941 @@ -350,10 +359,11 @@ this might mask clients defined later, which then will never be matched.
942  
943  In the case of TLS/DTLS, the name of the client must match the FQDN or IP
944  address in the client certificate (CN or SubectAltName:DNS or SubjectAltName:IP
945 -respectively). Note that this is not required when the client name is an IP
946 -prefix. If overlapping clients are defined (see section above), they will be
947 -searched for matching \fBMatchCertificateAttribute\fR, but they must reference
948 -the same tls block.
949 +respectively) and any \fBMatchCertificateAttribute\fR to be positively identified. 
950 +Note that no FQDN/IP is checked when using an IP prefix. 
951 +If overlapping clients are defined (see section above), they will be searched for 
952 +positive identification, but only among clients referencing the same tls block
953 +(selected by the first matching IP address or prefix).
954  
955  The allowed options in a client block are:
956  
957 @@ -620,6 +630,19 @@ Warning: when the dynamic lookup and connection process is slow, this wil block
958  respective realm for that time.
959  .RE
960  
961 +.BR "SNI (" on | off )
962 +
963 +.RS
964 +Override gobal SNI setting (see above). This is implicitly enabled if \fBSNIservername\fR
965 +is set.
966 +.RE
967 +
968 +.BI "SNIservername " sni
969 +.RS
970 +Explicitly set the \fIsni\fR to request from the server, in case the server is specified
971 +by IP address or to override the hostname. Implicitly enables \fBSNI\fR for this server.
972 +.RE
973 +
974  The meaning and syntax of the following options are exactly the same as for the client
975  block. The details are not repeated here. Please refer to the definitions in the \fBCLIENT BLOCK\fR section.
976  
977 @@ -679,6 +702,12 @@ Enable sending Accounting-Response instead of ignoring Accounting-Requests when
978  no \fBaccoutingServer\fR are configured.
979  .RE
980  
981 +.BR "AccountingLog (" on | off )
982 +.RS
983 +When responding to Accounting-Requests (\fBAccountingResponse on\fR), log the 
984 +accounting data.
985 +.RE
986 +
987  .BI "ReplyMessage " message
988  .RS
989  Specify a message to be sent back to the client if a Access-Request is denied
990 @@ -852,7 +881,8 @@ for DTLS.
991  .BI "DhFile " file
992  .RS
993  DH parameter \fIfile\fR to use. See \fBopenssl-dhparam\fR(1)
994 -
995 +.br
996 +Note: starting with OpenSSL 3.0, use of custom DH parameters is discouraged.
997  
998  .SH "REWRITE BLOCK"
999  .nf
1000 diff --git a/radsecproxy.h b/radsecproxy.h
1001 index cf493b4..8844415 100644
1002 --- a/radsecproxy.h
1003 +++ b/radsecproxy.h
1004 @@ -11,6 +11,7 @@
1005  #include "radmsg.h"
1006  #include "gconfig.h"
1007  #include "rewrite.h"
1008 +#include "hostport.h"
1009  
1010  #include <openssl/asn1.h>
1011  
1012 @@ -28,15 +29,9 @@
1013  #define STATUS_SERVER_PERIOD 25
1014  #define IDLE_TIMEOUT 300
1015  
1016 -/* We want PTHREAD_STACK_SIZE to be 32768, but some platforms
1017 - * have a higher minimum value defined in PTHREAD_STACK_MIN. */
1018 -#define PTHREAD_STACK_SIZE 32768
1019 -#if defined(PTHREAD_STACK_MIN)
1020 -#if PTHREAD_STACK_MIN > PTHREAD_STACK_SIZE
1021 -#undef PTHREAD_STACK_SIZE
1022 -#define PTHREAD_STACK_SIZE PTHREAD_STACK_MIN
1023 -#endif
1024 -#endif
1025 +/* Target value for stack size.
1026 + * Some platforms might define higher minimums in PTHREAD_STACK_MIN. */
1027 +#define THREAD_STACK_SIZE 32768
1028  
1029  /* For systems that only support RFC 2292 Socket API, but not RFC 3542
1030   * like Cygwin */
1031 @@ -103,6 +98,7 @@ struct options {
1032      uint8_t *fticks_key;
1033      uint8_t ipv4only;
1034      uint8_t ipv6only;
1035 +    uint8_t sni;
1036  };
1037  
1038  struct commonprotoopts {
1039 @@ -176,6 +172,8 @@ struct clsrvconf {
1040      struct server *servers;
1041      char *fticks_viscountry;
1042      char *fticks_visinst;
1043 +    uint8_t sni;
1044 +    char *sniservername;
1045  };
1046  
1047  #include "tlscommon.h"
1048 @@ -216,6 +214,7 @@ struct realm {
1049      char *name;
1050      char *message;
1051      uint8_t accresp;
1052 +    uint8_t acclog;
1053      regex_t regex;
1054      uint32_t refcount;
1055      pthread_mutex_t refmutex;
1056 @@ -250,7 +249,7 @@ struct protodefs {
1057  
1058  #define RADLEN(x) ntohs(((uint16_t *)(x))[1])
1059  
1060 -struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur);
1061 +struct clsrvconf *find_clconf(uint8_t type, struct sockaddr *addr, struct list_node **cur, struct hostportres **hp);
1062  struct clsrvconf *find_srvconf(uint8_t type, struct sockaddr *addr, struct list_node **cur);
1063  struct clsrvconf *find_clconf_type(uint8_t type, struct list_node **cur);
1064  struct client *addclient(struct clsrvconf *conf, uint8_t lock);
1065 diff --git a/tcp.c b/tcp.c
1066 index ffb2f4c..e148ed0 100644
1067 --- a/tcp.c
1068 +++ b/tcp.c
1069 @@ -22,6 +22,7 @@
1070  #include <pthread.h>
1071  #include "radsecproxy.h"
1072  #include "hostport.h"
1073 +#include "list.h"
1074  
1075  #ifdef RADPROT_TCP
1076  #include "debug.h"
1077 @@ -84,6 +85,8 @@ int tcpconnect(struct server *server, int timeout, char *text) {
1078      int firsttry = 1;
1079      time_t wait;
1080      struct addrinfo *source = NULL;
1081 +    struct list_node *entry;
1082 +    struct hostportres *hp;
1083  
1084      debug(DBG_DBG, "tcpconnect: called from %s", text);
1085      pthread_mutex_lock(&server->lock);
1086 @@ -112,16 +115,25 @@ int tcpconnect(struct server *server, int timeout, char *text) {
1087              if (source) freeaddrinfo(source);
1088              return 0;
1089          }
1090 -        debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait);
1091 +        if (wait) debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait);
1092          sleep(wait);
1093          firsttry = 0;
1094  
1095 -        
1096          pthread_mutex_lock(&server->lock);
1097  
1098 -        debug(DBG_INFO, "tcpconnect: connecting to %s", server->conf->name);
1099 -        if ((server->sock = connecttcphostlist(server->conf->hostports, source ? source : srcres)) < 0)
1100 +        for (entry = list_first(server->conf->hostports); entry; entry = list_next(entry)) {
1101 +            hp = (struct hostportres *)entry->data;
1102 +            debug(DBG_INFO, "tcpconnect: trying to open TCP connection to server %s (%s port %s)", server->conf->name, hp->host, hp->port);
1103 +            if ((server->sock = connecttcp(hp->addrinfo, source ? source : srcres, list_count(server->conf->hostports) > 1 ? 5 : 30)) >= 0) {
1104 +                debug(DBG_WARN, "tcpconnect: TCP connection to server %s (%s port %s) up", hp->host, hp->port);
1105 +                break;
1106 +            }
1107 +        }
1108 +        if (server->sock < 0) {
1109 +            debug(DBG_ERR, "tcpconnect: TCP connection to server %s failed", server->conf->name);
1110              continue;
1111 +        }
1112 +
1113          if (server->conf->keepalive)
1114              enable_keepalive(server->sock);
1115          break;
1116 @@ -339,7 +351,7 @@ void *tcpservernew(void *arg) {
1117      }
1118      debug(DBG_WARN, "tcpservernew: incoming TCP connection from %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)));
1119  
1120 -    conf = find_clconf(handle, (struct sockaddr *)&from, NULL);
1121 +    conf = find_clconf(handle, (struct sockaddr *)&from, NULL, NULL);
1122      if (conf) {
1123          client = addclient(conf, 1);
1124          if (client) {
1125 diff --git a/tests/t_verify_cert.c b/tests/t_verify_cert.c
1126 index ca0d47e..b52a990 100644
1127 --- a/tests/t_verify_cert.c
1128 +++ b/tests/t_verify_cert.c
1129 @@ -234,7 +234,7 @@ vY/uPjA=\n\
1130          hp.prefixlen = 255;
1131          list_push(conf.hostports, &hp);
1132  
1133 -        ok(1, verifyconfcert(certsimple, &conf), "check disabled");
1134 +        ok(1, verifyconfcert(certsimple, &conf, &hp), "check disabled");
1135  
1136          while(list_shift(conf.hostports));
1137      }
1138 @@ -249,7 +249,7 @@ vY/uPjA=\n\
1139          hp.prefixlen = 0;
1140          list_push(conf.hostports, &hp);
1141  
1142 -        ok(1,verifyconfcert(certsimple, &conf),"cidr prefix");
1143 +        ok(1,verifyconfcert(certsimple, &conf, &hp),"cidr prefix");
1144  
1145          while(list_shift(conf.hostports));
1146      }
1147 @@ -264,11 +264,11 @@ vY/uPjA=\n\
1148          hp.prefixlen = 255;
1149          list_push(conf.hostports, &hp);
1150  
1151 -        ok(1,verifyconfcert(certsimple, &conf), "simple cert cn");
1152 -        ok(0,verifyconfcert(certsimpleother, &conf), "negative simple cert cn");
1153 +        ok(1,verifyconfcert(certsimple, &conf, &hp), "simple cert cn");
1154 +        ok(0,verifyconfcert(certsimpleother, &conf, &hp), "negative simple cert cn");
1155  
1156          /* as per RFC 6125 6.4.4: CN MUST NOT be matched if SAN is present */
1157 -        ok(0,verifyconfcert(certsandns, &conf), "simple cert cn vs san dns, RFC6125");
1158 +        ok(0,verifyconfcert(certsandns, &conf, &hp), "simple cert cn vs san dns, RFC6125");
1159  
1160          while(list_shift(conf.hostports));
1161      }
1162 @@ -284,11 +284,11 @@ vY/uPjA=\n\
1163          hp.prefixlen = 255;
1164          list_push(conf.hostports, &hp);
1165  
1166 -        ok(1,verifyconfcert(certsanip, &conf),"san ip");
1167 -        ok(0,verifyconfcert(certsanipother, &conf),"wrong san ip");
1168 -        ok(0,verifyconfcert(certsimple, &conf), "negative san ip");
1169 -        ok(1,verifyconfcert(certsanipindns, &conf),"san ip in dns");
1170 -        ok(1,verifyconfcert(certcomplex,&conf),"san ip in complex cert");
1171 +        ok(1,verifyconfcert(certsanip, &conf, &hp),"san ip");
1172 +        ok(0,verifyconfcert(certsanipother, &conf, &hp),"wrong san ip");
1173 +        ok(0,verifyconfcert(certsimple, &conf, &hp), "negative san ip");
1174 +        ok(1,verifyconfcert(certsanipindns, &conf, &hp),"san ip in dns");
1175 +        ok(1,verifyconfcert(certcomplex,&conf, &hp),"san ip in complex cert");
1176  
1177          freeaddrinfo(hp.addrinfo);
1178          while(list_shift(conf.hostports));
1179 @@ -306,11 +306,11 @@ vY/uPjA=\n\
1180          hp.prefixlen = 255;
1181          list_push(conf.hostports, &hp);
1182  
1183 -        ok(1,verifyconfcert(certsanipv6, &conf),"san ipv6");
1184 -        ok(0,verifyconfcert(certsanipother, &conf),"wrong san ipv6");
1185 -        ok(0,verifyconfcert(certsimple, &conf),"negative san ipv6");
1186 -        ok(1,verifyconfcert(certsanipv6indns, &conf),"san ipv6 in dns");
1187 -        ok(1,verifyconfcert(certcomplex,&conf),"san ipv6 in complex cert");
1188 +        ok(1,verifyconfcert(certsanipv6, &conf, &hp),"san ipv6");
1189 +        ok(0,verifyconfcert(certsanipother, &conf, &hp),"wrong san ipv6");
1190 +        ok(0,verifyconfcert(certsimple, &conf, &hp),"negative san ipv6");
1191 +        ok(1,verifyconfcert(certsanipv6indns, &conf, &hp),"san ipv6 in dns");
1192 +        ok(1,verifyconfcert(certcomplex,&conf, &hp),"san ipv6 in complex cert");
1193  
1194          freeaddrinfo(hp.addrinfo);
1195          while(list_shift(conf.hostports));
1196 @@ -326,10 +326,10 @@ vY/uPjA=\n\
1197          hp.prefixlen = 255;
1198          list_push(conf.hostports, &hp);
1199  
1200 -        ok(1,verifyconfcert(certsandns, &conf),"san dns");
1201 -        ok(0,verifyconfcert(certsandnsother, &conf),"negative san dns");
1202 -        ok(1,verifyconfcert(certcomplex,&conf),"san dns in complex cert");
1203 -        ok(0,verifyconfcert(certsimple, &conf),"missing san dns");
1204 +        ok(1,verifyconfcert(certsandns, &conf, &hp),"san dns");
1205 +        ok(0,verifyconfcert(certsandnsother, &conf, &hp),"negative san dns");
1206 +        ok(1,verifyconfcert(certcomplex,&conf, &hp),"san dns in complex cert");
1207 +        ok(0,verifyconfcert(certsimple, &conf, &hp),"missing san dns");
1208  
1209          while(list_shift(conf.hostports));
1210      }
1211 @@ -347,8 +347,8 @@ vY/uPjA=\n\
1212          hp2.prefixlen = 255;
1213          list_push(conf.hostports, &hp2);
1214  
1215 -        ok(1,verifyconfcert(certsimple, &conf),"multi hostport cn");
1216 -        ok(0,verifyconfcert(certsimpleother, &conf),"negative multi hostport cn");
1217 +        ok(1,verifyconfcert(certsimple, &conf, NULL),"multi hostport cn");
1218 +        ok(0,verifyconfcert(certsimpleother, &conf, NULL),"negative multi hostport cn");
1219  
1220          while(list_shift(conf.hostports));
1221      }
1222 @@ -366,9 +366,14 @@ vY/uPjA=\n\
1223          hp2.prefixlen = 255;
1224          list_push(conf.hostports, &hp2);
1225  
1226 -        ok(1,verifyconfcert(certsandns, &conf),"multi hostport san dns");
1227 -        ok(0,verifyconfcert(certsandnsother, &conf),"negative multi hostport san dns");
1228 -        ok(1,verifyconfcert(certcomplex,&conf),"multi hostport san dns in complex cert");
1229 +        ok(1,verifyconfcert(certsandns, &conf, NULL),"multi hostport san dns");
1230 +        ok(0,verifyconfcert(certsandnsother, &conf, NULL),"negative multi hostport san dns");
1231 +        ok(1,verifyconfcert(certcomplex,&conf, NULL),"multi hostport san dns in complex cert");
1232 +
1233 +        ok(0,verifyconfcert(certsandns, &conf, &hp1),"multi hostport explicit wrong cert");
1234 +        ok(1,verifyconfcert(certsandns, &conf, &hp2),"multi hostport explicit matching cert");
1235 +        ok(0,verifyconfcert(certcomplex, &conf, &hp1),"multi hostport explicit wrong complex cert");
1236 +        ok(1,verifyconfcert(certcomplex, &conf, &hp2),"multi hostport explicit matching complex cert");
1237  
1238          while(list_shift(conf.hostports));
1239      }
1240 @@ -380,9 +385,9 @@ vY/uPjA=\n\
1241  
1242          ok(1,addmatchcertattr(&conf, "CN:/t..t/"),"explicit cn regex config");
1243  
1244 -        ok(1,verifyconfcert(certsimple, &conf),"explicit cn regex");
1245 -        ok(0,verifyconfcert(certsimpleother, &conf),"negative explicit cn regex");
1246 -        ok(1,verifyconfcert(certsandns, &conf), "explicit cn regex with SAN DNS");
1247 +        ok(1,verifyconfcert(certsimple, &conf, NULL),"explicit cn regex");
1248 +        ok(0,verifyconfcert(certsimpleother, &conf, NULL),"negative explicit cn regex");
1249 +        ok(1,verifyconfcert(certsandns, &conf, NULL), "explicit cn regex with SAN DNS");
1250  
1251          freematchcertattr(&conf);
1252      }
1253 @@ -394,10 +399,10 @@ vY/uPjA=\n\
1254  
1255          ok(1,addmatchcertattr(&conf, "SubjectAltName:IP:192.0.2.1"),"explicit san ip config");
1256  
1257 -        ok(1,verifyconfcert(certsanip, &conf),"explicit san ip");
1258 -        ok(0,verifyconfcert(certsanipother, &conf),"wrong explicit san ip");
1259 -        ok(0,verifyconfcert(certsimple, &conf), "missing explicit san ip");
1260 -        ok(1,verifyconfcert(certcomplex,&conf),"explicit san ip in complex cert");
1261 +        ok(1,verifyconfcert(certsanip, &conf, NULL),"explicit san ip");
1262 +        ok(0,verifyconfcert(certsanipother, &conf, NULL),"wrong explicit san ip");
1263 +        ok(0,verifyconfcert(certsimple, &conf, NULL), "missing explicit san ip");
1264 +        ok(1,verifyconfcert(certcomplex,&conf, NULL),"explicit san ip in complex cert");
1265  
1266          freematchcertattr(&conf);
1267      }
1268 @@ -409,10 +414,10 @@ vY/uPjA=\n\
1269  
1270          ok(1,addmatchcertattr(&conf, "SubjectAltName:IP:2001:db8::1"),"explicit san ipv6 config");
1271  
1272 -        ok(1,verifyconfcert(certsanipv6, &conf),"explicit san ipv6");
1273 -        ok(0,verifyconfcert(certsanipother, &conf),"wrong explicit san ipv6");
1274 -        ok(0,verifyconfcert(certsimple, &conf),"missing explicitsan ipv6");
1275 -        ok(1,verifyconfcert(certcomplex,&conf),"explicit san ipv6 in complex cert");
1276 +        ok(1,verifyconfcert(certsanipv6, &conf, NULL),"explicit san ipv6");
1277 +        ok(0,verifyconfcert(certsanipother, &conf, NULL),"wrong explicit san ipv6");
1278 +        ok(0,verifyconfcert(certsimple, &conf, NULL),"missing explicitsan ipv6");
1279 +        ok(1,verifyconfcert(certcomplex,&conf, NULL),"explicit san ipv6 in complex cert");
1280  
1281          freematchcertattr(&conf);
1282      }
1283 @@ -424,10 +429,10 @@ vY/uPjA=\n\
1284  
1285          ok(1,addmatchcertattr(&conf, "SubjectAltName:DNS:/t..t\\.local/"),"explicit san dns regex config");
1286  
1287 -        ok(1,verifyconfcert(certsandns, &conf),"explicit san dns");
1288 -        ok(0,verifyconfcert(certsandnsother, &conf),"negative explicit san dns");
1289 -        ok(0,verifyconfcert(certsimple,&conf),"missing explicit san dns");
1290 -        ok(1,verifyconfcert(certcomplex,&conf),"explicit san dns in complex cert");
1291 +        ok(1,verifyconfcert(certsandns, &conf, NULL),"explicit san dns");
1292 +        ok(0,verifyconfcert(certsandnsother, &conf, NULL),"negative explicit san dns");
1293 +        ok(0,verifyconfcert(certsimple,&conf, NULL),"missing explicit san dns");
1294 +        ok(1,verifyconfcert(certcomplex,&conf, NULL),"explicit san dns in complex cert");
1295  
1296          freematchcertattr(&conf);
1297      }
1298 @@ -439,9 +444,9 @@ vY/uPjA=\n\
1299  
1300          ok(1,addmatchcertattr(&conf, "SubjectAltName:URI:/https:\\/\\/test.local\\/profile#me/"),"explicit cn regex config");
1301  
1302 -        ok(1,verifyconfcert(certsanuri, &conf),"explicit san uri regex");
1303 -        ok(0,verifyconfcert(certsanuriother, &conf),"negative explicit san uri");
1304 -        ok(0,verifyconfcert(certsimple, &conf), "missing explicit san uri");
1305 +        ok(1,verifyconfcert(certsanuri, &conf, NULL),"explicit san uri regex");
1306 +        ok(0,verifyconfcert(certsanuriother, &conf, NULL),"negative explicit san uri");
1307 +        ok(0,verifyconfcert(certsimple, &conf, NULL), "missing explicit san uri");
1308  
1309          freematchcertattr(&conf);
1310      }
1311 @@ -453,9 +458,9 @@ vY/uPjA=\n\
1312  
1313          ok(1,addmatchcertattr(&conf, "SubjectAltName:rID:1.2.3.4"),"explicit san rid config");
1314  
1315 -        ok(1,verifyconfcert(certsanrid, &conf),"explicit san rid");
1316 -        ok(0,verifyconfcert(certsanridother, &conf),"negative explicit san rid");
1317 -        ok(0,verifyconfcert(certsimple, &conf), "missing explicit san rid");
1318 +        ok(1,verifyconfcert(certsanrid, &conf, NULL),"explicit san rid");
1319 +        ok(0,verifyconfcert(certsanridother, &conf, NULL),"negative explicit san rid");
1320 +        ok(0,verifyconfcert(certsimple, &conf, NULL), "missing explicit san rid");
1321  
1322          freematchcertattr(&conf);
1323      }
1324 @@ -467,9 +472,9 @@ vY/uPjA=\n\
1325  
1326          ok(1,addmatchcertattr(&conf, "SubjectAltName:otherName:1.3.6.1.5.5.7.8.8:/test.local/"),"explicit san otherName config");
1327  
1328 -        ok(1,verifyconfcert(certsanothername, &conf),"explicit san otherName");
1329 -        ok(0,verifyconfcert(certsanothernameother, &conf),"negative explicit san otherName");
1330 -        ok(0,verifyconfcert(certsimple, &conf), "missing explicit san otherName");
1331 +        ok(1,verifyconfcert(certsanothername, &conf, NULL),"explicit san otherName");
1332 +        ok(0,verifyconfcert(certsanothernameother, &conf, NULL),"negative explicit san otherName");
1333 +        ok(0,verifyconfcert(certsimple, &conf, NULL), "missing explicit san otherName");
1334  
1335          freematchcertattr(&conf);
1336      }
1337 @@ -480,7 +485,7 @@ vY/uPjA=\n\
1338          conf.certnamecheck = 0;
1339  
1340          ok(1,addmatchcertattr(&conf, "CN:/t..t"),"test regex config syntax");
1341 -        ok(1,verifyconfcert(certsimple, &conf),"test regex config syntax execution");
1342 +        ok(1,verifyconfcert(certsimple, &conf, NULL),"test regex config syntax execution");
1343  
1344          freematchcertattr(&conf);
1345      }
1346 @@ -518,10 +523,10 @@ vY/uPjA=\n\
1347  
1348          ok(1,addmatchcertattr(&conf, "CN:/t..t"),"combined config");
1349  
1350 -        ok(1,verifyconfcert(certsandns, &conf),"combined san dns");
1351 -        ok(0,verifyconfcert(certsandnsother, &conf),"negative combined san dns");
1352 -        ok(1,verifyconfcert(certcomplex,&conf),"combined san dns in complex cert");
1353 -        ok(0,verifyconfcert(certsimple, &conf),"combined missing san dns");
1354 +        ok(1,verifyconfcert(certsandns, &conf, &hp),"combined san dns");
1355 +        ok(0,verifyconfcert(certsandnsother, &conf, &hp),"negative combined san dns");
1356 +        ok(1,verifyconfcert(certcomplex,&conf, &hp),"combined san dns in complex cert");
1357 +        ok(0,verifyconfcert(certsimple, &conf, &hp),"combined missing san dns");
1358  
1359          while(list_shift(conf.hostports));
1360          freematchcertattr(&conf);
1361 @@ -540,12 +545,12 @@ vY/uPjA=\n\
1362          ok(1,addmatchcertattr(&conf, "SubjectAltName:DNS:/test\\.local/"),"multiple check 1");
1363          ok(1,addmatchcertattr(&conf, "SubjectAltName:rID:1.2.3.4"),"multiple check 2");
1364  
1365 -        ok(0,verifyconfcert(certsandns, &conf),"multiple missing rID");
1366 -        ok(0,verifyconfcert(certsanrid, &conf), "multiple missing DNS");
1367 -        ok(1,verifyconfcert(certmulti, &conf),"multiple SANs");
1368 -        ok(0,verifyconfcert(certmultiother, &conf),"multiple negative match");
1369 -        ok(0,verifyconfcert(certcomplex, &conf),"multiple missing rID in complex cert");
1370 -        ok(0,verifyconfcert(certsimple, &conf),"multiple missing everything");
1371 +        ok(0,verifyconfcert(certsandns, &conf, &hp),"multiple missing rID");
1372 +        ok(0,verifyconfcert(certsanrid, &conf, &hp), "multiple missing DNS");
1373 +        ok(1,verifyconfcert(certmulti, &conf, &hp),"multiple SANs");
1374 +        ok(0,verifyconfcert(certmultiother, &conf, &hp),"multiple negative match");
1375 +        ok(0,verifyconfcert(certcomplex, &conf, &hp),"multiple missing rID in complex cert");
1376 +        ok(0,verifyconfcert(certsimple, &conf, &hp),"multiple missing everything");
1377  
1378          while(list_shift(conf.hostports));
1379          freematchcertattr(&conf);
1380 diff --git a/tls.c b/tls.c
1381 index 87bbe2c..049f3a9 100644
1382 --- a/tls.c
1383 +++ b/tls.c
1384 @@ -23,11 +23,11 @@
1385  #include <assert.h>
1386  #include "radsecproxy.h"
1387  #include "hostport.h"
1388 -
1389 -#ifdef RADPROT_TLS
1390  #include "debug.h"
1391  #include "util.h"
1392  
1393 +#ifdef RADPROT_TLS
1394 +
1395  static void setprotoopts(struct commonprotoopts *opts);
1396  static char **getlistenerargs();
1397  void *tlslistener(void *arg);
1398 @@ -82,6 +82,17 @@ void tlssetsrcres() {
1399                                     AF_UNSPEC, NULL, protodefs.socktype);
1400  }
1401  
1402 +static void cleanup_connection(struct server *server) {
1403 +    if (server->ssl)
1404 +        SSL_shutdown(server->ssl);
1405 +    if (server->sock >= 0)
1406 +        close(server->sock);
1407 +    server->sock = -1;
1408 +    if (server->ssl)
1409 +        SSL_free(server->ssl);
1410 +    server->ssl = NULL;
1411 +}
1412 +
1413  int tlsconnect(struct server *server, int timeout, char *text) {
1414      struct timeval now, start;
1415      time_t wait;
1416 @@ -92,6 +103,8 @@ int tlsconnect(struct server *server, int timeout, char *text) {
1417      int origflags;
1418      struct addrinfo *source = NULL;
1419      char *subj;
1420 +    struct list_node *entry;
1421 +    struct hostportres *hp;
1422  
1423      debug(DBG_DBG, "tlsconnect: called from %s", text);
1424      pthread_mutex_lock(&server->lock);
1425 @@ -108,15 +121,7 @@ int tlsconnect(struct server *server, int timeout, char *text) {
1426      gettimeofday(&start, NULL);
1427  
1428      for (;;) {
1429 -        /* ensure previous connection is properly closed */
1430 -        if (server->ssl)
1431 -            SSL_shutdown(server->ssl);
1432 -        if (server->sock >= 0)
1433 -            close(server->sock);
1434 -        if (server->ssl)
1435 -            SSL_free(server->ssl);
1436 -        server->ssl = NULL;
1437 -
1438 +        cleanup_connection(server);
1439          wait = connect_wait(start, server->connecttime, firsttry);
1440          gettimeofday(&now, NULL);
1441          if (timeout && (now.tv_sec - start.tv_sec) + wait > timeout) {
1442 @@ -124,7 +129,7 @@ int tlsconnect(struct server *server, int timeout, char *text) {
1443              if (source) freeaddrinfo(source);
1444              return 0;
1445          }
1446 -        debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait);
1447 +        if (wait) debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait);
1448          sleep(wait);
1449          firsttry = 0;
1450  
1451 @@ -135,46 +140,76 @@ int tlsconnect(struct server *server, int timeout, char *text) {
1452              return 0;
1453          }
1454  
1455 -        debug(DBG_INFO, "tlsconnect: connecting to %s", server->conf->name);
1456 -        if ((server->sock = connecttcphostlist(server->conf->hostports, source ? source : srcres)) < 0)
1457 -            continue;
1458 -        if (server->conf->keepalive)
1459 -            enable_keepalive(server->sock);
1460 +        for (entry = list_first(server->conf->hostports); entry; entry = list_next(entry)) {
1461 +            hp = (struct hostportres *)entry->data;
1462 +            debug(DBG_INFO, "tlsconnect: trying to open TLS connection to server %s (%s port %s)", server->conf->name, hp->host, hp->port);
1463 +            if ((server->sock = connecttcp(hp->addrinfo, source ? source : srcres, list_count(server->conf->hostports) > 1 ? 5 : 30)) < 0 ) {
1464 +                debug(DBG_ERR, "tlsconnect: TLS connection to %s (%s port %s) failed: TCP connect failed", server->conf->name, hp->host, hp->port);
1465 +                goto concleanup;
1466 +            }
1467 +
1468 +            if (server->conf->keepalive)
1469 +                enable_keepalive(server->sock);
1470 +
1471 +            pthread_mutex_lock(&server->conf->tlsconf->lock);
1472 +            if (!(ctx = tlsgetctx(handle, server->conf->tlsconf))) {
1473 +                pthread_mutex_unlock(&server->conf->tlsconf->lock);
1474 +                debug(DBG_ERR, "tlsconnect: failed to get TLS context for server %s", server->conf->name);
1475 +                goto concleanup;
1476 +            }
1477  
1478 -        pthread_mutex_lock(&server->conf->tlsconf->lock);
1479 -        if (!(ctx = tlsgetctx(handle, server->conf->tlsconf))){
1480 +            server->ssl = SSL_new(ctx);
1481              pthread_mutex_unlock(&server->conf->tlsconf->lock);
1482 -            continue;
1483 -        }
1484 +            if (!server->ssl) {
1485 +                debug(DBG_ERR, "tlsconnect: failed to create SSL conneciton for server %s", server->conf->name);
1486 +                goto concleanup;
1487 +            }
1488  
1489 -        server->ssl = SSL_new(ctx);
1490 -        pthread_mutex_unlock(&server->conf->tlsconf->lock);
1491 -        if (!server->ssl)
1492 -            continue;
1493 +            if (server->conf->sni) {
1494 +                struct in6_addr tmp;
1495 +                char *servername = server->conf->sniservername ? server->conf->sniservername : 
1496 +                    (inet_pton(AF_INET, hp->host, &tmp) || inet_pton(AF_INET6, hp->host, &tmp)) ? NULL : hp->host;
1497 +                if (servername && !tlssetsni(server->ssl, servername)) {
1498 +                    debug(DBG_ERR, "tlsconnect: set SNI %s failed", servername);
1499 +                    goto concleanup;
1500 +                }
1501 +            }
1502 +            
1503 +            SSL_set_fd(server->ssl, server->sock);
1504 +            if (sslconnecttimeout(server->ssl, 5) <= 0) {
1505 +                while ((error = ERR_get_error()))
1506 +                    debug(DBG_ERR, "tlsconnect: SSL connect to %s failed: %s", server->conf->name, ERR_error_string(error, NULL));
1507 +                debug(DBG_ERR, "tlsconnect: SSL connect to %s (%s port %s) failed", server->conf->name, hp->host, hp->port);
1508 +                goto concleanup;
1509 +            }
1510  
1511 -        SSL_set_fd(server->ssl, server->sock);
1512 -        if (sslconnecttimeout(server->ssl, 5) <= 0) {
1513 -            while ((error = ERR_get_error()))
1514 -                debug(DBG_ERR, "tlsconnect: SSL connect to %s failed: %s", server->conf->name, ERR_error_string(error, NULL));
1515 -            debug(DBG_ERR, "tlsconnect: SSL connect to %s failed", server->conf->name);
1516 -            continue;
1517 -        }
1518 +            cert = verifytlscert(server->ssl);
1519 +            if (!cert) {
1520 +                debug(DBG_ERR, "tlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port);
1521 +                goto concleanup;
1522 +            }
1523  
1524 -        cert = verifytlscert(server->ssl);
1525 -        if (!cert)
1526 -            continue;
1527 -        if (verifyconfcert(cert, server->conf)) {
1528 -            subj = getcertsubject(cert);
1529 -            if(subj) {
1530 -                debug(DBG_WARN, "tlsconnect: TLS connection to %s, subject %s up", server->conf->name, subj);
1531 -                free(subj);
1532 +            if (verifyconfcert(cert, server->conf, hp)) {
1533 +                subj = getcertsubject(cert);
1534 +                if(subj) {
1535 +                    debug(DBG_WARN, "tlsconnect: TLS connection to %s (%s port %s), subject %s, %s with cipher %s up",
1536 +                        server->conf->name, hp->host, hp->port, subj,
1537 +                        SSL_get_version(server->ssl), SSL_CIPHER_get_name(SSL_get_current_cipher(server->ssl)));
1538 +                    free(subj);
1539 +                }
1540 +                X509_free(cert);
1541 +                break;
1542 +            } else {
1543 +                debug(DBG_ERR, "tlsconnect: certificate verification failed for %s (%s port %s)", server->conf->name, hp->host, hp->port);
1544              }
1545              X509_free(cert);
1546 -            break;
1547 +
1548 +concleanup:
1549 +            /* ensure previous connection is properly closed */
1550 +            cleanup_connection(server);
1551          }
1552 -        X509_free(cert);
1553 +        if (server->ssl) break;
1554      }
1555 -    debug(DBG_WARN, "tlsconnect: TLS connection to %s up", server->conf->name);
1556  
1557      origflags = fcntl(server->sock, F_GETFL, 0);
1558      if (origflags == -1) {
1559 @@ -251,6 +286,7 @@ int sslreadtimeout(SSL *ssl, unsigned char *buf, int num, int timeout, pthread_m
1560                      continue;
1561                  case SSL_ERROR_ZERO_RETURN:
1562                      debug(DBG_DBG, "sslreadtimeout: got ssl shutdown");
1563 +                    /* fallthrough */
1564                  default:
1565                      while ((error = ERR_get_error()))
1566                          debug(DBG_ERR, "sslreadtimeout: SSL: %s", ERR_error_string(error, NULL));
1567 @@ -505,6 +541,7 @@ void *tlsservernew(void *arg) {
1568      struct client *client;
1569      struct tls *accepted_tls = NULL;
1570      char tmp[INET6_ADDRSTRLEN], *subj;
1571 +    struct hostportres *hp;
1572  
1573      s = *(int *)arg;
1574      free(arg);
1575 @@ -514,7 +551,7 @@ void *tlsservernew(void *arg) {
1576      }
1577      debug(DBG_WARN, "tlsservernew: incoming TLS connection from %s", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)));
1578  
1579 -    conf = find_clconf(handle, (struct sockaddr *)&from, &cur);
1580 +    conf = find_clconf(handle, (struct sockaddr *)&from, &cur, &hp);
1581      if (conf) {
1582          pthread_mutex_lock(&conf->tlsconf->lock);
1583          ctx = tlsgetctx(handle, conf->tlsconf);
1584 @@ -549,11 +586,12 @@ void *tlsservernew(void *arg) {
1585      }
1586  
1587      while (conf) {
1588 -        if (accepted_tls == conf->tlsconf && verifyconfcert(cert, conf)) {
1589 +        if (accepted_tls == conf->tlsconf && verifyconfcert(cert, conf, NULL)) {
1590              subj = getcertsubject(cert);
1591              if(subj) {
1592 -                debug(DBG_WARN, "tlsservernew: TLS connection from %s, client %s, subject %s up",
1593 -                    addr2string((struct sockaddr *)&from,tmp, sizeof(tmp)), conf->name, subj);
1594 +                debug(DBG_WARN, "tlsservernew: TLS connection from %s, client %s, subject %s, %s with cipher %s up",
1595 +                    addr2string((struct sockaddr *)&from,tmp, sizeof(tmp)), conf->name, subj,
1596 +                    SSL_get_version(ssl), SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)));
1597                  free(subj);
1598              }
1599              X509_free(cert);
1600 @@ -569,9 +607,10 @@ void *tlsservernew(void *arg) {
1601                  debug(DBG_WARN, "tlsservernew: failed to create new client instance");
1602              goto exit;
1603          }
1604 -        conf = find_clconf(handle, (struct sockaddr *)&from, &cur);
1605 +        conf = find_clconf(handle, (struct sockaddr *)&from, &cur, &hp);
1606      }
1607 -    debug(DBG_WARN, "tlsservernew: ignoring request, no matching TLS client");
1608 +    debug(DBG_WARN, "tlsservernew: ignoring request, no matching TLS client for %s", 
1609 +        addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)));
1610      if (cert)
1611         X509_free(cert);
1612  
1613 diff --git a/tlscommon.c b/tlscommon.c
1614 index 0bd7da4..2dc0f48 100644
1615 --- a/tlscommon.c
1616 +++ b/tlscommon.c
1617 @@ -492,12 +492,26 @@ static SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
1618  #endif
1619  
1620      if (conf->dhparam) {
1621 +#if OPENSSL_VERSION_NUMBER >= 0x30000000
1622 +        if (!SSL_CTX_set0_tmp_dh_pkey(ctx, conf->dhparam)) {
1623 +#else
1624          if (!SSL_CTX_set_tmp_dh(ctx, conf->dhparam)) {
1625 +#endif
1626              while ((error = ERR_get_error()))
1627                  debug(DBG_WARN, "tlscreatectx: SSL: %s", ERR_error_string(error, NULL));
1628              debug(DBG_WARN, "tlscreatectx: Failed to set dh params. Can continue, but some ciphers might not be available.");
1629          }
1630      }
1631 +#if OPENSSL_VERSION_NUMBER >= 0x10100000
1632 +    else {
1633 +        if (!SSL_CTX_set_dh_auto(ctx, 1)) {
1634 +            while ((error = ERR_get_error()))
1635 +                debug(DBG_WARN, "tlscreatectx: SSL: %s", ERR_error_string(error, NULL));
1636 +            debug(DBG_WARN, "tlscreatectx: Failed to set automatic dh params. Can continue, but some ciphers might not be available.");
1637 +        }
1638 +    }
1639 +#endif
1640 +
1641      debug(DBG_DBG, "tlscreatectx: created TLS context %s", conf->name);
1642      return ctx;
1643  }
1644 @@ -506,7 +520,7 @@ struct tls *tlsgettls(char *alt1, char *alt2) {
1645      struct tls *t;
1646  
1647      t = hash_read(tlsconfs, alt1, strlen(alt1));
1648 -    if (!t)
1649 +    if (!t && alt2)
1650         t = hash_read(tlsconfs, alt2, strlen(alt2));
1651      return t;
1652  }
1653 @@ -711,64 +725,67 @@ static int matchsubjaltname(X509 *cert, struct certattrmatch* match) {
1654      }
1655  
1656      if (r<1)
1657 -        debug(DBG_WARN, "matchsubjaltname: no matching Subject Alt Name found! (%s)", fail);
1658 +        debug(DBG_DBG, "matchsubjaltname: no matching Subject Alt Name found! (%s)", fail);
1659      free(fail);
1660  
1661      GENERAL_NAMES_free(alt);
1662      return r;
1663  }
1664  
1665 -int certnamecheck(X509 *cert, struct list *hostports) {
1666 -    struct list_node *entry;
1667 -    struct hostportres *hp;
1668 +int certnamecheck(X509 *cert, struct hostportres *hp) {
1669      int r = 0;
1670      struct certattrmatch match;
1671  
1672      memset(&match, 0, sizeof(struct certattrmatch));
1673  
1674 -    for (entry = list_first(hostports); entry; entry = list_next(entry)) {
1675 -        r = 0;
1676 -        hp = (struct hostportres *)entry->data;
1677 -        if (hp->prefixlen != 255) {
1678 -            /* we disable the check for prefixes */
1679 +    r = 0;
1680 +    if (hp->prefixlen != 255) {
1681 +        /* we disable the check for prefixes */
1682 +        return 1;
1683 +    }
1684 +    if (inet_pton(AF_INET, hp->host, &match.ipaddr))
1685 +        match.af = AF_INET;
1686 +    else if (inet_pton(AF_INET6, hp->host, &match.ipaddr))
1687 +        match.af = AF_INET6;
1688 +    else
1689 +        match.af = 0;
1690 +    match.exact = hp->host;
1691 +
1692 +    if (match.af) {
1693 +        match.matchfn = &certattr_matchip;
1694 +        match.type = GEN_IPADD;
1695 +        r = matchsubjaltname(cert, &match);
1696 +    }
1697 +    if (!r) {
1698 +        match.matchfn = &certattr_matchregex;
1699 +        match.type = GEN_DNS;
1700 +        r = matchsubjaltname(cert, &match);
1701 +    }
1702 +    if (r) {
1703 +        if (r > 0) {
1704 +            debug(DBG_DBG, "certnamecheck: Found subjectaltname matching %s %s", match.af ? "address" : "host", hp->host);
1705              return 1;
1706          }
1707 -        if (inet_pton(AF_INET, hp->host, &match.ipaddr))
1708 -            match.af = AF_INET;
1709 -        else if (inet_pton(AF_INET6, hp->host, &match.ipaddr))
1710 -            match.af = AF_INET6;
1711 -        else
1712 -            match.af = 0;
1713 -        match.exact = hp->host;
1714 -
1715 -        if (match.af) {
1716 -            match.matchfn = &certattr_matchip;
1717 -            match.type = GEN_IPADD;
1718 -            r = matchsubjaltname(cert, &match);
1719 -        }
1720 -        if (!r) {
1721 -            match.matchfn = &certattr_matchregex;
1722 -            match.type = GEN_DNS;
1723 -            r = matchsubjaltname(cert, &match);
1724 -        }
1725 -        if (r) {
1726 -            if (r > 0) {
1727 -                debug(DBG_DBG, "certnamecheck: Found subjectaltname matching %s %s", match.af ? "address" : "host", hp->host);
1728 -                return 1;
1729 -            }
1730 -            debug(DBG_WARN, "certnamecheck: No subjectaltname matching %s %s", match.af ? "address" : "host", hp->host);
1731 -        } else {
1732 -            if (certattr_matchcn(cert, &match)) {
1733 -                debug(DBG_DBG, "certnamecheck: Found cn matching host %s", hp->host);
1734 -                return 1;
1735 -            }
1736 -            debug(DBG_WARN, "certnamecheck: cn not matching host %s", hp->host);
1737 +        debug(DBG_WARN, "certnamecheck: No subjectaltname matching %s %s", match.af ? "address" : "host", hp->host);
1738 +    } else { /* as per RFC 6125 6.4.4: CN MUST NOT be matched if SAN is present */
1739 +        if (certattr_matchcn(cert, &match)) {
1740 +            debug(DBG_DBG, "certnamecheck: Found cn matching host %s", hp->host);
1741 +            return 1;
1742          }
1743 +        debug(DBG_WARN, "certnamecheck: cn not matching host %s", hp->host);
1744      }
1745      return 0;
1746  }
1747  
1748 -int verifyconfcert(X509 *cert, struct clsrvconf *conf) {
1749 +int certnamecheckany(X509 *cert, struct list *hostports) {
1750 +    struct list_node *entry;
1751 +    for (entry = list_first(hostports); entry; entry = list_next(entry)) {
1752 +        if (certnamecheck(cert, (struct hostportres *)entry->data)) return 1;
1753 +    }
1754 +    return 0;
1755 +}
1756 +
1757 +int verifyconfcert(X509 *cert, struct clsrvconf *conf, struct hostportres *hpconnected) {
1758      char *subject;
1759      int ok = 1;
1760      struct list_node *entry;
1761 @@ -777,9 +794,16 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf) {
1762      debug(DBG_DBG, "verifyconfcert: verify certificate for host %s, subject %s", conf->name, subject);
1763      if (conf->certnamecheck) {
1764          debug(DBG_DBG, "verifyconfcert: verify hostname");
1765 -        if (!certnamecheck(cert, conf->hostports)) {
1766 -            debug(DBG_DBG, "verifyconfcert: certificate name check failed for host %s", conf->name);
1767 -            ok = 0;
1768 +        if (hpconnected) {
1769 +            if (!certnamecheck(cert, hpconnected)) {
1770 +                debug(DBG_WARN, "verifyconfcert: certificate name check failed for host %s (%s)", conf->name, hpconnected->host);
1771 +                ok = 0;
1772 +            }
1773 +        } else {
1774 +            if (!certnamecheckany(cert, conf->hostports)) {
1775 +                debug(DBG_DBG, "verifyconfcert: no matching CN or SAN found for host %s", conf->name);
1776 +                ok = 0;
1777 +            }
1778          }
1779      }
1780  
1781 @@ -913,11 +937,27 @@ int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *v
1782          dtlsversion = NULL;
1783      }
1784  #else
1785 +    if (tlsversion || dtlsversion) {
1786          debug(DBG_ERR, "error in block %s, setting tls/dtls version requires openssl 1.1.0 or later", val);
1787          goto errexit;
1788 +    }
1789  #endif
1790  
1791      if (dhfile) {
1792 +#if OPENSSL_VERSION_NUMBER >= 0x30000000
1793 +        BIO *bio = BIO_new_file(dhfile, "r");
1794 +        if (bio) {
1795 +            conf->dhparam = EVP_PKEY_new();
1796 +            if (!PEM_read_bio_Parameters(bio, &conf->dhparam)) {
1797 +                BIO_free(bio);
1798 +                while ((error = ERR_get_error()))
1799 +                    debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
1800 +                debug(DBG_ERR, "error in block %s: Failed to load DhFile %s.", val, dhfile);
1801 +                goto errexit;
1802 +            }
1803 +            BIO_free(bio);
1804 +        }
1805 +#else
1806          FILE *dhfp = fopen(dhfile, "r");
1807          if (dhfp) {
1808              conf->dhparam = PEM_read_DHparams(dhfp, NULL, NULL, NULL);
1809 @@ -934,6 +974,7 @@ int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *v
1810          }
1811          free(dhfile);
1812          dhfile = NULL;
1813 +#endif
1814      }
1815  
1816      conf->name = stringcopy(val, 0);
1817 @@ -964,7 +1005,11 @@ errexit:
1818      free(tlsversion);
1819      free(dtlsversion);
1820      free(dhfile);
1821 +#if OPENSSL_VERSION_NUMBER >= 0x30000000
1822 +    EVP_PKEY_free(conf->dhparam);
1823 +#else
1824      DH_free(conf->dhparam);
1825 +#endif
1826      free(conf);
1827      return 0;
1828  }
1829 @@ -1091,6 +1136,10 @@ void freematchcertattr(struct clsrvconf *conf) {
1830      }
1831  }
1832  
1833 +int tlssetsni(SSL *ssl, char *sni) {
1834 +    return SSL_set_tlsext_host_name(ssl, sni); 
1835 +}
1836 +
1837  int sslaccepttimeout (SSL *ssl, int timeout) {
1838      int socket, origflags, ndesc, r = -1, sockerr = 0;
1839      socklen_t errlen = sizeof(sockerr);
1840 diff --git a/tlscommon.h b/tlscommon.h
1841 index 6be9079..1006626 100644
1842 --- a/tlscommon.h
1843 +++ b/tlscommon.h
1844 @@ -3,6 +3,7 @@
1845  /* See LICENSE for licensing information. */
1846  
1847  #include <openssl/ssl.h>
1848 +#include "hostport.h"
1849  
1850  #if OPENSSL_VERSION_NUMBER < 0x10100000L
1851  #define ASN1_STRING_get0_data(o) ((o)->data)
1852 @@ -25,7 +26,11 @@ struct tls {
1853      int tlsmaxversion;
1854      int dtlsminversion;
1855      int dtlsmaxversion;
1856 +#if OPENSSL_VERSION_NUMBER >= 0x30000000
1857 +    EVP_PKEY* dhparam;
1858 +#else
1859      DH *dhparam;
1860 +#endif
1861      uint32_t tlsexpiry;
1862      uint32_t dtlsexpiry;
1863      X509_VERIFY_PARAM *vpm;
1864 @@ -40,12 +45,13 @@ void sslinit();
1865  struct tls *tlsgettls(char *alt1, char *alt2);
1866  SSL_CTX *tlsgetctx(uint8_t type, struct tls *t);
1867  X509 *verifytlscert(SSL *ssl);
1868 -int verifyconfcert(X509 *cert, struct clsrvconf *conf);
1869 +int verifyconfcert(X509 *cert, struct clsrvconf *conf, struct hostportres *);
1870  char *getcertsubject(X509 *cert);
1871  int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val);
1872  int addmatchcertattr(struct clsrvconf *conf, const char *match);
1873  void freematchcertattr(struct clsrvconf *conf);
1874  void tlsreloadcrls();
1875 +int tlssetsni(SSL *ssl, char *sni);
1876  int sslconnecttimeout(SSL *ssl, int timeout);
1877  int sslaccepttimeout (SSL *ssl, int timeout);
1878  #endif
1879 diff --git a/tlv11.c b/tlv11.c
1880 index d570b39..9eaf6d9 100644
1881 --- a/tlv11.c
1882 +++ b/tlv11.c
1883 @@ -12,6 +12,7 @@
1884  #include <stdlib.h>
1885  #include <string.h>
1886  #include <arpa/inet.h>
1887 +#include <stdio.h>
1888  
1889  struct tlv *maketlv(uint8_t t, uint8_t l, void *v) {
1890      struct tlv *tlv;
1891 @@ -97,6 +98,8 @@ void rmtlv(struct list *tlvs, uint8_t t) {
1892  }
1893  
1894  uint8_t *tlv2str(struct tlv *tlv) {
1895 +    if(!tlv)
1896 +        return NULL;
1897      uint8_t *s = malloc(tlv->l + 1);
1898      if (s) {
1899         memcpy(s, tlv->v, tlv->l);
1900 @@ -117,6 +120,28 @@ struct tlv *resizetlv(struct tlv *tlv, uint8_t newlen) {
1901      return tlv;
1902  }
1903  
1904 +uint32_t tlv2longint(struct tlv *tlv) {
1905 +    if (!tlv) return 0;
1906 +    if (tlv->l != sizeof(uint32_t)) return 0;
1907 +    return ntohl(*(uint32_t *)tlv->v);
1908 +}
1909 +
1910 +char* tlv2ipv4addr(struct tlv *tlv) {
1911 +    char *result;
1912 +
1913 +    if (!tlv) return NULL;
1914 +    if (tlv->l != sizeof(in_addr_t)) return NULL;
1915 +
1916 +    result = malloc(INET_ADDRSTRLEN);
1917 +    if (!result) return NULL;
1918 +
1919 +    if (!inet_ntop(AF_INET, tlv->v, result, INET_ADDRSTRLEN)) {
1920 +        free(result);
1921 +        return NULL;
1922 +    }
1923 +    return result;
1924 +}
1925 +
1926  /* Local Variables: */
1927  /* c-file-style: "stroustrup" */
1928  /* End: */
1929 diff --git a/tlv11.h b/tlv11.h
1930 index 84db3d7..c565d13 100644
1931 --- a/tlv11.h
1932 +++ b/tlv11.h
1933 @@ -17,6 +17,8 @@ void freetlvlist(struct list *);
1934  void rmtlv(struct list *, uint8_t);
1935  uint8_t *tlv2str(struct tlv *tlv);
1936  struct tlv *resizetlv(struct tlv *, uint8_t);
1937 +uint32_t tlv2longint(struct tlv *tlv);
1938 +char* tlv2ipv4addr(struct tlv *tlv);
1939  
1940  /* Local Variables: */
1941  /* c-file-style: "stroustrup" */
1942 diff --git a/tools/naptr-eduroam.sh b/tools/naptr-eduroam.sh
1943 index 5402d18..2f90601 100755
1944 --- a/tools/naptr-eduroam.sh
1945 +++ b/tools/naptr-eduroam.sh
1946 @@ -14,7 +14,6 @@ usage() {
1947  
1948  test -n "${1}" || usage
1949  
1950 -REALM="${1}"
1951  DIGCMD=$(command -v dig)
1952  HOSTCMD=$(command -v host)
1953  PRINTCMD=$(command -v printf)
1954 @@ -38,7 +37,7 @@ dig_it_srv() {
1955  }
1956  
1957  dig_it_naptr() {
1958 -    ${DIGCMD} +short naptr ${REALM} | grep x-eduroam:radius.tls | sort -n -k1 |
1959 +    ${DIGCMD} +short naptr "${REALM}" | grep x-eduroam:radius.tls | sort -n -k1 |
1960      while read line; do
1961          set $line ; TYPE=$3 ; HOST=$(validate_host $6)
1962          if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then
1963 @@ -59,7 +58,7 @@ host_it_srv() {
1964  }
1965  
1966  host_it_naptr() {
1967 -    ${HOSTCMD} -t naptr ${REALM} | grep x-eduroam:radius.tls | sort -n -k5 |
1968 +    ${HOSTCMD} -t naptr "${REALM}" | grep x-eduroam:radius.tls | sort -n -k5 |
1969      while read line; do
1970          set $line ; TYPE=$7 ; HOST=$(validate_host ${10})
1971          if ( [ "$TYPE" = "\"s\"" ] || [ "$TYPE" = "\"S\"" ] ) && [ -n "${HOST}" ]; then
1972 @@ -69,6 +68,12 @@ host_it_naptr() {
1973      done
1974  }
1975  
1976 +REALM=$(validate_host ${1})
1977 +if [ -z "${REALM}" ]; then
1978 +    echo "Error: realm \"${1}\" failed validation"
1979 +    usage
1980 +fi
1981 +
1982  if [ -x "${DIGCMD}" ]; then
1983      SERVERS=$(dig_it_naptr)
1984  elif [ -x "${HOSTCMD}" ]; then
1985 @@ -79,7 +84,7 @@ else
1986  fi
1987  
1988  if [ -n "${SERVERS}" ]; then
1989 -    $PRINTCMD "server dynamic_radsec.${REALM} {\n${SERVERS}\n\ttype TLS\n}\n"
1990 +    $PRINTCMD "server dynamic_radsec.${REALM} {\n${SERVERS}\n}\n"
1991      exit 0
1992  fi
1993  
1994 diff --git a/tools/radsec-dynsrv.sh b/tools/radsec-dynsrv.sh
1995 index 68bb5ba..d8318ed 100755
1996 --- a/tools/radsec-dynsrv.sh
1997 +++ b/tools/radsec-dynsrv.sh
1998 @@ -14,7 +14,6 @@ usage() {
1999  
2000  test -n "${1}" || usage
2001  
2002 -REALM="${1}"
2003  DIGCMD=$(command -v digaaa)
2004  HOSTCMD=$(command -v host)
2005  PRINTCMD=$(command -v printf)
2006 @@ -28,7 +27,7 @@ validate_port() {
2007  }
2008  
2009  dig_it() {
2010 -   ${DIGCMD} +short srv _radsec._tcp.${REALM} | sort -n -k1 |
2011 +   ${DIGCMD} +short srv "_radsec._tcp.${REALM}" | sort -n -k1 |
2012     while read line ; do
2013        set $line ; PORT=$(validate_port $3) ; HOST=$(validate_host $4)
2014        if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then 
2015 @@ -38,7 +37,7 @@ dig_it() {
2016  }
2017  
2018  host_it() {
2019 -   ${HOSTCMD} -t srv _radsec._tcp.${REALM} | sort -n -k5 |
2020 +   ${HOSTCMD} -t srv "_radsec._tcp.${REALM}" | sort -n -k5 |
2021     while read line ; do
2022        set $line ; PORT=$(validate_port $7) ; HOST=$(validate_host $8) 
2023        if [ -n "${HOST}" ] && [ -n "${PORT}" ]; then
2024 @@ -47,6 +46,12 @@ host_it() {
2025     done
2026  }
2027  
2028 +REALM=$(validate_host ${1})
2029 +if test -z "${REALM}" ; then
2030 +    echo "Error: realm \"${1}\" failed validation"
2031 +    usage
2032 +fi
2033 +
2034  if test -x "${DIGCMD}" ; then
2035     SERVERS=$(dig_it)
2036  elif test -x "${HOSTCMD}" ; then
2037 @@ -57,7 +62,7 @@ else
2038  fi
2039  
2040  if test -n "${SERVERS}" ; then
2041 -        $PRINTCMD "server dynamic_radsec.${REALM} {\n${SERVERS}\n\ttype TLS\n}\n"
2042 +        $PRINTCMD "server dynamic_radsec.${REALM} {\n${SERVERS}\n}\n"
2043          exit 0
2044  fi
2045  
2046 diff --git a/udp.c b/udp.c
2047 index e3e1464..6e86fbe 100644
2048 --- a/udp.c
2049 +++ b/udp.c
2050 @@ -160,7 +160,7 @@ unsigned char *radudpget(int s, struct client **client, struct server **server)
2051          }
2052  
2053          p = client
2054 -            ? find_clconf(handle, (struct sockaddr *)&from, NULL)
2055 +            ? find_clconf(handle, (struct sockaddr *)&from, NULL, NULL)
2056              : find_srvconf(handle, (struct sockaddr *)&from, NULL);
2057          if (!p) {
2058              debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, tmp, sizeof(tmp)));
This page took 0.191104 seconds and 3 git commands to generate.