2 * Copyright (c) 2012, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include <tr_config.h>
44 #include <tr_filter.h>
45 #include <trust_router/tr_constraint.h>
47 void tr_print_config (FILE *stream, TR_CFG *cfg) {
48 fprintf(stream, "tr_print_config: Not yet implemented.");
52 void tr_cfg_free (TR_CFG *cfg) {
57 TR_CFG_RC tr_apply_new_config (TR_INSTANCE *tr) {
59 return TR_CFG_BAD_PARAMS;
62 tr_cfg_free(tr->active_cfg);
64 tr->active_cfg = tr->new_cfg;
66 tr_log_threshold(tr->active_cfg->internal->log_threshold);
67 tr_console_threshold(tr->active_cfg->internal->console_threshold);
69 return TR_CFG_SUCCESS;
72 static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
76 json_t *jhname = NULL;
78 json_t *jconthres = NULL;
79 json_t *jlogthres = NULL;
81 if ((!trc) || (!jcfg))
82 return TR_CFG_BAD_PARAMS;
84 if (NULL == trc->internal) {
85 if (NULL == (trc->internal = talloc(trc, TR_CFG_INTERNAL)))
88 memset(trc->internal, 0, sizeof(TR_CFG_INTERNAL));
91 if (NULL != (jint = json_object_get(jcfg, "tr_internal"))) {
92 if (NULL != (jmtd = json_object_get(jint, "max_tree_depth"))) {
93 if (json_is_number(jmtd)) {
94 trc->internal->max_tree_depth = json_integer_value(jmtd);
96 tr_debug("tr_cfg_parse_internal: Parsing error, max_tree_depth is not a number.");
97 return TR_CFG_NOPARSE;
100 /* If not configured, use the default */
101 trc->internal->max_tree_depth = TR_DEFAULT_MAX_TREE_DEPTH;
103 if (NULL != (jtp = json_object_get(jint, "tids_port"))) {
104 if (json_is_number(jtp)) {
105 trc->internal->tids_port = json_integer_value(jtp);
107 tr_debug("tr_cfg_parse_internal: Parsing error, port is not a number.");
108 return TR_CFG_NOPARSE;
111 /* If not configured, use the default */
112 trc->internal->tids_port = TR_DEFAULT_TIDS_PORT;
114 if (NULL != (jhname = json_object_get(jint, "hostname"))) {
115 if (json_is_string(jhname)) {
116 trc->internal->hostname = json_string_value(jhname);
118 tr_debug("tr_cfg_parse_internal: Parsing error, hostname is not a string.");
119 return TR_CFG_NOPARSE;
123 if (NULL != (jlog = json_object_get(jcfg, "logging"))) {
124 if (NULL != (jlogthres = json_object_get(jint, "log_threshold"))) {
125 if (json_is_string(jlogthres)) {
126 trc->internal->log_threshold = str2sev(json_string_value(jlogthres));
128 tr_debug("tr_cfg_parse_internal: Parsing error, log_threshold is not a string.");
129 return TR_CFG_NOPARSE;
132 /* If not configured, use the default */
133 trc->internal->log_threshold = TR_DEFAULT_LOG_THRESHOLD;
136 if (NULL != (jconthres = json_object_get(jint, "console_threshold"))) {
137 if (json_is_string(jconthres)) {
138 trc->internal->console_threshold = str2sev(json_string_value(jconthres));
140 tr_debug("tr_cfg_parse_internal: Parsing error, console_threshold is not a string.");
141 return TR_CFG_NOPARSE;
144 /* If not configured, use the default */
145 trc->internal->console_threshold = TR_DEFAULT_CONSOLE_THRESHOLD;
148 /* If not configured, use the default */
149 trc->internal->console_threshold = TR_DEFAULT_CONSOLE_THRESHOLD;
150 trc->internal->log_threshold = TR_DEFAULT_LOG_THRESHOLD;
153 tr_debug("tr_cfg_parse_internal: Internal config parsed.");
154 return TR_CFG_SUCCESS;
156 return TR_CFG_SUCCESS;
159 static TR_CONSTRAINT *tr_cfg_parse_one_constraint (TR_CFG *trc, char *ctype, json_t *jc, TR_CFG_RC *rc)
164 if ((!trc) || (!ctype) || (!jc) || (!rc) ||
165 (!json_is_array(jc)) ||
166 (0 >= json_array_size(jc)) ||
167 (TR_MAX_CONST_MATCHES < json_array_size(jc)) ||
168 (!json_is_string(json_array_get(jc, 0)))) {
169 tr_debug("tr_cfg_parse_one_constraint: config error.");
170 *rc = TR_CFG_NOPARSE;
174 if (NULL == (cons = talloc(trc, TR_CONSTRAINT))) {
175 tr_debug("tr_cfg_parse_one_constraint: Out of memory (cons).");
180 memset(cons, 0, sizeof(TR_CONSTRAINT));
182 if (NULL == (cons->type = tr_new_name(ctype))) {
183 tr_debug("tr_cfg_parse_one_constraint: Out of memory (type).");
188 for (i = 0; i < json_array_size(jc); i++) {
189 cons->matches[i] = tr_new_name((char *)(json_string_value(json_array_get(jc, i))));
195 static TR_FILTER *tr_cfg_parse_one_filter (TR_CFG *trc, json_t *jfilt, TR_CFG_RC *rc)
197 TR_FILTER *filt = NULL;
198 json_t *jftype = NULL;
200 json_t *jfaction = NULL;
201 json_t *jfspecs = NULL;
202 json_t *jffield = NULL;
203 json_t *jfmatch = NULL;
208 if ((NULL == (jftype = json_object_get(jfilt, "type"))) ||
209 (!json_is_string(jftype))) {
210 tr_debug("tr_cfg_parse_one_filter: Error parsing filter type.");
211 *rc = TR_CFG_NOPARSE;
215 if ((NULL == (jfls = json_object_get(jfilt, "filter_lines"))) ||
216 (!json_is_array(jfls))) {
217 tr_debug("tr_cfg_parse_one_filter: Error parsing filter type.");
218 *rc = TR_CFG_NOPARSE;
222 if (TR_MAX_FILTER_LINES < json_array_size(jfls)) {
223 tr_debug("tr_cfg_parse_one_filter: Filter has too many filter_lines, maximimum of %d.", TR_MAX_FILTER_LINES);
224 *rc = TR_CFG_NOPARSE;
228 if (NULL == (filt = talloc(trc, TR_FILTER))) {
229 tr_debug("tr_cfg_parse_one_filter: Out of memory.");
234 memset(filt, 0, sizeof(TR_FILTER));
236 if (!strcmp(json_string_value(jftype), "rp_permitted")) {
237 filt->type = TR_FILTER_TYPE_RP_PERMITTED;
240 tr_debug("tr_cfg_parse_one_filter: Error parsing filter type, unknown type '%s'.", json_string_value(jftype));
241 *rc = TR_CFG_NOPARSE;
242 tr_filter_free(filt);
246 /* For each filter line... */
247 for (i = 0; i < json_array_size(jfls); i++) {
249 if ((NULL == (jfaction = json_object_get(json_array_get(jfls, i), "action"))) ||
250 (!json_is_string(jfaction))) {
251 tr_debug("tr_cfg_parse_one_filter: Error parsing filter action.");
252 *rc = TR_CFG_NOPARSE;
253 tr_filter_free(filt);
257 if ((NULL == (jfspecs = json_object_get(json_array_get(jfls, i), "filter_specs"))) ||
258 (!json_is_array(jfspecs)) ||
259 (0 == json_array_size(jfspecs))) {
260 tr_debug("tr_cfg_parse_one_filter: Error parsing filter specs.");
261 *rc = TR_CFG_NOPARSE;
262 tr_filter_free(filt);
266 if (TR_MAX_FILTER_SPECS < json_array_size(jfspecs)) {
267 tr_debug("tr_cfg_parse_one_filter: Filter has too many filter_specs, maximimum of %d.", TR_MAX_FILTER_SPECS);
268 *rc = TR_CFG_NOPARSE;
269 tr_filter_free(filt);
273 if (NULL == (filt->lines[i] = talloc(trc, TR_FLINE))) {
274 tr_debug("tr_cfg_parse_one_filter: Out of memory (fline).");
276 tr_filter_free(filt);
280 memset(filt->lines[i], 0, sizeof(TR_FLINE));
282 if (!strcmp(json_string_value(jfaction), "accept")) {
283 filt->lines[i]->action = TR_FILTER_ACTION_ACCEPT;
285 else if (!strcmp(json_string_value(jfaction), "reject")) {
286 filt->lines[i]->action = TR_FILTER_ACTION_REJECT;
289 tr_debug("tr_cfg_parse_one_filter: Error parsing filter action, unknown action' %s'.", json_string_value(jfaction));
290 *rc = TR_CFG_NOPARSE;
291 tr_filter_free(filt);
295 if ((NULL != (jrc = json_object_get(json_array_get(jfls, i), "realm_constraints"))) &&
296 (json_is_array(jrc)) &&
297 (0 != json_array_size(jrc)) &&
298 (TR_MAX_CONST_MATCHES >= json_array_size(jrc))) {
300 if (NULL == (filt->lines[i]->realm_cons = tr_cfg_parse_one_constraint(trc, "realm", jrc, rc))) {
301 tr_debug("tr_cfg_parse_one_filter: Error parsing realm constraint");
302 tr_filter_free(filt);
307 if ((NULL != (jdc = json_object_get(json_array_get(jfls, i), "domain_constraints"))) &&
308 (json_is_array(jdc)) &&
309 (0 != json_array_size(jdc)) &&
310 (TR_MAX_CONST_MATCHES >= json_array_size(jdc))) {
312 if (NULL == (filt->lines[i]->domain_cons = tr_cfg_parse_one_constraint(trc, "domain", jdc, rc))) {
313 tr_debug("tr_cfg_parse_one_filter: Error parsing domain constraint");
314 tr_filter_free(filt);
319 /*For each filter spec within the filter line... */
320 for (j = 0; j <json_array_size(jfspecs); j++) {
322 if ((NULL == (jffield = json_object_get(json_array_get(jfspecs, j), "field"))) ||
323 (!json_is_string(jffield)) ||
324 (NULL == (jfmatch = json_object_get(json_array_get(jfspecs, j), "match"))) ||
325 (!json_is_string(jfmatch))) {
326 tr_debug("tr_cfg_parse_one_filter: Error parsing filter field and match for filter spec %d, filter line %d.", i, j);
327 *rc = TR_CFG_NOPARSE;
328 tr_filter_free(filt);
332 if (NULL == (filt->lines[i]->specs[j] = talloc(trc, TR_FSPEC))) {
333 tr_debug("tr_cfg_parse_one_filter: Out of memory.");
335 tr_filter_free(filt);
339 memset(filt->lines[i]->specs[j], 0, sizeof(TR_FSPEC));
341 if ((NULL == (filt->lines[i]->specs[j]->field = tr_new_name((char *)json_string_value(jffield)))) ||
342 (NULL == (filt->lines[i]->specs[j]->match = tr_new_name((char *)json_string_value(jfmatch))))) {
343 tr_debug("tr_cfg_parse_one_filter: Out of memory.");
345 tr_filter_free(filt);
354 static TR_RP_CLIENT *tr_cfg_parse_one_rp_client (TR_CFG *trc, json_t *jrp, TR_CFG_RC *rc)
356 TR_RP_CLIENT *rp = NULL;
358 json_t *jfilt = NULL;
359 json_t *jftype = NULL;
362 if ((!trc) || (!jrp) || (!rc)) {
363 tr_debug("tr_cfg_parse_one_rp_realm: Bad parameters.");
365 *rc = TR_CFG_BAD_PARAMS;
369 if ((NULL == (jgns = json_object_get(jrp, "gss_names"))) ||
370 (!json_is_array(jgns))) {
371 tr_debug("tr_cfg_parse_one_rp_client: Error parsing RP client configuration, no GSS names.");
372 *rc = TR_CFG_NOPARSE;
376 /* TBD -- Support more than one filter per RP client? */
377 if (NULL == (jfilt = json_object_get(jrp, "filter"))) {
378 tr_debug("tr_cfg_parse_one_rp_client: Error parsing RP client configuration, no filter.");
379 *rc = TR_CFG_NOPARSE;
383 /* We only support rp_permitted filters for RP clients */
384 if ((NULL == (jftype = json_object_get(jfilt, "type"))) ||
385 (!json_is_string(jftype)) ||
386 (strcmp(json_string_value(jftype), "rp_permitted"))) {
387 tr_debug("tr_cfg_parse_one_rp_client: Error parsing RP client filter type.");
388 *rc = TR_CFG_NOPARSE;
392 if (TR_MAX_GSS_NAMES < json_array_size(jgns)) {
393 tr_debug("tr_cfg_parse_one_rp_client: RP Client has too many GSS Names.");
394 *rc = TR_CFG_NOPARSE;
398 if (NULL == (rp = talloc(trc, TR_RP_CLIENT))) {
399 tr_debug("tr_cfg_parse_one_rp_realm: Out of memory.");
404 memset(rp, 0, sizeof(TR_RP_CLIENT));
406 /* TBD -- support more than one filter entry per RP Client? */
407 if (NULL == (rp->filter = tr_cfg_parse_one_filter(trc, jfilt, rc))) {
408 tr_debug("tr_cfg_parse_one_rp_client: Error parsing filter.");
409 *rc = TR_CFG_NOPARSE;
413 for (i = 0; i < json_array_size(jgns); i++) {
414 if (NULL == (rp->gss_names[i] = tr_new_name ((char *)json_string_value(json_array_get(jgns, i))))) {
415 tr_debug("tr_cfg_parse_one_rp_client: No memory for GSS Name.");
424 static TR_CFG_RC tr_cfg_parse_rp_clients (TR_CFG *trc, json_t *jcfg) {
426 TR_RP_CLIENT *rp = NULL;
427 TR_CFG_RC rc = TR_CFG_SUCCESS;
430 if ((!trc) || (!jcfg))
431 return TR_CFG_BAD_PARAMS;
433 if (NULL != (jrps = json_object_get(jcfg, "rp_clients"))) {
435 if (!json_is_array(jrps)) {
436 return TR_CFG_NOPARSE;
439 for (i = 0; i < json_array_size(jrps); i++) {
440 if (NULL == (rp = tr_cfg_parse_one_rp_client(trc,
441 json_array_get(jrps, i),
445 tr_debug("tr_cfg_parse_rp_clients: RP client configured -- first gss: %s", rp->gss_names[0]->buf);
446 rp->next = trc->rp_clients;
447 trc->rp_clients = rp;
453 static TR_AAA_SERVER *tr_cfg_parse_one_aaa_server (TR_CFG *trc, json_t *jaddr, TR_CFG_RC *rc) {
454 TR_AAA_SERVER *aaa = NULL;
456 if ((!trc) || (!jaddr) || (!json_is_string(jaddr))) {
457 tr_debug("tr_cfg_parse_one_aaa_server: Bad parameters.");
458 *rc = TR_CFG_BAD_PARAMS;
462 if (NULL == (aaa = talloc(trc, TR_AAA_SERVER))) {
463 tr_debug("tr_cfg_parse_one_aaa_server: Out of memory.");
468 memset(aaa, 0, sizeof(TR_AAA_SERVER));
470 aaa->hostname = tr_new_name((char *)(json_string_value(jaddr)));
475 static TR_AAA_SERVER *tr_cfg_parse_aaa_servers (TR_CFG *trc, json_t *jaaas, TR_CFG_RC *rc)
477 TR_AAA_SERVER *aaa = NULL;
478 TR_AAA_SERVER *temp_aaa = NULL;
481 for (i = 0; i < json_array_size(jaaas); i++) {
482 if (NULL == (temp_aaa = tr_cfg_parse_one_aaa_server(trc, json_array_get(jaaas, i), rc))) {
485 /* TBD -- IPv6 addresses */
486 // tr_debug("tr_cfg_parse_aaa_servers: Configuring AAA Server: ip_addr = %s.", inet_ntoa(temp_aaa->aaa_server_addr));
487 temp_aaa->next = aaa;
493 static TR_APC *tr_cfg_parse_apcs (TR_CFG *trc, json_t *japcs, TR_CFG_RC *rc)
497 *rc = TR_CFG_SUCCESS; /* presume success */
499 if ((!trc) || (!japcs) || (!rc)) {
500 tr_debug("tr_cfg_parse_apcs: Bad parameters.");
502 *rc = TR_CFG_BAD_PARAMS;
506 if (NULL == (apc = talloc(trc, TR_APC))) {
507 tr_debug("tr_cfg_parse_apcs: Out of memory.");
512 memset(apc, 0, sizeof(TR_APC));
514 /* TBD, deal with more than one APC. In the meantime, though... */
515 /* Only parse the first APC, because we only know how to deal with one, anyway. */
516 if (0 == json_array_size(japcs))
519 if (NULL == (apc->id = tr_new_name((char *)json_string_value(json_array_get(japcs, 0))))) {
520 tr_debug("tr_cfg_parse_apcs: No memory for APC name.");
528 static TR_IDP_REALM *tr_cfg_parse_one_idp_realm (TR_CFG *trc, json_t *jidp, TR_CFG_RC *rc) {
529 TR_IDP_REALM *idp = NULL;
531 json_t *jscfg = NULL;
532 json_t *jsrvrs = NULL;
533 json_t *japcs = NULL;
535 if ((!trc) || (!jidp) || (!rc)) {
536 tr_debug("tr_cfg_parse_one_idp_realm: Bad parameters.");
538 *rc = TR_CFG_BAD_PARAMS;
542 if (NULL == (idp = talloc(trc, TR_IDP_REALM))) {
543 tr_debug("tr_cfg_parse_one_idp_realm: Out of memory.");
548 memset(idp, 0, sizeof(TR_IDP_REALM));
550 if ((NULL == (jrid = json_object_get(jidp, "realm_id"))) ||
551 (!json_is_string(jrid)) ||
552 (NULL == (jscfg = json_object_get(jidp, "shared_config"))) ||
553 (!json_is_string(jscfg)) ||
554 (NULL == (jsrvrs = json_object_get(jidp, "aaa_servers"))) ||
555 (!json_is_array(jsrvrs))) {
556 tr_debug("tr_cfg_parse_one_idp_realm: Error parsing IDP realm configuration.");
557 *rc = TR_CFG_NOPARSE;
561 if (0 == strcmp(json_string_value(jscfg), "no")) {
562 idp->shared_config = 0;
564 idp->shared_config = 1;
567 if (NULL == (idp->realm_id = tr_new_name((char *)json_string_value(jrid)))) {
568 tr_debug("tr_cfg_parse_one_idp_realm: No memory for realm id.");
573 if (NULL == (idp->aaa_servers = tr_cfg_parse_aaa_servers(trc, jsrvrs, rc))) {
574 tr_debug("tr_cfg_parse_one_idp_realm: Can't parse AAA servers for realm %s.", idp->realm_id->buf);
575 tr_free_name(idp->realm_id);
579 if ((NULL != (japcs = json_object_get(jidp, "apcs"))) &&
580 (json_is_array(japcs))) {
581 if (NULL == (idp->apcs = tr_cfg_parse_apcs(trc, japcs, rc))) {
582 tr_debug("tr_cfg_parse_one_idp_realm: Can't parse APCs for realm %s .", idp->realm_id->buf);
583 tr_free_name(idp->realm_id);
584 /* TBD -- free aaa_servers */;
591 static TR_CFG_RC tr_cfg_parse_default_servers (TR_CFG *trc, json_t *jcfg)
594 TR_CFG_RC rc = TR_CFG_SUCCESS;
595 TR_AAA_SERVER *ds = NULL;
598 if ((!trc) || (!jcfg))
599 return TR_CFG_BAD_PARAMS;
601 /* If there are default servers, store them */
602 if ((NULL != (jdss = json_object_get(jcfg, "default_servers"))) &&
603 (json_is_array(jdss)) &&
604 (0 < json_array_size(jdss))) {
606 for (i = 0; i < json_array_size(jdss); i++) {
607 if (NULL == (ds = tr_cfg_parse_one_aaa_server(trc,
608 json_array_get(jdss, i),
612 tr_debug("tr_cfg_parse_default_servers: Default server configured: %s", ds->hostname->buf);
613 ds->next = trc->default_servers;
614 trc->default_servers = ds;
621 static TR_CFG_RC tr_cfg_parse_idp_realms (TR_CFG *trc, json_t *jcfg)
623 json_t *jidps = NULL;
624 TR_CFG_RC rc = TR_CFG_SUCCESS;
625 TR_IDP_REALM *idp = NULL;
628 if ((!trc) || (!jcfg))
629 return TR_CFG_BAD_PARAMS;
631 /* If there are any IDP Realms, parse them */
632 if ((NULL != (jidps = json_object_get(jcfg, "idp_realms"))) &&
633 (json_is_array(jidps))) {
634 for (i = 0; i < json_array_size(jidps); i++) {
635 if (NULL == (idp = tr_cfg_parse_one_idp_realm(trc,
636 json_array_get(jidps, i),
640 tr_debug("tr_cfg_parse_idp_realms: IDP realm configured: %s.", idp->realm_id->buf);
641 idp->next = trc->idp_realms;
642 trc->idp_realms = idp;
649 static TR_IDP_REALM *tr_cfg_parse_comm_idps (TR_CFG *trc, json_t *jidps, TR_CFG_RC *rc)
651 TR_IDP_REALM *idp = NULL;
652 TR_IDP_REALM *temp_idp = NULL;
657 (!json_is_array(jidps))) {
659 *rc = TR_CFG_BAD_PARAMS;
663 for (i = 0; i < json_array_size(jidps); i++) {
664 if (NULL == (temp_idp = (tr_cfg_find_idp(trc,
665 tr_new_name((char *)json_string_value(json_array_get(jidps, i))),
667 tr_debug("tr_cfg_parse_comm_idps: Unknown IDP %s.",
668 (char *)json_string_value(json_array_get(jidps, i)));
672 temp_idp->comm_next = idp;
679 static TR_RP_REALM *tr_cfg_parse_comm_rps (TR_CFG *trc, json_t *jrps, TR_CFG_RC *rc)
681 TR_RP_REALM *rp = NULL;
682 TR_RP_REALM *temp_rp = NULL;
687 (!json_is_array(jrps))) {
689 *rc = TR_CFG_BAD_PARAMS;
693 for (i = (json_array_size(jrps)-1); i >= 0; i--) {
694 if (NULL == (temp_rp = talloc(trc, TR_RP_REALM))) {
695 tr_debug("tr_cfg_parse_comm_rps: Can't allocate memory for RP Realm.");
700 memset (temp_rp, 0, sizeof(TR_RP_REALM));
702 if (NULL == (temp_rp->realm_name = tr_new_name((char *)json_string_value(json_array_get(jrps, i))))) {
703 tr_debug("tr_cfg_parse_comm_rps: No memory for RP Realm Name.");
716 static TR_COMM *tr_cfg_parse_one_comm (TR_CFG *trc, json_t *jcomm, TR_CFG_RC *rc) {
717 TR_COMM *comm = NULL;
719 json_t *jtype = NULL;
720 json_t *japcs = NULL;
721 json_t *jidps = NULL;
724 if ((!trc) || (!jcomm) || (!rc)) {
725 tr_debug("tr_cfg_parse_one_comm: Bad parameters.");
727 *rc = TR_CFG_BAD_PARAMS;
731 if (NULL == (comm = talloc_zero(trc, TR_COMM))) {
732 tr_crit("tr_cfg_parse_one_comm: Out of memory.");
738 if ((NULL == (jid = json_object_get(jcomm, "community_id"))) ||
739 (!json_is_string(jid)) ||
740 (NULL == (jtype = json_object_get(jcomm, "type"))) ||
741 (!json_is_string(jtype)) ||
742 (NULL == (japcs = json_object_get(jcomm, "apcs"))) ||
743 (!json_is_array(japcs)) ||
744 (NULL == (jidps = json_object_get(jcomm, "idp_realms"))) ||
745 (!json_is_array(jidps)) ||
746 (NULL == (jrps = json_object_get(jcomm, "rp_realms"))) ||
747 (!json_is_array(jrps))) {
748 tr_debug("tr_cfg_parse_one_comm: Error parsing Communities configuration.");
749 *rc = TR_CFG_NOPARSE;
753 if (NULL == (comm->id = tr_new_name((char *)json_string_value(jid)))) {
754 tr_debug("tr_cfg_parse_one_comm: No memory for community id.");
759 if (0 == strcmp(json_string_value(jtype), "apc")) {
760 comm->type = TR_COMM_APC;
761 } else if (0 == strcmp(json_string_value(jtype), "coi")) {
762 comm->type = TR_COMM_COI;
763 if (NULL == (comm->apcs = tr_cfg_parse_apcs(trc, japcs, rc))) {
764 tr_debug("tr_cfg_parse_one_comm: Can't parse APCs for COI %s.", comm->id->buf);
765 tr_free_name(comm->id);
769 tr_debug("tr_cfg_parse_one_comm: Invalid community type, comm = %s, type = %s", comm->id->buf, json_string_value(jtype));
770 tr_free_name(comm->id);
771 *rc = TR_CFG_NOPARSE;
775 comm->idp_realms = tr_cfg_parse_comm_idps(trc, jidps, rc);
776 if (TR_CFG_SUCCESS != *rc) {
777 tr_debug("tr_cfg_parse_one_comm: Can't parse IDP realms for comm %s.", comm->id->buf);
778 tr_free_name(comm->id);
782 comm->rp_realms = tr_cfg_parse_comm_rps(trc, jrps, rc);
783 if (TR_CFG_SUCCESS != *rc) {
784 tr_debug("tr_cfg_parse_comm: Can't parse RP realms for comm %s .", comm->id->buf);
785 tr_free_name(comm->id);
789 if (TR_COMM_APC == comm->type) {
790 json_t *jexpire = json_object_get(jcomm, "expiration_interval");
791 comm->expiration_interval = 43200; /*30 days*/
793 if (!json_is_integer(jexpire)) {
794 fprintf(stderr, "tr_parse_comm: expirae_interval is not an integer\n");
797 comm->expiration_interval = json_integer_value(jexpire);
798 if (comm->expiration_interval <= 10)
799 comm->expiration_interval = 11; /* Freeradius waits 10 minutes between successful TR queries*/
800 if (comm->expiration_interval > 129600) /* 90 days*/
801 comm->expiration_interval = 129600;
808 static TR_CFG_RC tr_cfg_parse_comms (TR_CFG *trc, json_t *jcfg)
810 json_t *jcomms = NULL;
811 TR_CFG_RC rc = TR_CFG_SUCCESS;
812 TR_COMM *comm = NULL;
815 if ((!trc) || (!jcfg)) {
816 tr_debug("tr_cfg_parse_comms: Bad Parameters.");
817 return TR_CFG_BAD_PARAMS;
820 if (NULL != (jcomms = json_object_get(jcfg, "communities"))) {
821 if (!json_is_array(jcomms)) {
822 return TR_CFG_NOPARSE;
825 for (i = 0; i < json_array_size(jcomms); i++) {
826 if (NULL == (comm = tr_cfg_parse_one_comm(trc,
827 json_array_get(jcomms, i),
831 tr_debug("tr_cfg_parse_comms: Community configured: %s.", comm->id->buf);
832 comm->next = trc->comms;
839 TR_CFG_RC tr_cfg_validate (TR_CFG *trc) {
840 TR_CFG_RC rc = TR_CFG_SUCCESS;
843 return TR_CFG_BAD_PARAMS;
845 if ((NULL == trc->internal)||
846 (NULL == trc->internal->hostname)) {
847 tr_debug("tr_cfg_validate: Error: No internal configuration, or no hostname.");
851 if (NULL == trc->rp_clients) {
852 tr_debug("tr_cfg_validate: Error: No RP Clients configured");
856 if (NULL == trc->comms) {
857 tr_debug("tr_cfg_validate: Error: No Communities configured");
861 if ((NULL == trc->default_servers) && (NULL == trc->idp_realms)) {
862 tr_debug("tr_cfg_validate: Error: No default servers or IDPs configured.");
869 TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, int n, struct dirent **cfg_files) {
873 if ((!tr) || (!cfg_files))
874 return TR_CFG_BAD_PARAMS;
876 /* If there is a partial/abandoned config lying around, free it */
878 tr_cfg_free(tr->new_cfg);
880 if (NULL == (tr->new_cfg = talloc(NULL, TR_CFG)))
883 memset(tr->new_cfg, 0, sizeof(TR_CFG));
885 /* Parse configuration information from each config file */
887 tr_debug("tr_read_config: Parsing %s.", cfg_files[n]->d_name);
888 if (NULL == (jcfg = json_load_file(cfg_files[n]->d_name,
889 JSON_DISABLE_EOF_CHECK, &rc))) {
890 tr_debug("tr_read_config: Error parsing config file %s.",
891 cfg_files[n]->d_name);
892 return TR_CFG_NOPARSE;
895 if ((TR_CFG_SUCCESS != tr_cfg_parse_internal(tr->new_cfg, jcfg)) ||
896 (TR_CFG_SUCCESS != tr_cfg_parse_rp_clients(tr->new_cfg, jcfg)) ||
897 (TR_CFG_SUCCESS != tr_cfg_parse_idp_realms(tr->new_cfg, jcfg)) ||
898 (TR_CFG_SUCCESS != tr_cfg_parse_default_servers(tr->new_cfg, jcfg)) ||
899 (TR_CFG_SUCCESS != tr_cfg_parse_comms(tr->new_cfg, jcfg))) {
900 tr_cfg_free(tr->new_cfg);
905 /* make sure we got a complete, consistent configuration */
906 if (TR_CFG_SUCCESS != tr_cfg_validate(tr->new_cfg)) {
907 tr_debug("tr_parse_config: Error: INVALID CONFIGURATION, EXITING");
911 return TR_CFG_SUCCESS;
914 TR_IDP_REALM *tr_cfg_find_idp (TR_CFG *tr_cfg, TR_NAME *idp_id, TR_CFG_RC *rc)
917 TR_IDP_REALM *cfg_idp;
919 if ((!tr_cfg) || (!idp_id)) {
921 *rc = TR_CFG_BAD_PARAMS;
925 for (cfg_idp = tr_cfg->idp_realms; NULL != cfg_idp; cfg_idp = cfg_idp->next) {
926 if (!tr_name_cmp (idp_id, cfg_idp->realm_id)) {
927 tr_debug("tr_cfg_find_idp: Found %s.", idp_id->buf);
931 /* if we didn't find one, return NULL */
935 TR_RP_CLIENT *tr_cfg_find_rp (TR_CFG *tr_cfg, TR_NAME *rp_gss, TR_CFG_RC *rc)
937 TR_RP_CLIENT *cfg_rp;
940 if ((!tr_cfg) || (!rp_gss)) {
942 *rc = TR_CFG_BAD_PARAMS;
946 for (cfg_rp = tr_cfg->rp_clients; NULL != cfg_rp; cfg_rp = cfg_rp->next) {
947 for (i = 0; i < TR_MAX_GSS_NAMES; i++) {
948 if (!tr_name_cmp (rp_gss, cfg_rp->gss_names[i])) {
949 tr_debug("tr_cfg_find_rp: Found %s.", rp_gss->buf);
954 /* if we didn't find one, return NULL */
958 static int is_cfg_file(const struct dirent *dent) {
961 /* if the last four letters of the filename are .cfg, return true. */
962 if ((4 <= (n = strlen(dent->d_name))) &&
963 (0 == strcmp(&(dent->d_name[n-4]), ".cfg"))) {
967 /* otherwise, return false. */
971 int tr_find_config_files (struct dirent ***cfg_files) {
974 n = scandir(".", cfg_files, &is_cfg_file, 0);
978 tr_debug("tr_find_config: scandir error.");
983 tr_debug("tr_find_config: No config files found.");
989 tr_debug("tr_find_config: Config file found (%s).", (*cfg_files)[i]->d_name);