Use macro for terminating CONF_PARSER arrays
[freeradius.git] / src / main / realms.c
1 /*
2  * realms.c     Realm handling code
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2007  The FreeRADIUS server project
21  * Copyright 2007  Alan DeKok <aland@deployingradius.com>
22  */
23
24 RCSID("$Id$")
25
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/realms.h>
28 #include <freeradius-devel/rad_assert.h>
29
30 #include <sys/stat.h>
31
32 #include <ctype.h>
33 #include <fcntl.h>
34
35 static rbtree_t *realms_byname = NULL;
36 #ifdef WITH_TCP
37 bool home_servers_udp = false;
38 #endif
39
40 #ifdef HAVE_REGEX
41 typedef struct realm_regex realm_regex_t;
42
43 /** Regular expression associated with a realm
44  *
45  */
46 struct realm_regex {
47         REALM           *realm;         //!< The realm this regex matches.
48         regex_t         *preg;          //!< The pre-compiled regular expression.
49         realm_regex_t   *next;          //!< The next realm in the list of regular expressions.
50 };
51 static realm_regex_t *realms_regex = NULL;
52 #endif /* HAVE_REGEX */
53
54 struct realm_config {
55         CONF_SECTION            *cs;
56         uint32_t                dead_time;
57         uint32_t                retry_count;
58         uint32_t                retry_delay;
59         bool                    dynamic;
60         bool                    fallback;
61         bool                    wake_all_if_all_dead;
62 };
63
64 static const FR_NAME_NUMBER home_server_types[] = {
65         { "auth",               HOME_TYPE_AUTH },
66         { "acct",               HOME_TYPE_ACCT },
67         { "auth+acct",          HOME_TYPE_AUTH_ACCT },
68         { "coa",                HOME_TYPE_COA },
69         { NULL, 0 }
70 };
71
72 static const FR_NAME_NUMBER home_ping_check[] = {
73         { "none",               HOME_PING_CHECK_NONE },
74         { "status-server",      HOME_PING_CHECK_STATUS_SERVER },
75         { "request",            HOME_PING_CHECK_REQUEST },
76         { NULL, 0 }
77 };
78
79 static const FR_NAME_NUMBER home_proto[] = {
80         { "UDP",                IPPROTO_UDP },
81         { "TCP",                IPPROTO_TCP },
82         { NULL, 0 }
83 };
84
85
86 static realm_config_t *realm_config = NULL;
87
88 #ifdef WITH_PROXY
89 static rbtree_t *home_servers_byaddr = NULL;
90 static rbtree_t *home_servers_byname = NULL;
91 #ifdef WITH_STATS
92 static int home_server_max_number = 0;
93 static rbtree_t *home_servers_bynumber = NULL;
94 #endif
95
96 static rbtree_t *home_pools_byname = NULL;
97
98 /*
99  *  Map the proxy server configuration parameters to variables.
100  */
101 static const CONF_PARSER proxy_config[] = {
102         { "retry_delay", FR_CONF_OFFSET(PW_TYPE_INTEGER, realm_config_t, retry_delay), STRINGIFY(RETRY_DELAY)  },
103
104         { "retry_count", FR_CONF_OFFSET(PW_TYPE_INTEGER, realm_config_t, retry_count), STRINGIFY(RETRY_COUNT)  },
105
106         { "default_fallback", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, realm_config_t, fallback), "no" },
107
108         { "dynamic", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, realm_config_t, dynamic), NULL },
109
110         { "dead_time", FR_CONF_OFFSET(PW_TYPE_INTEGER, realm_config_t, dead_time), STRINGIFY(DEAD_TIME)  },
111
112         { "wake_all_if_all_dead", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, realm_config_t, wake_all_if_all_dead), "no" },
113         CONF_PARSER_TERMINATOR
114 };
115 #endif
116
117 static int realm_name_cmp(void const *one, void const *two)
118 {
119         REALM const *a = one;
120         REALM const *b = two;
121
122         return strcasecmp(a->name, b->name);
123 }
124
125
126 #ifdef WITH_PROXY
127 static void home_server_free(void *data)
128 {
129         home_server_t *home = talloc_get_type_abort(data, home_server_t);
130
131         talloc_free(home);
132 }
133
134 static int home_server_name_cmp(void const *one, void const *two)
135 {
136         home_server_t const *a = one;
137         home_server_t const *b = two;
138
139         if (a->type < b->type) return -1;
140         if (a->type > b->type) return +1;
141
142         return strcasecmp(a->name, b->name);
143 }
144
145 static int home_server_addr_cmp(void const *one, void const *two)
146 {
147         int rcode;
148         home_server_t const *a = one;
149         home_server_t const *b = two;
150
151         if (a->server && !b->server) return -1;
152         if (!a->server && b->server) return +1;
153         if (a->server && b->server) {
154                 rcode = a->type - b->type;
155                 if (rcode != 0) return rcode;
156                 return strcmp(a->server, b->server);
157         }
158
159         if (a->port < b->port) return -1;
160         if (a->port > b->port) return +1;
161
162 #ifdef WITH_TCP
163         if (a->proto < b->proto) return -1;
164         if (a->proto > b->proto) return +1;
165 #endif
166
167         rcode = fr_ipaddr_cmp(&a->src_ipaddr, &b->src_ipaddr);
168         if (rcode != 0) return rcode;
169
170         return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
171 }
172
173 #ifdef WITH_STATS
174 static int home_server_number_cmp(void const *one, void const *two)
175 {
176         home_server_t const *a = one;
177         home_server_t const *b = two;
178
179         return (a->number - b->number);
180 }
181 #endif
182
183 static int home_pool_name_cmp(void const *one, void const *two)
184 {
185         home_pool_t const *a = one;
186         home_pool_t const *b = two;
187
188         if (a->server_type < b->server_type) return -1;
189         if (a->server_type > b->server_type) return +1;
190
191         return strcasecmp(a->name, b->name);
192 }
193
194
195 static size_t CC_HINT(nonnull) xlat_cs(CONF_SECTION *cs, char const *fmt, char *out, size_t outlen)
196 {
197         char const *value = NULL;
198
199         /*
200          *      Instance name
201          */
202         if (strcmp(fmt, "instance") == 0) {
203                 value = cf_section_name2(cs);
204                 if (!value) {
205                         *out = '\0';
206                         return 0;
207                 }
208         } else {
209                 CONF_PAIR *cp;
210
211                 cp = cf_pair_find(cs, fmt);
212                 if (!cp || !(value = cf_pair_value(cp))) {
213                         *out = '\0';
214                         return 0;
215                 }
216         }
217
218         strlcpy(out, value, outlen);
219
220         return strlen(out);
221 }
222
223
224 /*
225  *      Xlat for %{home_server:foo}
226  */
227 static ssize_t CC_HINT(nonnull) xlat_home_server(UNUSED void *instance, REQUEST *request,
228                                                  char const *fmt, char *out, size_t outlen)
229 {
230         if (!request->home_server) {
231                 RWDEBUG("No home_server associated with this request");
232
233                 *out = '\0';
234                 return 0;
235         }
236
237         return xlat_cs(request->home_server->cs, fmt, out, outlen);
238 }
239
240
241 /*
242  *      Xlat for %{home_server_pool:foo}
243  */
244 static ssize_t CC_HINT(nonnull) xlat_server_pool(UNUSED void *instance, REQUEST *request,
245                                                  char const *fmt, char *out, size_t outlen)
246 {
247         if (!request->home_pool) {
248                 RWDEBUG("No home_pool associated with this request");
249
250                 *out = '\0';
251                 return 0;
252         }
253
254         return xlat_cs(request->home_pool->cs, fmt, out, outlen);
255 }
256 #endif
257
258 void realms_free(void)
259 {
260 #ifdef WITH_PROXY
261 #  ifdef WITH_STATS
262         rbtree_free(home_servers_bynumber);
263         home_servers_bynumber = NULL;
264 #  endif
265
266         rbtree_free(home_servers_byname);
267         home_servers_byname = NULL;
268
269         rbtree_free(home_servers_byaddr);
270         home_servers_byaddr = NULL;
271
272         rbtree_free(home_pools_byname);
273         home_pools_byname = NULL;
274 #endif
275
276         rbtree_free(realms_byname);
277         realms_byname = NULL;
278
279         realm_pool_free(NULL);
280
281         talloc_free(realm_config);
282         realm_config = NULL;
283 }
284
285
286 #ifdef WITH_PROXY
287 static CONF_PARSER limit_config[] = {
288         { "max_connections", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, limit.max_connections), "16" },
289         { "max_requests", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, limit.max_requests), "0" },
290         { "lifetime", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, limit.lifetime), "0" },
291         { "idle_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, limit.idle_timeout), "0" },
292         CONF_PARSER_TERMINATOR
293 };
294
295 #ifdef WITH_COA
296 static CONF_PARSER home_server_coa[] = {
297         { "irt",  FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, coa_irt), STRINGIFY(2) },
298         { "mrt",  FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, coa_mrt), STRINGIFY(16) },
299         { "mrc",  FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, coa_mrc), STRINGIFY(5) },
300         { "mrd",  FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, coa_mrd), STRINGIFY(30) },
301         CONF_PARSER_TERMINATOR
302 };
303 #endif
304
305 static CONF_PARSER home_server_config[] = {
306         { "ipaddr", FR_CONF_OFFSET(PW_TYPE_COMBO_IP_ADDR, home_server_t, ipaddr), NULL },
307         { "ipv4addr", FR_CONF_OFFSET(PW_TYPE_IPV4_ADDR, home_server_t, ipaddr), NULL },
308         { "ipv6addr", FR_CONF_OFFSET(PW_TYPE_IPV6_ADDR, home_server_t, ipaddr), NULL },
309         { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, server), NULL },
310
311         { "port", FR_CONF_OFFSET(PW_TYPE_SHORT, home_server_t, port), "0" },
312
313         { "type", FR_CONF_OFFSET(PW_TYPE_STRING, home_server_t, type_str), NULL },
314
315 #ifdef WITH_TCP
316         { "proto", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, proto_str), NULL },
317 #endif
318
319         { "secret", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_SECRET, home_server_t, secret), NULL },
320
321         { "src_ipaddr", FR_CONF_OFFSET(PW_TYPE_STRING, home_server_t, src_ipaddr_str), NULL },
322
323         { "response_window", FR_CONF_OFFSET(PW_TYPE_TIMEVAL, home_server_t, response_window), "30" },
324         { "response_timeouts", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, max_response_timeouts), "1" },
325         { "max_outstanding", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, max_outstanding), "65536" },
326
327         { "zombie_period", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, zombie_period), "40" },
328
329         { "status_check",  FR_CONF_OFFSET(PW_TYPE_STRING, home_server_t, ping_check_str), "none" },
330         { "ping_check", FR_CONF_OFFSET(PW_TYPE_STRING, home_server_t, ping_check_str), NULL },
331
332         { "ping_interval", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, ping_interval), "30" },
333         { "check_interval", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, ping_interval), NULL },
334
335         { "check_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, ping_timeout), "4" },
336         { "status_check_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, ping_timeout), NULL },
337
338         { "num_answers_to_alive", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, num_pings_to_alive), "3" },
339         { "revive_interval", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, revive_interval), "300" },
340
341         { "username", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, ping_user_name), NULL },
342         { "password", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, ping_user_password), NULL },
343
344 #ifdef WITH_STATS
345         { "historic_average_window", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, ema.window), NULL },
346 #endif
347
348         { "limit", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) limit_config },
349
350 #ifdef WITH_COA
351         { "coa", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) home_server_coa },
352 #endif
353
354         CONF_PARSER_TERMINATOR
355 };
356
357
358 static void null_free(UNUSED void *data)
359 {
360 }
361
362 /*
363  *      Ensure that all of the parameters in the home server are OK.
364  */
365 void realm_home_server_sanitize(home_server_t *home, CONF_SECTION *cs)
366 {
367         CONF_SECTION *parent = NULL;
368
369         FR_INTEGER_BOUND_CHECK("max_outstanding", home->max_outstanding, >=, 8);
370         FR_INTEGER_BOUND_CHECK("max_outstanding", home->max_outstanding, <=, 65536*16);
371
372         FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, >=, 6);
373         FR_INTEGER_BOUND_CHECK("ping_interval", home->ping_interval, <=, 120);
374
375         FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, >=, 0, 1000);
376         FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=, 60, 0);
377         FR_TIMEVAL_BOUND_CHECK("response_window", &home->response_window, <=,
378                                main_config.max_request_time, 0);
379
380         FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, >=, 1);
381         FR_INTEGER_BOUND_CHECK("response_timeouts", home->max_response_timeouts, <=, 1000);
382
383         /*
384          *      Track the minimum response window, so that we can
385          *      correctly set the timers in process.c
386          */
387         if (timercmp(&main_config.init_delay, &home->response_window, >)) {
388                 main_config.init_delay = home->response_window;
389         }
390
391         FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, >=, 1);
392         FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, <=, 120);
393         FR_INTEGER_BOUND_CHECK("zombie_period", home->zombie_period, >=, (uint32_t) home->response_window.tv_sec);
394
395         FR_INTEGER_BOUND_CHECK("num_pings_to_alive", home->num_pings_to_alive, >=, 3);
396         FR_INTEGER_BOUND_CHECK("num_pings_to_alive", home->num_pings_to_alive, <=, 10);
397
398         FR_INTEGER_BOUND_CHECK("check_timeout", home->ping_timeout, >=, 1);
399         FR_INTEGER_BOUND_CHECK("check_timeout", home->ping_timeout, <=, 10);
400
401         FR_INTEGER_BOUND_CHECK("revive_interval", home->revive_interval, >=, 60);
402         FR_INTEGER_BOUND_CHECK("revive_interval", home->revive_interval, <=, 3600);
403
404 #ifdef WITH_COA
405         FR_INTEGER_BOUND_CHECK("coa_irt", home->coa_irt, >=, 1);
406         FR_INTEGER_BOUND_CHECK("coa_irt", home->coa_irt, <=, 5);
407
408         FR_INTEGER_BOUND_CHECK("coa_mrc", home->coa_mrc, <=, 20);
409
410         FR_INTEGER_BOUND_CHECK("coa_mrt", home->coa_mrt, <=, 30);
411
412         FR_INTEGER_BOUND_CHECK("coa_mrd", home->coa_mrd, >=, 5);
413         FR_INTEGER_BOUND_CHECK("coa_mrd", home->coa_mrd, <=, 60);
414 #endif
415
416         FR_INTEGER_BOUND_CHECK("max_connections", home->limit.max_connections, <=, 1024);
417
418 #ifdef WITH_TCP
419         /*
420          *      UDP sockets can't be connection limited.
421          */
422         if (home->proto != IPPROTO_TCP) home->limit.max_connections = 0;
423 #endif
424
425         if ((home->limit.idle_timeout > 0) && (home->limit.idle_timeout < 5))
426                 home->limit.idle_timeout = 5;
427         if ((home->limit.lifetime > 0) && (home->limit.lifetime < 5))
428                 home->limit.lifetime = 5;
429         if ((home->limit.lifetime > 0) && (home->limit.idle_timeout > home->limit.lifetime))
430                 home->limit.idle_timeout = 0;
431
432         /*
433          *      Make sure that this is set.
434          */
435         if (home->src_ipaddr.af == AF_UNSPEC) {
436                 home->src_ipaddr.af = home->ipaddr.af;
437         }
438
439         parent = cf_item_parent(cf_section_to_item(cs));
440         if (parent && strcmp(cf_section_name1(parent), "server") == 0) {
441                 home->parent_server = cf_section_name2(parent);
442         }
443 }
444
445 /** Insert a new home server into the various internal lookup trees
446  *
447  * @param home server to add.
448  * @param cs That defined the home server.
449  * @return true on success else false.
450  */
451 static bool home_server_insert(home_server_t *home, CONF_SECTION *cs)
452 {
453         if (home->name && !rbtree_insert(home_servers_byname, home)) {
454                 cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name);
455                 return false;
456         }
457
458         if (!home->server && !rbtree_insert(home_servers_byaddr, home)) {
459                 rbtree_deletebydata(home_servers_byname, home);
460                 cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name);
461                 return false;
462         }
463
464 #ifdef WITH_STATS
465         home->number = home_server_max_number++;
466         if (!rbtree_insert(home_servers_bynumber, home)) {
467                 rbtree_deletebydata(home_servers_byname, home);
468                 if (home->ipaddr.af != AF_UNSPEC) {
469                         rbtree_deletebydata(home_servers_byname, home);
470                 }
471                 cf_log_err_cs(cs, "Internal error %d adding home server %s", __LINE__, home->log_name);
472                 return false;
473         }
474 #endif
475
476         return true;
477 }
478
479 /** Add an already allocate home_server_t to the various trees
480  *
481  * @param home server to add.
482  * @return true on success, else false on error.
483  */
484 bool realm_home_server_add(home_server_t *home)
485 {
486         /*
487          *      The structs aren't mutex protected.  Refuse to destroy
488          *      the server.
489          */
490         if (event_loop_started && !realm_config->dynamic) {
491                 ERROR("Failed to add dynamic home server, \"dynamic = yes\" must be set in proxy.conf");
492                 return false;
493         }
494
495         if (home->name && (rbtree_finddata(home_servers_byname, home) != NULL)) {
496                 cf_log_err_cs(home->cs, "Duplicate home server name %s", home->name);
497                 return false;
498         }
499
500         if (!home->server && (rbtree_finddata(home_servers_byaddr, home) != NULL)) {
501                 char buffer[INET6_ADDRSTRLEN + 3];
502
503                 inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr, buffer, sizeof(buffer));
504
505                 cf_log_err_cs(home->cs, "Duplicate home server address%s%s%s: %s:%s%s/%i",
506                               home->name ? " (already in use by" : "",
507                               home->name ? home->name : "",
508                               home->name ? ")" : "",
509                               buffer,
510                               fr_int2str(home_proto, home->proto, "<INVALID>"),
511 #ifdef WITH_TLS
512                               home->tls ? "+tls" : "",
513 #else
514                               "",
515 #endif
516                               home->port);
517
518                 return false;
519         }
520
521         if (!home_server_insert(home, home->cs)) return false;
522
523         /*
524          *      Dual home servers cause us to auto-create an
525          *      accounting server for UDP sockets, and leave
526          *      everything alone for TLS sockets.
527          */
528         if (home->dual
529 #ifdef WITH_TLS
530             && !home->tls
531 #endif
532 ) {
533                 home_server_t *home2 = talloc(talloc_parent(home), home_server_t);
534
535                 memcpy(home2, home, sizeof(*home2));
536
537                 home2->type = HOME_TYPE_ACCT;
538                 home2->dual = true;
539                 home2->port++;
540
541                 home2->ping_user_password = NULL;
542                 home2->cs = home->cs;
543                 home2->parent_server = home->parent_server;
544
545                 if (!home_server_insert(home2, home->cs)) {
546                         talloc_free(home2);
547                         return false;
548                 }
549         }
550
551         /*
552          *      Mark it as already processed
553          */
554         cf_data_add(home->cs, "home_server", (void *)null_free, null_free);
555
556         return true;
557 }
558
559 /** Alloc a new home server defined by a CONF_SECTION
560  *
561  * @param ctx to allocate home_server_t in.
562  * @param rc Realm config, may be NULL in which case the global realm_config will be used.
563  * @param cs Configuration section containing home server parameters.
564  * @return a new home_server_t alloced in the context of the realm_config, or NULL on error.
565  */
566 home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SECTION *cs)
567 {
568         home_server_t   *home;
569         CONF_SECTION    *tls;
570
571         if (!rc) rc = realm_config; /* Use the global config */
572
573         home = talloc_zero(ctx, home_server_t);
574         home->name = cf_section_name2(cs);
575         home->log_name = talloc_typed_strdup(home, home->name);
576         home->cs = cs;
577         home->state = HOME_STATE_UNKNOWN;
578         home->proto = IPPROTO_UDP;
579
580         /*
581          *      Parse the configuration into the home server
582          *      struct.
583          */
584         if (cf_section_parse(cs, home, home_server_config) < 0) goto error;
585
586         /*
587          *      It has an IP address, it must be a remote server.
588          */
589         if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) {
590                 if (fr_inaddr_any(&home->ipaddr) == 1) {
591                         cf_log_err_cs(cs, "Wildcard '*' addresses are not permitted for home servers");
592                         goto error;
593                 }
594
595                 if (!home->log_name) {
596                         char buffer[INET6_ADDRSTRLEN + 3];
597
598                         fr_ntop(buffer, sizeof(buffer), &home->ipaddr);
599
600                         home->log_name = talloc_asprintf(home, "%s:%i", buffer, home->port);
601                 }
602         /*
603          *      If it has a 'virtual_Server' config item, it's
604          *      a loopback into a virtual server.
605          */
606         } else if (cf_pair_find(cs, "virtual_server") != NULL) {
607                 home->ipaddr.af = AF_UNSPEC;    /* mark ipaddr as unused */
608
609                 if (!home->server) {
610                         cf_log_err_cs(cs, "Invalid value for virtual_server");
611                         goto error;
612                 }
613
614                 /*
615                  *      Try and find a 'server' section off the root of
616                  *      the config with a name that matches the
617                  *      virtual_server.
618                  */
619                 if (!cf_section_sub_find_name2(rc->cs, "server", home->server)) {
620                         cf_log_err_cs(cs, "No such server %s", home->server);
621                         goto error;
622                 }
623
624                 home->secret = "";
625                 home->log_name = talloc_typed_strdup(home, home->server);
626         /*
627          *      Otherwise it's an invalid config section and we
628          *      raise an error.
629          */
630         } else {
631                 cf_log_err_cs(cs, "No ipaddr, ipv4addr, ipv6addr, or virtual_server defined "
632                               "for home server");
633         error:
634                 talloc_free(home);
635                 return false;
636         }
637
638         {
639                 home_type_t type = HOME_TYPE_AUTH_ACCT;
640
641                 if (home->type_str) type = fr_str2int(home_server_types, home->type_str, HOME_TYPE_INVALID);
642
643                 home->type = type;
644
645                 switch (type) {
646                 case HOME_TYPE_AUTH_ACCT:
647                         home->dual = true;
648                         break;
649
650                 case HOME_TYPE_AUTH:
651                 case HOME_TYPE_ACCT:
652                         break;
653
654 #ifdef WITH_COA
655                 case HOME_TYPE_COA:
656                         if (home->server != NULL) {
657                                 cf_log_err_cs(cs, "Home servers of type \"coa\" cannot point to a virtual server");
658                                 goto error;
659                         }
660                         break;
661 #endif
662
663                 case HOME_TYPE_INVALID:
664                         cf_log_err_cs(cs, "Invalid type \"%s\" for home server %s", home->type_str, home->log_name);
665                         goto error;
666                 }
667         }
668
669         {
670                 home_ping_check_t type = HOME_PING_CHECK_NONE;
671
672                 if (home->ping_check_str) type = fr_str2int(home_ping_check, home->ping_check_str,
673                                                             HOME_PING_CHECK_INVALID);
674
675                 switch (type) {
676                 case HOME_PING_CHECK_STATUS_SERVER:
677                 case HOME_PING_CHECK_NONE:
678                         break;
679
680                 case HOME_PING_CHECK_REQUEST:
681                         if (!home->ping_user_name) {
682                                 cf_log_err_cs(cs, "You must supply a 'username' to enable status_check=request");
683                                 goto error;
684                         }
685
686                         if ((home->type == HOME_TYPE_AUTH) && !home->ping_user_password) {
687                                 cf_log_err_cs(cs, "You must supply a 'password' to enable status_check=request");
688                                 goto error;
689                         }
690
691                         break;
692
693                 case HOME_PING_CHECK_INVALID:
694                         cf_log_err_cs(cs, "Invalid status_check \"%s\" for home server %s",
695                                       home->ping_check_str, home->log_name);
696                         goto error;
697                 }
698
699                 home->ping_check = type;
700         }
701
702         {
703                 int proto = IPPROTO_UDP;
704
705                 if (home->proto_str) proto = fr_str2int(home_proto, home->proto_str, -1);
706
707                 switch (proto) {
708                 case IPPROTO_UDP:
709                         home_servers_udp = true;
710                         break;
711
712                 case IPPROTO_TCP:
713 #ifndef WITH_TCP
714                         cf_log_err_cs(cs, "Server not built with support for RADIUS over TCP");
715                         goto error;
716 #endif
717                         if (home->ping_check != HOME_PING_CHECK_NONE) {
718                                 cf_log_err_cs(cs, "Only 'status_check = none' is allowed for home "
719                                               "servers with 'proto = tcp'");
720                                 goto error;
721                         }
722                         break;
723
724                 default:
725                         cf_log_err_cs(cs, "Unknown proto \"%s\"", home->proto_str);
726                         goto error;
727                 }
728
729                 home->proto = proto;
730         }
731
732         if (!home->server && rbtree_finddata(home_servers_byaddr, home)) {
733                 cf_log_err_cs(cs, "Duplicate home server");
734                 goto error;
735         }
736
737         /*
738          *      Check the TLS configuration.
739          */
740         tls = cf_section_sub_find(cs, "tls");
741 #ifndef WITH_TLS
742         if (tls) {
743                 cf_log_err_cs(cs, "TLS transport is not available in this executable");
744                 goto error;
745         }
746 #endif
747
748         /*
749          *      If were doing RADSEC (tls+tcp) the secret should default
750          *      to radsec, else a secret must be set.
751          */
752         if (!home->secret) {
753 #ifdef WITH_TLS
754                 if (tls && (home->proto == IPPROTO_TCP)) {
755                         home->secret = "radsec";
756                 } else
757 #endif
758                 {
759                         cf_log_err_cs(cs, "No shared secret defined for home server %s", home->log_name);
760                         goto error;
761                 }
762         }
763
764         /*
765          *      Virtual servers have some TLS restrictions.
766          */
767         if (home->server) {
768                 if (tls) {
769                         cf_log_err_cs(cs, "Virtual home_servers cannot have a \"tls\" subsection");
770                         goto error;
771                 }
772         } else {
773                 /*
774                  *      If the home is not a virtual server, guess the port
775                  *      and look up the source ip address.
776                  */
777                 rad_assert(home->ipaddr.af != AF_UNSPEC);
778
779 #ifdef WITH_TLS
780                 if (tls && (home->proto != IPPROTO_TCP)) {
781                         cf_log_err_cs(cs, "TLS transport is not available for UDP sockets");
782                         goto error;
783                 }
784 #endif
785
786                 /*
787                  *      Set the default port if necessary.
788                  */
789                 if (home->port == 0) {
790                         char buffer[INET6_ADDRSTRLEN + 3];
791
792                         /*
793                          *      For RADSEC we use the special RADIUS over TCP/TLS port
794                          *      for both accounting and authentication, but for some
795                          *      bizarre reason for RADIUS over plain TCP we use separate
796                          *      ports 1812 and 1813.
797                          */
798 #ifdef WITH_TLS
799                         if (tls) {
800                                 home->port = PW_RADIUS_TLS_PORT;
801                         } else
802 #endif
803                         switch (home->type) {
804                         default:
805                                 rad_assert(0);
806                                 /* FALL-THROUGH */
807
808                         case HOME_TYPE_AUTH:
809                                 home->port = PW_AUTH_UDP_PORT;
810                                 break;
811
812                         case HOME_TYPE_ACCT:
813                                 home->port = PW_ACCT_UDP_PORT;
814                                 break;
815
816                         case HOME_TYPE_COA:
817                                 home->port = PW_COA_UDP_PORT;
818                                 break;
819                         }
820
821                         /*
822                          *      Now that we have a real port, use that.
823                          */
824                         rad_const_free(home->log_name);
825
826                         fr_ntop(buffer, sizeof(buffer), &home->ipaddr);
827
828                         home->log_name = talloc_asprintf(home, "%s:%i", buffer, home->port);
829                 }
830
831                 /*
832                  *      If we have a src_ipaddr_str resolve it to
833                  *      the same address family as the destination
834                  *      IP.
835                  */
836                 if (home->src_ipaddr_str) {
837                         if (ip_hton(&home->src_ipaddr, home->ipaddr.af, home->src_ipaddr_str, false) < 0) {
838                                 cf_log_err_cs(cs, "Failed parsing src_ipaddr");
839                                 goto error;
840                         }
841                 /*
842                  *      Source isn't specified, set it to the
843                  *      correct address family, but leave it as
844                  *      zeroes.
845                  */
846                 } else {
847                         home->src_ipaddr.af = home->ipaddr.af;
848                 }
849
850 #ifdef WITH_TLS
851                 /*
852                  *      Parse the SSL client configuration.
853                  */
854                 if (tls) {
855                         home->tls = tls_client_conf_parse(tls);
856                         if (!home->tls) {
857                                 goto error;
858                         }
859                 }
860 #endif
861         } /* end of parse home server */
862
863         realm_home_server_sanitize(home, cs);
864
865         return home;
866 }
867
868 /** Fixup a client configuration section to specify a home server
869  *
870  * This is used to create the equivalent CoA home server entry for a client,
871  * so that the server can originate CoA messages.
872  *
873  * The server section automatically inherits the following fields from the client:
874  *  - ipaddr/ipv4addr/ipv6addr
875  *  - secret
876  *  - src_ipaddr
877  *
878  * @note new CONF_SECTION will be allocated in the context of the client, but the client
879  *      CONF_SECTION will not be modified.
880  *
881  * @param client CONF_SECTION to inherit values from.
882  * @return a new server CONF_SCTION, or a pointer to the existing CONF_SECTION in the client.
883  */
884 CONF_SECTION *home_server_cs_afrom_client(CONF_SECTION *client)
885 {
886         CONF_SECTION *server, *cs;
887         CONF_PAIR *cp;
888
889         /*
890          *      Alloc a plain home server for both cases
891          *
892          *      There's no way these can be referenced by a pool,
893          *      and they may conflict with home servers in proxy.conf
894          *      so it's easier to not set a name.
895          */
896
897         /*
898          *
899          *      Duplicate the server section, so we don't mangle
900          *      the client CONF_SECTION we were passed.
901          */
902         cs = cf_section_sub_find(client, "coa_server");
903         if (cs) {
904                 server = cf_section_dup(client, cs, "home_server", NULL, true);
905         } else {
906                 server = cf_section_alloc(client, "home_server", NULL);
907         }
908
909         if (!cs || (!cf_pair_find(cs, "ipaddr") && !cf_pair_find(cs, "ipv4addr") && !cf_pair_find(cs, "ipv6addr"))) {
910                 cp = cf_pair_find(client, "ipaddr");
911                 if (!cp) cp = cf_pair_find(client, "ipv4addr");
912                 if (!cp) cp = cf_pair_find(client, "ipv6addr");
913
914                 cf_pair_add(server, cf_pair_dup(server, cp));
915         }
916
917         if (!cs || !cf_pair_find(cs, "secret")) {
918                 cp = cf_pair_find(client, "secret");
919                 if (cp) cf_pair_add(server, cp);
920         }
921
922         if (!cs || !cf_pair_find(cs, "src_ipaddr")) {
923                 cp = cf_pair_find(client, "src_ipaddr");
924                 if (cp) cf_pair_add(server, cf_pair_dup(server, cp));
925         }
926
927         if (!cs || !(cp = cf_pair_find(cs, "type"))) {
928                 cp = cf_pair_alloc(server, "type", "coa", T_OP_EQ, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
929                 if (cp) cf_pair_add(server, cf_pair_dup(server, cp));
930         } else if (strcmp(cf_pair_value(cp), "coa") != 0) {
931                 talloc_free(server);
932                 cf_log_err_cs(server, "server.type must be \"coa\"");
933                 return NULL;
934         }
935
936         return server;
937 }
938
939 static home_pool_t *server_pool_alloc(char const *name, home_pool_type_t type,
940                                       home_type_t server_type, int num_home_servers)
941 {
942         home_pool_t *pool;
943
944         pool = rad_malloc(sizeof(*pool) + (sizeof(pool->servers[0]) * num_home_servers));
945         if (!pool) return NULL; /* just for pairanoia */
946
947         memset(pool, 0, sizeof(*pool) + (sizeof(pool->servers[0]) * num_home_servers));
948
949         pool->name = name;
950         pool->type = type;
951         pool->server_type = server_type;
952         pool->num_home_servers = num_home_servers;
953
954         return pool;
955 }
956
957 /*
958  * Ensure any home_server clauses in a home_server_pool section reference
959  * defined home servers, which should already have been created, regardless
960  * of where they appear in the configuration.
961  */
962 static int pool_check_home_server(UNUSED realm_config_t *rc, CONF_PAIR *cp,
963                                   char const *name, home_type_t server_type,
964                                   home_server_t **phome)
965 {
966         home_server_t myhome, *home;
967
968         if (!name) {
969                 cf_log_err_cp(cp,
970                            "No value given for home_server");
971                 return 0;
972         }
973
974         myhome.name = name;
975         myhome.type = server_type;
976         home = rbtree_finddata(home_servers_byname, &myhome);
977         if (home) {
978                 *phome = home;
979                 return 1;
980         }
981
982         switch (server_type) {
983         case HOME_TYPE_AUTH:
984         case HOME_TYPE_ACCT:
985                 myhome.type = HOME_TYPE_AUTH_ACCT;
986                 home = rbtree_finddata(home_servers_byname, &myhome);
987                 if (home) {
988                         *phome = home;
989                         return 1;
990                 }
991                 break;
992
993         default:
994                 break;
995         }
996
997         cf_log_err_cp(cp, "Unknown home_server \"%s\".", name);
998         return 0;
999 }
1000
1001
1002 #ifndef HAVE_PTHREAD_H
1003 void realm_pool_free(home_pool_t *pool)
1004 {
1005         if (!event_loop_started) return;
1006         if (!realm_config->dynamic) return;
1007
1008         talloc_free(pool);
1009 }
1010 #else  /* HAVE_PTHREAD_H */
1011 typedef struct pool_list_t pool_list_t;
1012
1013 struct pool_list_t {
1014         pool_list_t     *next;
1015         home_pool_t     *pool;
1016         time_t          when;
1017 };
1018
1019 static bool             pool_free_init = false;
1020 static pthread_mutex_t  pool_free_mutex;
1021 static pool_list_t      *pool_list = NULL;
1022
1023 void realm_pool_free(home_pool_t *pool)
1024 {
1025         int i;
1026         time_t now;
1027         pool_list_t *this, **last;
1028
1029         if (!event_loop_started) return;
1030         if (!realm_config->dynamic) return;
1031
1032         if (pool) {
1033                 /*
1034                  *      Double-check that the realm wasn't loaded from the
1035                  *      configuration files.
1036                  */
1037                 for (i = 0; i < pool->num_home_servers; i++) {
1038                         if (pool->servers[i]->cs) {
1039                                 rad_assert(0 == 1);
1040                                 return;
1041                         }
1042                 }
1043         }
1044
1045         if (!pool_free_init) {
1046                 pthread_mutex_init(&pool_free_mutex, NULL);
1047                 pool_free_init = true;
1048         }
1049
1050         /*
1051          *      Ensure only one caller at a time is freeing a pool.
1052          */
1053         pthread_mutex_lock(&pool_free_mutex);
1054
1055         /*
1056          *      Free all of the pools.
1057          */
1058         if (!pool) {
1059                 while ((this = pool_list) != NULL) {
1060                         pool_list = this->next;
1061                         talloc_free(this->pool);
1062                         talloc_free(this);
1063                 }
1064                 pthread_mutex_unlock(&pool_free_mutex);
1065                 return;
1066         }
1067
1068         now = time(NULL);
1069
1070         /*
1071          *      Free the oldest pool(s)
1072          */
1073         while ((this = pool_list) != NULL) {
1074                 if (this->when > now) break;
1075
1076                 pool_list = this->next;
1077                 talloc_free(this->pool);
1078                 talloc_free(this);
1079         }
1080
1081         /*
1082          *      Add this pool to the end of the list.
1083          */
1084         for (last = &pool_list;
1085              *last != NULL;
1086              last = &((*last))->next) {
1087                 /* do nothing */
1088         }
1089
1090         *last = this = talloc(NULL, pool_list_t);
1091         if (!this) {
1092                 talloc_free(pool); /* hope for the best */
1093                 pthread_mutex_unlock(&pool_free_mutex);
1094                 return;
1095         }
1096
1097         this->next = NULL;
1098         this->when = now + 60;
1099         this->pool = pool;
1100         pthread_mutex_unlock(&pool_free_mutex);
1101 }
1102 #endif  /* HAVE_PTHREAD_H */
1103
1104 int realm_pool_add(home_pool_t *pool, UNUSED CONF_SECTION *cs)
1105 {
1106         /*
1107          *      The structs aren't mutex protected.  Refuse to destroy
1108          *      the server.
1109          */
1110         if (event_loop_started && !realm_config->dynamic) {
1111                 DEBUG("Must set \"dynamic = true\" in proxy.conf");
1112                 return 0;
1113         }
1114
1115         if (!rbtree_insert(home_pools_byname, pool)) {
1116                 rad_assert("Internal sanity check failed" == NULL);
1117                 return 0;
1118         }
1119
1120         return 1;
1121 }
1122
1123 static int server_pool_add(realm_config_t *rc,
1124                            CONF_SECTION *cs, home_type_t server_type, bool do_print)
1125 {
1126         char const *name2;
1127         home_pool_t *pool = NULL;
1128         char const *value;
1129         CONF_PAIR *cp;
1130         int num_home_servers;
1131         home_server_t *home;
1132
1133         name2 = cf_section_name1(cs);
1134         if (!name2 || ((strcasecmp(name2, "server_pool") != 0) &&
1135                        (strcasecmp(name2, "home_server_pool") != 0))) {
1136                 cf_log_err_cs(cs,
1137                            "Section is not a home_server_pool");
1138                 return 0;
1139         }
1140
1141         name2 = cf_section_name2(cs);
1142         if (!name2) {
1143                 cf_log_err_cs(cs,
1144                            "Server pool section is missing a name");
1145                 return 0;
1146         }
1147
1148         /*
1149          *      Count the home servers and initalize them.
1150          */
1151         num_home_servers = 0;
1152         for (cp = cf_pair_find(cs, "home_server");
1153              cp != NULL;
1154              cp = cf_pair_find_next(cs, cp, "home_server")) {
1155                 num_home_servers++;
1156
1157                 if (!pool_check_home_server(rc, cp, cf_pair_value(cp),
1158                                             server_type, &home)) {
1159                         return 0;
1160                 }
1161         }
1162
1163         if (num_home_servers == 0) {
1164                 cf_log_err_cs(cs,
1165                            "No home servers defined in pool %s",
1166                            name2);
1167                 goto error;
1168         }
1169
1170         pool = server_pool_alloc(name2, HOME_POOL_FAIL_OVER, server_type,
1171                                  num_home_servers);
1172         if (!pool) {
1173                 cf_log_err_cs(cs, "Failed allocating memory for pool");
1174                 goto error;
1175         }
1176         pool->cs = cs;
1177
1178
1179         /*
1180          *      Fallback servers must be defined, and must be
1181          *      virtual servers.
1182          */
1183         cp = cf_pair_find(cs, "fallback");
1184         if (cp) {
1185 #ifdef WITH_COA
1186                 if (server_type == HOME_TYPE_COA) {
1187                         cf_log_err_cs(cs, "Home server pools of type \"coa\" cannot have a fallback virtual server");
1188                         goto error;
1189                 }
1190 #endif
1191
1192                 if (!pool_check_home_server(rc, cp, cf_pair_value(cp), server_type, &pool->fallback)) {
1193                         goto error;
1194                 }
1195
1196                 if (!pool->fallback->server) {
1197                         cf_log_err_cs(cs, "Fallback home_server %s does NOT contain a virtual_server directive",
1198                                       pool->fallback->log_name);
1199                         goto error;
1200                 }
1201         }
1202
1203         if (do_print) cf_log_info(cs, " home_server_pool %s {", name2);
1204
1205         cp = cf_pair_find(cs, "type");
1206         if (cp) {
1207                 static FR_NAME_NUMBER pool_types[] = {
1208                         { "load-balance", HOME_POOL_LOAD_BALANCE },
1209
1210                         { "fail-over", HOME_POOL_FAIL_OVER },
1211                         { "fail_over", HOME_POOL_FAIL_OVER },
1212
1213                         { "round-robin", HOME_POOL_LOAD_BALANCE },
1214                         { "round_robin", HOME_POOL_LOAD_BALANCE },
1215
1216                         { "client-balance", HOME_POOL_CLIENT_BALANCE },
1217                         { "client-port-balance", HOME_POOL_CLIENT_PORT_BALANCE },
1218                         { "keyed-balance", HOME_POOL_KEYED_BALANCE },
1219                         { NULL, 0 }
1220                 };
1221
1222                 value = cf_pair_value(cp);
1223                 if (!value) {
1224                         cf_log_err_cp(cp,
1225                                    "No value given for type");
1226                         goto error;
1227                 }
1228
1229                 pool->type = fr_str2int(pool_types, value, 0);
1230                 if (!pool->type) {
1231                         cf_log_err_cp(cp,
1232                                    "Unknown type \"%s\".",
1233                                    value);
1234                         goto error;
1235                 }
1236
1237                 if (do_print) cf_log_info(cs, "\ttype = %s", value);
1238         }
1239
1240         cp = cf_pair_find(cs, "virtual_server");
1241         if (cp) {
1242                 pool->virtual_server = cf_pair_value(cp);
1243                 if (!pool->virtual_server) {
1244                         cf_log_err_cp(cp, "No value given for virtual_server");
1245                         goto error;
1246                 }
1247
1248                 if (do_print) {
1249                         cf_log_info(cs, "\tvirtual_server = %s", pool->virtual_server);
1250                 }
1251
1252                 if (!cf_section_sub_find_name2(rc->cs, "server", pool->virtual_server)) {
1253                         cf_log_err_cp(cp, "No such server %s", pool->virtual_server);
1254                         goto error;
1255                 }
1256
1257         }
1258
1259         num_home_servers = 0;
1260         for (cp = cf_pair_find(cs, "home_server");
1261              cp != NULL;
1262              cp = cf_pair_find_next(cs, cp, "home_server")) {
1263                 home_server_t myhome;
1264
1265                 value = cf_pair_value(cp);
1266
1267                 memset(&myhome, 0, sizeof(myhome));
1268                 myhome.name = value;
1269                 myhome.type = server_type;
1270
1271                 home = rbtree_finddata(home_servers_byname, &myhome);
1272                 if (!home) {
1273                         switch (server_type) {
1274                         case HOME_TYPE_AUTH:
1275                         case HOME_TYPE_ACCT:
1276                                 myhome.type = HOME_TYPE_AUTH_ACCT;
1277                                 home = rbtree_finddata(home_servers_byname, &myhome);
1278                                 break;
1279
1280                         default:
1281                                 break;
1282                         }
1283                 }
1284
1285                 if (!home) {
1286                         ERROR("Failed to find home server %s", value);
1287                         goto error;
1288                 }
1289
1290                 if (do_print) cf_log_info(cs, "\thome_server = %s", home->name);
1291                 pool->servers[num_home_servers++] = home;
1292         } /* loop over home_server's */
1293
1294         if (pool->fallback && do_print) {
1295                 cf_log_info(cs, "\tfallback = %s", pool->fallback->name);
1296         }
1297
1298         if (!realm_pool_add(pool, cs)) goto error;
1299
1300         if (do_print) cf_log_info(cs, " }");
1301
1302         cf_data_add(cs, "home_server_pool", pool, free);
1303
1304         rad_assert(pool->server_type != 0);
1305
1306         return 1;
1307
1308  error:
1309         if (do_print) cf_log_info(cs, " }");
1310         free(pool);
1311         return 0;
1312 }
1313 #endif
1314
1315 static int old_server_add(realm_config_t *rc, CONF_SECTION *cs,
1316                           char const *realm,
1317                           char const *name, char const *secret,
1318                           home_pool_type_t ldflag, home_pool_t **pool_p,
1319                           home_type_t type, char const *server)
1320 {
1321 #ifdef WITH_PROXY
1322         int i, insert_point, num_home_servers;
1323         home_server_t myhome, *home;
1324         home_pool_t mypool, *pool;
1325         CONF_SECTION *subcs;
1326 #else
1327         (void) rc;              /* -Wunused */
1328         (void) realm;
1329         (void) secret;
1330         (void) ldflag;
1331         (void) type;
1332         (void) server;
1333 #endif
1334
1335         /*
1336          *      LOCAL realms get sanity checked, and nothing else happens.
1337          */
1338         if (strcmp(name, "LOCAL") == 0) {
1339                 if (*pool_p) {
1340                         cf_log_err_cs(cs, "Realm \"%s\" cannot be both LOCAL and remote", name);
1341                         return 0;
1342                 }
1343                 return 1;
1344         }
1345
1346 #ifndef WITH_PROXY
1347         return 0;               /* Not proxying.  Can't do non-LOCAL realms */
1348
1349 #else
1350         mypool.name = realm;
1351         mypool.server_type = type;
1352         pool = rbtree_finddata(home_pools_byname, &mypool);
1353         if (pool) {
1354                 if (pool->type != ldflag) {
1355                         cf_log_err_cs(cs, "Inconsistent ldflag for server pool \"%s\"", name);
1356                         return 0;
1357                 }
1358
1359                 if (pool->server_type != type) {
1360                         cf_log_err_cs(cs, "Inconsistent home server type for server pool \"%s\"", name);
1361                         return 0;
1362                 }
1363         }
1364
1365         myhome.name = name;
1366         myhome.type = type;
1367         home = rbtree_finddata(home_servers_byname, &myhome);
1368         if (home) {
1369                 WARN("Please use pools instead of authhost and accthost");
1370
1371                 if (secret && (strcmp(home->secret, secret) != 0)) {
1372                         cf_log_err_cs(cs, "Inconsistent shared secret for home server \"%s\"", name);
1373                         return 0;
1374                 }
1375
1376                 if (home->type != type) {
1377                         cf_log_err_cs(cs, "Inconsistent type for home server \"%s\"", name);
1378                         return 0;
1379                 }
1380
1381                 /*
1382                  *      See if the home server is already listed
1383                  *      in the pool.  If so, do nothing else.
1384                  */
1385                 if (pool) for (i = 0; i < pool->num_home_servers; i++) {
1386                         if (pool->servers[i] == home) {
1387                                 return 1;
1388                         }
1389                 }
1390         }
1391
1392         /*
1393          *      If we do have a pool, check that there is room to
1394          *      insert the home server we've found, or the one that we
1395          *      create here.
1396          *
1397          *      Note that we insert it into the LAST available
1398          *      position, in order to maintain the same order as in
1399          *      the configuration files.
1400          */
1401         insert_point = -1;
1402         if (pool) {
1403                 for (i = pool->num_home_servers - 1; i >= 0; i--) {
1404                         if (pool->servers[i]) break;
1405
1406                         if (!pool->servers[i]) {
1407                                 insert_point = i;
1408                         }
1409                 }
1410
1411                 if (insert_point < 0) {
1412                         cf_log_err_cs(cs, "No room in pool to add home server \"%s\".  Please update the realm configuration to use the new-style home servers and server pools.", name);
1413                         return 0;
1414                 }
1415         }
1416
1417         /*
1418          *      No home server, allocate one.
1419          */
1420         if (!home) {
1421                 char const *p;
1422                 char *q;
1423
1424                 home = talloc_zero(rc, home_server_t);
1425                 home->name = name;
1426                 home->type = type;
1427                 home->secret = secret;
1428                 home->cs = cs;
1429                 home->proto = IPPROTO_UDP;
1430
1431                 p = strchr(name, ':');
1432                 if (!p) {
1433                         if (type == HOME_TYPE_AUTH) {
1434                                 home->port = PW_AUTH_UDP_PORT;
1435                         } else {
1436                                 home->port = PW_ACCT_UDP_PORT;
1437                         }
1438
1439                         p = name;
1440                         q = NULL;
1441
1442                 } else if (p == name) {
1443                         cf_log_err_cs(cs, "Invalid hostname %s", name);
1444                         talloc_free(home);
1445                         return 0;
1446                 } else {
1447                         unsigned long port = strtoul(p + 1, NULL, 0);
1448                         if ((port == 0) || (port > 65535)) {
1449                                 cf_log_err_cs(cs, "Invalid port %s", p + 1);
1450                                 talloc_free(home);
1451                                 return 0;
1452                         }
1453
1454                         home->port = (uint16_t)port;
1455                         q = talloc_array(home, char, (p - name) + 1);
1456                         memcpy(q, name, (p - name));
1457                         q[p - name] = '\0';
1458                         p = q;
1459                 }
1460
1461                 if (!server) {
1462                         if (ip_hton(&home->ipaddr, AF_UNSPEC, p, false) < 0) {
1463                                 cf_log_err_cs(cs,
1464                                            "Failed looking up hostname %s.",
1465                                            p);
1466                                 talloc_free(home);
1467                                 talloc_free(q);
1468                                 return 0;
1469                         }
1470                         home->src_ipaddr.af = home->ipaddr.af;
1471                 } else {
1472                         home->ipaddr.af = AF_UNSPEC;
1473                         home->server = server;
1474                 }
1475                 talloc_free(q);
1476
1477                 /*
1478                  *      Use the old-style configuration.
1479                  */
1480                 home->max_outstanding = 65535*16;
1481                 home->zombie_period = rc->retry_delay * rc->retry_count;
1482                 if (home->zombie_period < 2) home->zombie_period = 30;
1483                 home->response_window.tv_sec = home->zombie_period - 1;
1484                 home->response_window.tv_usec = 0;
1485
1486                 home->ping_check = HOME_PING_CHECK_NONE;
1487
1488                 home->revive_interval = rc->dead_time;
1489
1490                 if (rbtree_finddata(home_servers_byaddr, home)) {
1491                         cf_log_err_cs(cs, "Home server %s has the same IP address and/or port as another home server.", name);
1492                         talloc_free(home);
1493                         return 0;
1494                 }
1495
1496                 if (!rbtree_insert(home_servers_byname, home)) {
1497                         cf_log_err_cs(cs, "Internal error %d adding home server %s.", __LINE__, name);
1498                         talloc_free(home);
1499                         return 0;
1500                 }
1501
1502                 if (!rbtree_insert(home_servers_byaddr, home)) {
1503                         rbtree_deletebydata(home_servers_byname, home);
1504                         cf_log_err_cs(cs, "Internal error %d adding home server %s.", __LINE__, name);
1505                         talloc_free(home);
1506                         return 0;
1507                 }
1508
1509 #ifdef WITH_STATS
1510                 home->number = home_server_max_number++;
1511                 if (!rbtree_insert(home_servers_bynumber, home)) {
1512                         rbtree_deletebydata(home_servers_byname, home);
1513                         if (home->ipaddr.af != AF_UNSPEC) {
1514                                 rbtree_deletebydata(home_servers_byname, home);
1515                         }
1516                         cf_log_err_cs(cs,
1517                                    "Internal error %d adding home server %s.",
1518                                    __LINE__, name);
1519                         talloc_free(home);
1520                         return 0;
1521                 }
1522 #endif
1523         }
1524
1525         /*
1526          *      We now have a home server, see if we can insert it
1527          *      into pre-existing pool.
1528          */
1529         if (insert_point >= 0) {
1530                 rad_assert(pool != NULL);
1531                 pool->servers[insert_point] = home;
1532                 return 1;
1533         }
1534
1535         rad_assert(pool == NULL);
1536         rad_assert(home != NULL);
1537
1538         /*
1539          *      Count the old-style realms of this name.
1540          */
1541         num_home_servers = 0;
1542         for (subcs = cf_section_find_next(cs, NULL, "realm");
1543              subcs != NULL;
1544              subcs = cf_section_find_next(cs, subcs, "realm")) {
1545                 char const *this = cf_section_name2(subcs);
1546
1547                 if (!this || (strcmp(this, realm) != 0)) continue;
1548                 num_home_servers++;
1549         }
1550
1551         if (num_home_servers == 0) {
1552                 cf_log_err_cs(cs, "Internal error counting pools for home server %s.", name);
1553                 talloc_free(home);
1554                 return 0;
1555         }
1556
1557         pool = server_pool_alloc(realm, ldflag, type, num_home_servers);
1558         if (!pool) {
1559                 cf_log_err_cs(cs, "Out of memory");
1560                 return 0;
1561         }
1562
1563         pool->cs = cs;
1564
1565         pool->servers[0] = home;
1566
1567         if (!rbtree_insert(home_pools_byname, pool)) {
1568                 rad_assert("Internal sanity check failed" == NULL);
1569                 return 0;
1570         }
1571
1572         *pool_p = pool;
1573
1574         return 1;
1575 #endif
1576 }
1577
1578 static int old_realm_config(realm_config_t *rc, CONF_SECTION *cs, REALM *r)
1579 {
1580         char const *host;
1581         char const *secret = NULL;
1582         home_pool_type_t ldflag;
1583         CONF_PAIR *cp;
1584
1585         cp = cf_pair_find(cs, "ldflag");
1586         ldflag = HOME_POOL_FAIL_OVER;
1587         if (cp) {
1588                 host = cf_pair_value(cp);
1589                 if (!host) {
1590                         cf_log_err_cp(cp, "No value specified for ldflag");
1591                         return 0;
1592                 }
1593
1594                 if (strcasecmp(host, "fail_over") == 0) {
1595                         cf_log_info(cs, "\tldflag = fail_over");
1596
1597                 } else if (strcasecmp(host, "round_robin") == 0) {
1598                         ldflag = HOME_POOL_LOAD_BALANCE;
1599                         cf_log_info(cs, "\tldflag = round_robin");
1600
1601                 } else {
1602                         cf_log_err_cs(cs, "Unknown value \"%s\" for ldflag", host);
1603                         return 0;
1604                 }
1605         } /* else don't print it. */
1606
1607         /*
1608          *      Allow old-style if it doesn't exist, or if it exists and
1609          *      it's LOCAL.
1610          */
1611         cp = cf_pair_find(cs, "authhost");
1612         if (cp) {
1613                 host = cf_pair_value(cp);
1614                 if (!host) {
1615                         cf_log_err_cp(cp, "No value specified for authhost");
1616                         return 0;
1617                 }
1618
1619                 if (strcmp(host, "LOCAL") != 0) {
1620                         cp = cf_pair_find(cs, "secret");
1621                         if (!cp) {
1622                                 cf_log_err_cs(cs, "No shared secret supplied for realm: %s", r->name);
1623                                 return 0;
1624                         }
1625
1626                         secret = cf_pair_value(cp);
1627                         if (!secret) {
1628                                 cf_log_err_cp(cp, "No value specified for secret");
1629                                 return 0;
1630                         }
1631                 }
1632
1633                 cf_log_info(cs, "\tauthhost = %s",  host);
1634
1635                 if (!old_server_add(rc, cs, r->name, host, secret, ldflag,
1636                                     &r->auth_pool, HOME_TYPE_AUTH, NULL)) {
1637                         return 0;
1638                 }
1639         }
1640
1641         cp = cf_pair_find(cs, "accthost");
1642         if (cp) {
1643                 host = cf_pair_value(cp);
1644                 if (!host) {
1645                         cf_log_err_cp(cp, "No value specified for accthost");
1646                         return 0;
1647                 }
1648
1649                 /*
1650                  *      Don't look for a secret again if it was found
1651                  *      above.
1652                  */
1653                 if ((strcmp(host, "LOCAL") != 0) && !secret) {
1654                         cp = cf_pair_find(cs, "secret");
1655                         if (!cp) {
1656                                 cf_log_err_cs(cs, "No shared secret supplied for realm: %s", r->name);
1657                                 return 0;
1658                         }
1659
1660                         secret = cf_pair_value(cp);
1661                         if (!secret) {
1662                                 cf_log_err_cp(cp, "No value specified for secret");
1663                                 return 0;
1664                         }
1665                 }
1666
1667                 cf_log_info(cs, "\taccthost = %s", host);
1668
1669                 if (!old_server_add(rc, cs, r->name, host, secret, ldflag,
1670                                     &r->acct_pool, HOME_TYPE_ACCT, NULL)) {
1671                         return 0;
1672                 }
1673         }
1674
1675         cp = cf_pair_find(cs, "virtual_server");
1676         if (cp) {
1677                 host = cf_pair_value(cp);
1678                 if (!host) {
1679                         cf_log_err_cp(cp, "No value specified for virtual_server");
1680                         return 0;
1681                 }
1682
1683                 cf_log_info(cs, "\tvirtual_server = %s", host);
1684
1685                 if (!old_server_add(rc, cs, r->name, host, "", ldflag,
1686                                     &r->auth_pool, HOME_TYPE_AUTH, host)) {
1687                         return 0;
1688                 }
1689                 if (!old_server_add(rc, cs, r->name, host, "", ldflag,
1690                                     &r->acct_pool, HOME_TYPE_ACCT, host)) {
1691                         return 0;
1692                 }
1693         }
1694
1695         if (secret) cf_log_info(cs, "\tsecret = %s", secret);
1696
1697         return 1;
1698
1699 }
1700
1701
1702 #ifdef WITH_PROXY
1703 static int add_pool_to_realm(realm_config_t *rc, CONF_SECTION *cs,
1704                              char const *name, home_pool_t **dest,
1705                              home_type_t server_type, bool do_print)
1706 {
1707         home_pool_t mypool, *pool;
1708
1709         mypool.name = name;
1710         mypool.server_type = server_type;
1711
1712         pool = rbtree_finddata(home_pools_byname, &mypool);
1713         if (!pool) {
1714                 CONF_SECTION *pool_cs;
1715
1716                 pool_cs = cf_section_sub_find_name2(rc->cs,
1717                                                     "home_server_pool",
1718                                                     name);
1719                 if (!pool_cs) {
1720                         pool_cs = cf_section_sub_find_name2(rc->cs,
1721                                                             "server_pool",
1722                                                             name);
1723                 }
1724                 if (!pool_cs) {
1725                         cf_log_err_cs(cs, "Failed to find home_server_pool \"%s\"", name);
1726                         return 0;
1727                 }
1728
1729                 if (!server_pool_add(rc, pool_cs, server_type, do_print)) {
1730                         return 0;
1731                 }
1732
1733                 pool = rbtree_finddata(home_pools_byname, &mypool);
1734                 if (!pool) {
1735                         ERROR("Internal sanity check failed in add_pool_to_realm");
1736                         return 0;
1737                 }
1738         }
1739
1740         if (pool->server_type != server_type) {
1741                 cf_log_err_cs(cs, "Incompatible home_server_pool \"%s\" (mixed auth_pool / acct_pool)", name);
1742                 return 0;
1743         }
1744
1745         *dest = pool;
1746
1747         return 1;
1748 }
1749 #endif
1750
1751
1752 static int realm_add(realm_config_t *rc, CONF_SECTION *cs)
1753 {
1754         char const *name2;
1755         REALM *r = NULL;
1756         CONF_PAIR *cp;
1757 #ifdef WITH_PROXY
1758         home_pool_t *auth_pool, *acct_pool;
1759         char const *auth_pool_name, *acct_pool_name;
1760 #ifdef WITH_COA
1761         char const *coa_pool_name;
1762         home_pool_t *coa_pool;
1763 #endif
1764 #endif
1765
1766         name2 = cf_section_name1(cs);
1767         if (!name2 || (strcasecmp(name2, "realm") != 0)) {
1768                 cf_log_err_cs(cs, "Section is not a realm");
1769                 return 0;
1770         }
1771
1772         name2 = cf_section_name2(cs);
1773         if (!name2) {
1774                 cf_log_err_cs(cs, "Realm section is missing the realm name");
1775                 return 0;
1776         }
1777
1778 #ifdef WITH_PROXY
1779         auth_pool = acct_pool = NULL;
1780         auth_pool_name = acct_pool_name = NULL;
1781 #ifdef WITH_COA
1782         coa_pool = NULL;
1783         coa_pool_name = NULL;
1784 #endif
1785
1786         /*
1787          *      Prefer new configuration to old one.
1788          */
1789         cp = cf_pair_find(cs, "pool");
1790         if (!cp) cp = cf_pair_find(cs, "home_server_pool");
1791         if (cp) auth_pool_name = cf_pair_value(cp);
1792         if (cp && auth_pool_name) {
1793                 acct_pool_name = auth_pool_name;
1794                 if (!add_pool_to_realm(rc, cs,
1795                                        auth_pool_name, &auth_pool,
1796                                        HOME_TYPE_AUTH, 1)) {
1797                         return 0;
1798                 }
1799                 if (!add_pool_to_realm(rc, cs,
1800                                        auth_pool_name, &acct_pool,
1801                                        HOME_TYPE_ACCT, 0)) {
1802                         return 0;
1803                 }
1804         }
1805
1806         cp = cf_pair_find(cs, "auth_pool");
1807         if (cp) auth_pool_name = cf_pair_value(cp);
1808         if (cp && auth_pool_name) {
1809                 if (auth_pool) {
1810                         cf_log_err_cs(cs, "Cannot use \"pool\" and \"auth_pool\" at the same time");
1811                         return 0;
1812                 }
1813                 if (!add_pool_to_realm(rc, cs,
1814                                        auth_pool_name, &auth_pool,
1815                                        HOME_TYPE_AUTH, 1)) {
1816                         return 0;
1817                 }
1818         }
1819
1820         cp = cf_pair_find(cs, "acct_pool");
1821         if (cp) acct_pool_name = cf_pair_value(cp);
1822         if (cp && acct_pool_name) {
1823                 bool do_print = true;
1824
1825                 if (acct_pool) {
1826                         cf_log_err_cs(cs, "Cannot use \"pool\" and \"acct_pool\" at the same time");
1827                         return 0;
1828                 }
1829
1830                 if (!auth_pool ||
1831                     (auth_pool_name &&
1832                      (strcmp(auth_pool_name, acct_pool_name) != 0))) {
1833                         do_print = true;
1834                 }
1835
1836                 if (!add_pool_to_realm(rc, cs,
1837                                        acct_pool_name, &acct_pool,
1838                                        HOME_TYPE_ACCT, do_print)) {
1839                         return 0;
1840                 }
1841         }
1842
1843 #ifdef WITH_COA
1844         cp = cf_pair_find(cs, "coa_pool");
1845         if (cp) coa_pool_name = cf_pair_value(cp);
1846         if (cp && coa_pool_name) {
1847                 bool do_print = true;
1848
1849                 if (!add_pool_to_realm(rc, cs,
1850                                        coa_pool_name, &coa_pool,
1851                                        HOME_TYPE_COA, do_print)) {
1852                         return 0;
1853                 }
1854         }
1855 #endif
1856 #endif
1857
1858         cf_log_info(cs, " realm %s {", name2);
1859
1860 #ifdef WITH_PROXY
1861         /*
1862          *      The realm MAY already exist if it's an old-style realm.
1863          *      In that case, merge the old-style realm with this one.
1864          */
1865         r = realm_find2(name2);
1866         if (r && (strcmp(r->name, name2) == 0)) {
1867                 if (cf_pair_find(cs, "auth_pool") ||
1868                     cf_pair_find(cs, "acct_pool")) {
1869                         cf_log_err_cs(cs, "Duplicate realm \"%s\"", name2);
1870                         goto error;
1871                 }
1872
1873                 if (!old_realm_config(rc, cs, r)) {
1874                         goto error;
1875                 }
1876
1877                 cf_log_info(cs, " } # realm %s", name2);
1878                 return 1;
1879         }
1880 #endif
1881
1882         r = talloc_zero(rc, REALM);
1883         r->name = name2;
1884         r->strip_realm = true;
1885 #ifdef WITH_PROXY
1886         r->auth_pool = auth_pool;
1887         r->acct_pool = acct_pool;
1888 #ifdef WITH_COA
1889         r->coa_pool = coa_pool;
1890 #endif
1891
1892         if (auth_pool_name &&
1893             (auth_pool_name == acct_pool_name)) { /* yes, ptr comparison */
1894                 cf_log_info(cs, "\tpool = %s", auth_pool_name);
1895         } else {
1896                 if (auth_pool_name) cf_log_info(cs, "\tauth_pool = %s", auth_pool_name);
1897                 if (acct_pool_name) cf_log_info(cs, "\tacct_pool = %s", acct_pool_name);
1898 #ifdef WITH_COA
1899                 if (coa_pool_name) cf_log_info(cs, "\tcoa_pool = %s", coa_pool_name);
1900 #endif
1901         }
1902 #endif
1903
1904         cp = cf_pair_find(cs, "nostrip");
1905         if (cp && (cf_pair_value(cp) == NULL)) {
1906                 r->strip_realm = false;
1907                 cf_log_info(cs, "\tnostrip");
1908         }
1909
1910         /*
1911          *      We're a new-style realm.  Complain if we see the old
1912          *      directives.
1913          */
1914         if (r->auth_pool || r->acct_pool) {
1915                 if (((cp = cf_pair_find(cs, "authhost")) != NULL) ||
1916                     ((cp = cf_pair_find(cs, "accthost")) != NULL) ||
1917                     ((cp = cf_pair_find(cs, "secret")) != NULL) ||
1918                     ((cp = cf_pair_find(cs, "ldflag")) != NULL)) {
1919                         WARN("Ignoring old-style configuration entry \"%s\" in realm \"%s\"", cf_pair_attr(cp), r->name);
1920                 }
1921
1922
1923                 /*
1924                  *      The realm MAY be an old-style realm, as there
1925                  *      was no auth_pool or acct_pool.  Double-check
1926                  *      it, just to be safe.
1927                  */
1928         } else if (!old_realm_config(rc, cs, r)) {
1929                 goto error;
1930         }
1931
1932         if (!realm_realm_add(r, cs)) {
1933                 goto error;
1934         }
1935
1936         cf_log_info(cs, " }");
1937
1938         return 1;
1939
1940  error:
1941         cf_log_info(cs, " } # realm %s", name2);
1942         return 0;
1943 }
1944
1945 #ifdef HAVE_REGEX
1946 int realm_realm_add(REALM *r, CONF_SECTION *cs)
1947 #else
1948 int realm_realm_add(REALM *r, UNUSED CONF_SECTION *cs)
1949 #endif
1950 {
1951         /*
1952          *      The structs aren't mutex protected.  Refuse to destroy
1953          *      the server.
1954          */
1955         if (event_loop_started && !realm_config->dynamic) {
1956                 DEBUG("Must set \"dynamic = true\" in proxy.conf");
1957                 return 0;
1958         }
1959
1960 #ifdef HAVE_REGEX
1961         /*
1962          *      It's a regex.  Sanity check it, and add it to a
1963          *      separate list.
1964          */
1965         if (r->name[0] == '~') {
1966                 ssize_t slen;
1967                 realm_regex_t *rr, **last;
1968
1969                 rr = talloc(r, realm_regex_t);
1970
1971                 /*
1972                  *      Include substring matches.
1973                  */
1974                 slen = regex_compile(rr, &rr->preg, r->name + 1, strlen(r->name) - 1, true, false, false, false);
1975                 if (slen <= 0) {
1976                         char *spaces, *text;
1977
1978                         fr_canonicalize_error(r, &spaces, &text, slen, r->name + 1);
1979
1980                         cf_log_err_cs(cs, "Invalid regular expression:");
1981                         cf_log_err_cs(cs, "%s", text);
1982                         cf_log_err_cs(cs, "%s^ %s", spaces, fr_strerror());
1983
1984                         talloc_free(spaces);
1985                         talloc_free(text);
1986                         talloc_free(rr);
1987
1988                         return 0;
1989                 }
1990
1991                 last = &realms_regex;
1992                 while (*last) last = &((*last)->next);  /* O(N^2)... sue me. */
1993
1994                 rr->realm = r;
1995                 rr->next = NULL;
1996
1997                 *last = rr;
1998                 return 1;
1999         }
2000 #endif
2001
2002         if (!rbtree_insert(realms_byname, r)) {
2003                 rad_assert("Internal sanity check failed" == NULL);
2004                 return 0;
2005         }
2006
2007         return 1;
2008 }
2009
2010 #ifdef WITH_COA
2011
2012 static int pool_peek_type(CONF_SECTION *config, CONF_SECTION *cs)
2013 {
2014         int home;
2015         char const *name, *type;
2016         CONF_PAIR *cp;
2017         CONF_SECTION *server_cs;
2018
2019         cp = cf_pair_find(cs, "home_server");
2020         if (!cp) {
2021                 cf_log_err_cs(cs, "Pool does not contain a \"home_server\" entry");
2022                 return HOME_TYPE_INVALID;
2023         }
2024
2025         name = cf_pair_value(cp);
2026         if (!name) {
2027                 cf_log_err_cp(cp, "home_server entry does not reference a home server");
2028                 return HOME_TYPE_INVALID;
2029         }
2030
2031         server_cs = cf_section_sub_find_name2(config, "home_server", name);
2032         if (!server_cs) {
2033                 cf_log_err_cp(cp, "home_server \"%s\" does not exist", name);
2034                 return HOME_TYPE_INVALID;
2035         }
2036
2037         cp = cf_pair_find(server_cs, "type");
2038         if (!cp) {
2039                 cf_log_err_cs(server_cs, "home_server %s does not contain a \"type\" entry", name);
2040                 return HOME_TYPE_INVALID;
2041         }
2042
2043         type = cf_pair_value(cp);
2044         if (!type) {
2045                 cf_log_err_cs(server_cs, "home_server %s contains an empty \"type\" entry", name);
2046                 return HOME_TYPE_INVALID;
2047         }
2048
2049         home = fr_str2int(home_server_types, type, HOME_TYPE_INVALID);
2050         if (home == HOME_TYPE_INVALID) {
2051                 cf_log_err_cs(server_cs, "home_server %s contains an invalid \"type\" entry of value \"%s\"", name, type);
2052                 return HOME_TYPE_INVALID;
2053         }
2054
2055         return home;            /* 'cause we miss it so much */
2056 }
2057 #endif
2058
2059 int realms_init(CONF_SECTION *config)
2060 {
2061         CONF_SECTION *cs;
2062         int flags = 0;
2063 #ifdef WITH_PROXY
2064         CONF_SECTION *server_cs;
2065 #endif
2066         realm_config_t *rc;
2067
2068         if (event_loop_started) return 1;
2069
2070         rc = talloc_zero(NULL, realm_config_t);
2071         rc->cs = config;
2072
2073 #ifdef WITH_PROXY
2074         cs = cf_subsection_find_next(config, NULL, "proxy");
2075         if (cs) {
2076                 if (cf_section_parse(cs, rc, proxy_config) < 0) {
2077                         ERROR("Failed parsing proxy section");
2078                         goto error;
2079                 }
2080         } else {
2081                 rc->dead_time = DEAD_TIME;
2082                 rc->retry_count = RETRY_COUNT;
2083                 rc->retry_delay = RETRY_DELAY;
2084                 rc->fallback = false;
2085                 rc->dynamic = false;
2086                 rc->wake_all_if_all_dead= 0;
2087         }
2088
2089         if (rc->dynamic) {
2090                 flags = RBTREE_FLAG_LOCK;
2091         }
2092
2093         home_servers_byaddr = rbtree_create(NULL, home_server_addr_cmp, home_server_free, flags);
2094         if (!home_servers_byaddr) goto error;
2095
2096         home_servers_byname = rbtree_create(NULL, home_server_name_cmp, NULL, flags);
2097         if (!home_servers_byname) goto error;
2098
2099 #ifdef WITH_STATS
2100         home_servers_bynumber = rbtree_create(NULL, home_server_number_cmp, NULL, flags);
2101         if (!home_servers_bynumber) goto error;
2102 #endif
2103
2104         home_pools_byname = rbtree_create(NULL, home_pool_name_cmp, NULL, flags);
2105         if (!home_pools_byname) goto error;
2106
2107         for (cs = cf_subsection_find_next(config, NULL, "home_server");
2108              cs != NULL;
2109              cs = cf_subsection_find_next(config, cs, "home_server")) {
2110                 home_server_t *home;
2111
2112                 home = home_server_afrom_cs(rc, rc, cs);
2113                 if (!home) goto error;
2114                 if (!realm_home_server_add(home)) goto error;
2115         }
2116
2117         /*
2118          *      Loop over virtual servers to find home servers which
2119          *      are defined in them.
2120          */
2121         for (server_cs = cf_subsection_find_next(config, NULL, "server");
2122              server_cs != NULL;
2123              server_cs = cf_subsection_find_next(config, server_cs, "server")) {
2124                 for (cs = cf_subsection_find_next(server_cs, NULL, "home_server");
2125                      cs != NULL;
2126                      cs = cf_subsection_find_next(server_cs, cs, "home_server")) {
2127                         home_server_t *home;
2128
2129                         home = home_server_afrom_cs(rc, rc, cs);
2130                         if (!home) goto error;
2131                         if (!realm_home_server_add(home)) goto error;
2132                 }
2133         }
2134 #endif
2135
2136         /*
2137          *      Now create the realms, which point to the home servers
2138          *      and home server pools.
2139          */
2140         realms_byname = rbtree_create(NULL, realm_name_cmp, NULL, flags);
2141         if (!realms_byname) goto error;
2142
2143         for (cs = cf_subsection_find_next(config, NULL, "realm");
2144              cs != NULL;
2145              cs = cf_subsection_find_next(config, cs, "realm")) {
2146                 if (!realm_add(rc, cs)) {
2147                 error:
2148                         realms_free();
2149                         /*
2150                          *      Must be called after realms_free as home_servers
2151                          *      parented by rc are in trees freed by realms_free()
2152                          */
2153                         talloc_free(rc);
2154                         return 0;
2155                 }
2156         }
2157
2158 #ifdef WITH_COA
2159         /*
2160          *      CoA pools aren't necessarily tied to realms.
2161          */
2162         for (cs = cf_subsection_find_next(config, NULL, "home_server_pool");
2163              cs != NULL;
2164              cs = cf_subsection_find_next(config, cs, "home_server_pool")) {
2165                 int type;
2166
2167                 /*
2168                  *      Pool was already loaded.
2169                  */
2170                 if (cf_data_find(cs, "home_server_pool")) continue;
2171
2172                 type = pool_peek_type(config, cs);
2173                 if (type == HOME_TYPE_INVALID) goto error;
2174                 if (!server_pool_add(rc, cs, type, true)) goto error;
2175         }
2176 #endif
2177
2178 #ifdef WITH_PROXY
2179         xlat_register("home_server", xlat_home_server, NULL, NULL);
2180         xlat_register("home_server_pool", xlat_server_pool, NULL, NULL);
2181 #endif
2182
2183         realm_config = rc;
2184         return 1;
2185 }
2186
2187 /*
2188  *      Find a realm where "name" might be the regex.
2189  */
2190 REALM *realm_find2(char const *name)
2191 {
2192         REALM myrealm;
2193         REALM *realm;
2194
2195         if (!name) name = "NULL";
2196
2197         myrealm.name = name;
2198         realm = rbtree_finddata(realms_byname, &myrealm);
2199         if (realm) return realm;
2200
2201 #ifdef HAVE_REGEX
2202         if (realms_regex) {
2203                 realm_regex_t *this;
2204
2205                 for (this = realms_regex; this != NULL; this = this->next) {
2206                         if (strcmp(this->realm->name, name) == 0) {
2207                                 return this->realm;
2208                         }
2209                 }
2210         }
2211 #endif
2212
2213         /*
2214          *      Couldn't find a realm.  Look for DEFAULT.
2215          */
2216         myrealm.name = "DEFAULT";
2217         return rbtree_finddata(realms_byname, &myrealm);
2218 }
2219
2220
2221 /*
2222  *      Find a realm in the REALM list.
2223  */
2224 REALM *realm_find(char const *name)
2225 {
2226         REALM myrealm;
2227         REALM *realm;
2228
2229         if (!name) name = "NULL";
2230
2231         myrealm.name = name;
2232         realm = rbtree_finddata(realms_byname, &myrealm);
2233         if (realm) return realm;
2234
2235 #ifdef HAVE_REGEX
2236         if (realms_regex) {
2237                 realm_regex_t *this;
2238
2239                 for (this = realms_regex;
2240                      this != NULL;
2241                      this = this->next) {
2242                         int compare;
2243
2244                         compare = regex_exec(this->preg, name, strlen(name), NULL, NULL);
2245                         if (compare < 0) {
2246                                 ERROR("Failed performing realm comparison: %s", fr_strerror());
2247                                 return NULL;
2248                         }
2249                         if (compare == 1) return this->realm;
2250                 }
2251         }
2252 #endif
2253
2254         /*
2255          *      Couldn't find a realm.  Look for DEFAULT.
2256          */
2257         myrealm.name = "DEFAULT";
2258         return rbtree_finddata(realms_byname, &myrealm);
2259 }
2260
2261
2262 #ifdef WITH_PROXY
2263
2264 /*
2265  *      Allocate the proxy list if it doesn't already exist, and copy request
2266  *      VPs into it. Setup src/dst IP addresses based on home server, and
2267  *      calculate and add the message-authenticator.
2268  *
2269  *      This is a distinct function from home_server_ldb, as not all home_server_t
2270  *      lookups result in the *CURRENT* request being proxied,
2271  *      as in rlm_replicate, and this may trigger asserts elsewhere in the
2272  *      server.
2273  */
2274 void home_server_update_request(home_server_t *home, REQUEST *request)
2275 {
2276
2277         /*
2278          *      Allocate the proxy packet, only if it wasn't
2279          *      already allocated by a module.  This check is
2280          *      mainly to support the proxying of EAP-TTLS and
2281          *      EAP-PEAP tunneled requests.
2282          *
2283          *      In those cases, the EAP module creates a
2284          *      "fake" request, and recursively passes it
2285          *      through the authentication stage of the
2286          *      server.  The module then checks if the request
2287          *      was supposed to be proxied, and if so, creates
2288          *      a proxy packet from the TUNNELED request, and
2289          *      not from the EAP request outside of the
2290          *      tunnel.
2291          *
2292          *      The proxy then works like normal, except that
2293          *      the response packet is "eaten" by the EAP
2294          *      module, and encapsulated into an EAP packet.
2295          */
2296         if (!request->proxy) {
2297                 request->proxy = rad_alloc(request, true);
2298                 if (!request->proxy) {
2299                         ERROR("no memory");
2300                         fr_exit(1);
2301                 }
2302
2303                 /*
2304                  *      Copy the request, then look up name
2305                  *      and plain-text password in the copy.
2306                  *
2307                  *      Note that the User-Name attribute is
2308                  *      the *original* as sent over by the
2309                  *      client.  The Stripped-User-Name
2310                  *      attribute is the one hacked through
2311                  *      the 'hints' file.
2312                  */
2313                 request->proxy->vps = fr_pair_list_copy(request->proxy,
2314                                                request->packet->vps);
2315         }
2316
2317         /*
2318          *      Update the various fields as appropriate.
2319          */
2320         request->proxy->src_ipaddr = home->src_ipaddr;
2321         request->proxy->src_port = 0;
2322         request->proxy->dst_ipaddr = home->ipaddr;
2323         request->proxy->dst_port = home->port;
2324 #ifdef WITH_TCP
2325         request->proxy->proto = home->proto;
2326 #endif
2327         request->home_server = home;
2328
2329         /*
2330          *      Access-Requests have a Message-Authenticator added,
2331          *      unless one already exists.
2332          */
2333         if ((request->packet->code == PW_CODE_ACCESS_REQUEST) &&
2334             !fr_pair_find_by_num(request->proxy->vps, PW_MESSAGE_AUTHENTICATOR, 0, TAG_ANY)) {
2335                 fr_pair_make(request->proxy, &request->proxy->vps,
2336                          "Message-Authenticator", "0x00",
2337                          T_OP_SET);
2338         }
2339 }
2340
2341 home_server_t *home_server_ldb(char const *realmname,
2342                              home_pool_t *pool, REQUEST *request)
2343 {
2344         int             start;
2345         int             count;
2346         home_server_t   *found = NULL;
2347         home_server_t   *zombie = NULL;
2348         VALUE_PAIR      *vp;
2349         uint32_t        hash;
2350
2351         /*
2352          *      Determine how to pick choose the home server.
2353          */
2354         switch (pool->type) {
2355
2356
2357                 /*
2358                  *      For load-balancing by client IP address, we
2359                  *      pick a home server by hashing the client IP.
2360                  *
2361                  *      This isn't as even a load distribution as
2362                  *      tracking the State attribute, but it's better
2363                  *      than nothing.
2364                  */
2365         case HOME_POOL_CLIENT_BALANCE:
2366                 switch (request->packet->src_ipaddr.af) {
2367                 case AF_INET:
2368                         hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip4addr,
2369                                          sizeof(request->packet->src_ipaddr.ipaddr.ip4addr));
2370                         break;
2371
2372                 case AF_INET6:
2373                         hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip6addr,
2374                                          sizeof(request->packet->src_ipaddr.ipaddr.ip6addr));
2375                         break;
2376
2377                 default:
2378                         hash = 0;
2379                         break;
2380                 }
2381                 start = hash % pool->num_home_servers;
2382                 break;
2383
2384         case HOME_POOL_CLIENT_PORT_BALANCE:
2385                 switch (request->packet->src_ipaddr.af) {
2386                 case AF_INET:
2387                         hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip4addr,
2388                                          sizeof(request->packet->src_ipaddr.ipaddr.ip4addr));
2389                         break;
2390
2391                 case AF_INET6:
2392                         hash = fr_hash(&request->packet->src_ipaddr.ipaddr.ip6addr,
2393                                          sizeof(request->packet->src_ipaddr.ipaddr.ip6addr));
2394                         break;
2395
2396                 default:
2397                         hash = 0;
2398                         break;
2399                 }
2400                 fr_hash_update(&request->packet->src_port,
2401                                  sizeof(request->packet->src_port), hash);
2402                 start = hash % pool->num_home_servers;
2403                 break;
2404
2405         case HOME_POOL_KEYED_BALANCE:
2406                 if ((vp = fr_pair_find_by_num(request->config, PW_LOAD_BALANCE_KEY, 0, TAG_ANY)) != NULL) {
2407                         hash = fr_hash(vp->vp_strvalue, vp->vp_length);
2408                         start = hash % pool->num_home_servers;
2409                         break;
2410                 }
2411                 /* FALL-THROUGH */
2412
2413         case HOME_POOL_LOAD_BALANCE:
2414         case HOME_POOL_FAIL_OVER:
2415                 start = 0;
2416                 break;
2417
2418         default:                /* this shouldn't happen... */
2419                 start = 0;
2420                 break;
2421
2422         }
2423
2424         /*
2425          *      Starting with the home server we chose, loop through
2426          *      all home servers.  If the current one is dead, skip
2427          *      it.  If it is too busy, skip it.
2428          *
2429          *      Otherwise, use it.
2430          */
2431         for (count = 0; count < pool->num_home_servers; count++) {
2432                 home_server_t *home = pool->servers[(start + count) % pool->num_home_servers];
2433
2434                 if (!home) continue;
2435
2436                 /*
2437                  *      Skip dead home servers.
2438                  *
2439                  *      Home servers that are unknown, alive, or zombie
2440                  *      are used for proxying.
2441                  */
2442                 if (home->state == HOME_STATE_IS_DEAD) {
2443                         continue;
2444                 }
2445
2446                 /*
2447                  *      This home server is too busy.  Choose another one.
2448                  */
2449                 if (home->currently_outstanding >= home->max_outstanding) {
2450                         continue;
2451                 }
2452
2453 #ifdef WITH_DETAIL
2454                 /*
2455                  *      We read the packet from a detail file, AND it
2456                  *      came from this server.  Don't re-proxy it
2457                  *      there.
2458                  */
2459                 if ((request->listener->type == RAD_LISTEN_DETAIL) &&
2460                     (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) &&
2461                     (fr_ipaddr_cmp(&home->ipaddr, &request->packet->src_ipaddr) == 0)) {
2462                         continue;
2463                 }
2464 #endif
2465
2466                 /*
2467                  *      Default virtual: ignore homes tied to a
2468                  *      virtual.
2469                  */
2470                 if (!request->server && home->parent_server) {
2471                         continue;
2472                 }
2473
2474                 /*
2475                  *      A virtual AND home is tied to virtual,
2476                  *      ignore ones which don't match.
2477                  */
2478                 if (request->server && home->parent_server &&
2479                     strcmp(request->server, home->parent_server) != 0) {
2480                         continue;
2481                 }
2482
2483                 /*
2484                  *      Allow request->server && !home->parent_server
2485                  *
2486                  *      i.e. virtuals can proxy to globally defined
2487                  *      homes.
2488                  */
2489
2490                 /*
2491                  *      It's zombie, so we remember the first zombie
2492                  *      we find, but we don't mark it as a "live"
2493                  *      server.
2494                  */
2495                 if (home->state == HOME_STATE_ZOMBIE) {
2496                         if (!zombie) zombie = home;
2497                         continue;
2498                 }
2499
2500                 /*
2501                  *      We've found the first "live" one.  Use that.
2502                  */
2503                 if (pool->type != HOME_POOL_LOAD_BALANCE) {
2504                         found = home;
2505                         break;
2506                 }
2507
2508                 /*
2509                  *      Otherwise we're doing some kind of load balancing.
2510                  *      If we haven't found one yet, pick this one.
2511                  */
2512                 if (!found) {
2513                         found = home;
2514                         continue;
2515                 }
2516
2517                 RDEBUG3("PROXY %s %d\t%s %d",
2518                        found->log_name, found->currently_outstanding,
2519                        home->log_name, home->currently_outstanding);
2520
2521                 /*
2522                  *      Prefer this server if it's less busy than the
2523                  *      one we had previously found.
2524                  */
2525                 if (home->currently_outstanding < found->currently_outstanding) {
2526                         RDEBUG3("PROXY Choosing %s: It's less busy than %s",
2527                                home->log_name, found->log_name);
2528                         found = home;
2529                         continue;
2530                 }
2531
2532                 /*
2533                  *      Ignore servers which are busier than the one
2534                  *      we found.
2535                  */
2536                 if (home->currently_outstanding > found->currently_outstanding) {
2537                         RDEBUG3("PROXY Skipping %s: It's busier than %s",
2538                                home->log_name, found->log_name);
2539                         continue;
2540                 }
2541
2542                 /*
2543                  *      From the list of servers which have the same
2544                  *      load, choose one at random.
2545                  */
2546                 if (((count + 1) * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
2547                         found = home;
2548                 }
2549         } /* loop over the home servers */
2550
2551         /*
2552          *      We have no live servers, BUT we have a zombie.  Use
2553          *      the zombie as a last resort.
2554          */
2555         if (!found && zombie) {
2556                 found = zombie;
2557                 zombie = NULL;
2558         }
2559
2560         /*
2561          *      There's a fallback if they're all dead.
2562          */
2563         if (!found && pool->fallback) {
2564                 found = pool->fallback;
2565
2566                 WARN("Home server pool %s failing over to fallback %s",
2567                       pool->name, found->server);
2568                 if (pool->in_fallback) goto update_and_return;
2569
2570                 pool->in_fallback = true;
2571
2572                 /*
2573                  *      Run the trigger once an hour saying that
2574                  *      they're all dead.
2575                  */
2576                 if ((pool->time_all_dead + 3600) < request->timestamp) {
2577                         pool->time_all_dead = request->timestamp;
2578                         exec_trigger(request, pool->cs, "home_server_pool.fallback", false);
2579                 }
2580         }
2581
2582         if (found) {
2583         update_and_return:
2584                 if ((found != pool->fallback) && pool->in_fallback) {
2585                         pool->in_fallback = false;
2586                         exec_trigger(request, pool->cs, "home_server_pool.normal", false);
2587                 }
2588
2589                 return found;
2590         }
2591
2592         /*
2593          *      No live match found, and no fallback to the "DEFAULT"
2594          *      realm.  We fix this by blindly marking all servers as
2595          *      "live".  But only do it for ones that don't support
2596          *      "pings", as they will be marked live when they
2597          *      actually are live.
2598          */
2599         if (!realm_config->fallback &&
2600             realm_config->wake_all_if_all_dead) {
2601                 for (count = 0; count < pool->num_home_servers; count++) {
2602                         home_server_t *home = pool->servers[count];
2603
2604                         if (!home) continue;
2605
2606                         if ((home->state == HOME_STATE_IS_DEAD) &&
2607                             (home->ping_check == HOME_PING_CHECK_NONE)) {
2608                                 home->state = HOME_STATE_ALIVE;
2609                                 home->response_timeouts = 0;
2610                                 if (!found) found = home;
2611                         }
2612                 }
2613
2614                 if (found) goto update_and_return;
2615         }
2616
2617         /*
2618          *      Still nothing.  Look up the DEFAULT realm, but only
2619          *      if we weren't looking up the NULL or DEFAULT realms.
2620          */
2621         if (realm_config->fallback &&
2622             realmname &&
2623             (strcmp(realmname, "NULL") != 0) &&
2624             (strcmp(realmname, "DEFAULT") != 0)) {
2625                 REALM *rd = realm_find("DEFAULT");
2626
2627                 if (!rd) return NULL;
2628
2629                 pool = NULL;
2630                 if (request->packet->code == PW_CODE_ACCESS_REQUEST) {
2631                         pool = rd->auth_pool;
2632
2633                 } else if (request->packet->code == PW_CODE_ACCOUNTING_REQUEST) {
2634                         pool = rd->acct_pool;
2635                 }
2636                 if (!pool) return NULL;
2637
2638                 RDEBUG2("PROXY - realm %s has no live home servers.  Falling back to the DEFAULT realm.", realmname);
2639                 return home_server_ldb(rd->name, pool, request);
2640         }
2641
2642         /*
2643          *      Still haven't found anything.  Oh well.
2644          */
2645         return NULL;
2646 }
2647
2648
2649 home_server_t *home_server_find(fr_ipaddr_t *ipaddr, uint16_t port, int proto)
2650 {
2651         home_server_t myhome;
2652
2653         memset(&myhome, 0, sizeof(myhome));
2654         myhome.ipaddr = *ipaddr;
2655         myhome.src_ipaddr.af = ipaddr->af;
2656         myhome.port = port;
2657 #ifdef WITH_TCP
2658         myhome.proto = proto;
2659 #else
2660         myhome.proto = IPPROTO_UDP;
2661 #endif
2662         myhome.server = NULL;   /* we're not called for internal proxying */
2663
2664         return rbtree_finddata(home_servers_byaddr, &myhome);
2665 }
2666
2667 #ifdef WITH_COA
2668 home_server_t *home_server_byname(char const *name, int type)
2669 {
2670         home_server_t myhome;
2671
2672         memset(&myhome, 0, sizeof(myhome));
2673         myhome.type = type;
2674         myhome.name = name;
2675
2676         return rbtree_finddata(home_servers_byname, &myhome);
2677 }
2678 #endif
2679
2680 #ifdef WITH_STATS
2681 home_server_t *home_server_bynumber(int number)
2682 {
2683         home_server_t myhome;
2684
2685         memset(&myhome, 0, sizeof(myhome));
2686         myhome.number = number;
2687         myhome.server = NULL;   /* we're not called for internal proxying */
2688
2689         return rbtree_finddata(home_servers_bynumber, &myhome);
2690 }
2691 #endif
2692
2693 home_pool_t *home_pool_byname(char const *name, int type)
2694 {
2695         home_pool_t mypool;
2696
2697         memset(&mypool, 0, sizeof(mypool));
2698         mypool.name = name;
2699         mypool.server_type = type;
2700         return rbtree_finddata(home_pools_byname, &mypool);
2701 }
2702
2703 #endif