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