Merge remote-tracking branch 'origin/tr-peering' into tr-peering
authorMargaret Wasserman <mrw@painless-security.com>
Fri, 19 Sep 2014 19:13:52 +0000 (15:13 -0400)
committerMargaret Wasserman <mrw@painless-security.com>
Fri, 19 Sep 2014 19:13:52 +0000 (15:13 -0400)
42 files changed:
.gitignore
Makefile.am
common/jansson_iterators.h [new file with mode: 0644]
common/t_constraint.c [new file with mode: 0644]
common/tests.json [new file with mode: 0644]
common/tr_config.c
common/tr_constraint.c
common/tr_dh.c
common/tr_filter.c
common/tr_idp.c
common/tr_msg.c
configure.ac
gsscon/.#gsscon_test.c [deleted symlink]
gsscon/gsscon_passive.c
include/tid_internal.h [new file with mode: 0644]
include/tr.h
include/tr_config.h
include/tr_debug.h [new file with mode: 0644]
include/tr_filter.h
include/tr_idp.h
include/tr_msg.h
include/trust_router/tid.h
include/trust_router/tr_constraint.h
include/trust_router/tr_dh.h
include/trust_router/tr_name.h
redhat/default-main.cfg [new file with mode: 0644]
redhat/init [new file with mode: 0755]
redhat/sysconfig [new file with mode: 0644]
redhat/tidc-wrapper [new file with mode: 0755]
redhat/tr-test-main.cfg [new file with mode: 0644]
redhat/trust_router-wrapper [new file with mode: 0755]
redhat/trusts.cfg [new file with mode: 0644]
schema.sql [new file with mode: 0644]
tid/example/tidc_main.c
tid/example/tids_main.c
tid/tid_req.c
tid/tid_resp.c
tid/tidc.c
tid/tids.c
tids.service [new file with mode: 0644]
tr/tr_main.c
trust_router.spec

index f46797e..7159568 100644 (file)
@@ -19,5 +19,6 @@ libtool
 config.*
 tr/trust_router
 common/dh_test/tr_dh_test
+common/t_constraint
 tid/example/tids
 tid/example/tidc
\ No newline at end of file
index 717b265..5fd1825 100644 (file)
@@ -1,20 +1,30 @@
+DISTCHECK_CONFIGURE_FLAGS = \
+       --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
 bin_PROGRAMS= tr/trust_router tid/example/tidc tid/example/tids common/dh_test/tr_dh_test
 AM_CPPFLAGS=-I$(srcdir)/include
-AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror=strict-prototypes -Wno-parentheses
+AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses
 SUBDIRS = gsscon 
 common_srcs = common/tr_name.c \
-common/tr_msg.c \
-common/tr_dh.c \
+       common/tr_constraint.c \
+       common/jansson_iterators.h \
+       common/tr_msg.c \
+       common/tr_dh.c \
        common/tr_util.c
 
+check_PROGRAMS = common/t_constraint
+TESTS = common/t_constraint
+
 lib_LTLIBRARIES = libtr_tid.la
 
+common_t_constraint_SOURCES = common/t_constraint.c
+common_t_constraint_CPPFLAGS = $(AM_CPPFLAGS) -DTESTS=\"$(srcdir)/common/tests.json\"
+common_t_constraint_LDADD = gsscon/libgsscon.la libtr_tid.la
+
 tr_trust_router_SOURCES = tr/tr_main.c \
 common/tr_config.c \
 common/tr_idp.c \
 common/tr_comm.c \
 common/tr_filter.c \
-common/tr_constraint.c \
 common/tr_rp.c \
 tr/tr.c
 
@@ -36,7 +46,7 @@ $(common_srcs)
 
 libtr_tid_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
 libtr_tid_la_LIBADD = gsscon/libgsscon.la
-libtr_tid_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1 -no-undefined
+libtr_tid_la_LDFLAGS = $(AM_LDFLAGS) -version-info 2 -no-undefined
 
 pkginclude_HEADERS = include/trust_router/tid.h include/trust_router/tr_name.h \
        include/trust_router/tr_dh.h \
@@ -44,10 +54,18 @@ pkginclude_HEADERS = include/trust_router/tid.h include/trust_router/tr_name.h \
        include/trust_router/tr_versioning.h 
 
 noinst_HEADERS = include/gsscon.h include/tr_config.h \
+       include/tr_debug.h \
        include/tr_msg.h include/tr.h \
        include/tr_idp.h include/tr_rp.h \
        include/tr_comm.h include/tr_apc.h \
-       include/tr_filter.h
+       include/tr_filter.h \
+       include/tid_internal.h
+
+pkgdata_DATA=schema.sql
+nobase_dist_pkgdata_DATA=redhat/init redhat/sysconfig redhat/trusts.cfg redhat/tidc-wrapper redhat/trust_router-wrapper redhat/tr-test-main.cfg redhat/default-main.cfg
 
+if HAVE_SYSTEMD
+systemdsystemunit_DATA = tids.service
+endif
 
-EXTRA_DIST = trust_router.spec
+EXTRA_DIST = trust_router.spec common/tests.json schema.sql tids.service
diff --git a/common/jansson_iterators.h b/common/jansson_iterators.h
new file mode 100644 (file)
index 0000000..c4e8a32
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009-2013 Petri Lehtinen <petri@digip.org>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+/*See the LICENSE file in the jansson source distribution.
+ */
+
+#ifndef json_object_foreach
+#define json_object_foreach(object, key, value) \
+    for(key = json_object_iter_key(json_object_iter(object)); \
+        key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
+        key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key))))
+#endif
+
+#ifndef json_array_foreach
+#define json_array_foreach(array, index, value) \
+       for(index = 0; \
+               index < json_array_size(array) && (value = json_array_get(array, index)); \
+               index++)
+#endif
diff --git a/common/t_constraint.c b/common/t_constraint.c
new file mode 100644 (file)
index 0000000..7ba9a14
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <jansson.h>
+#include "jansson_iterators.h"
+#include <stdio.h>
+#include <assert.h>
+
+#include <tid_internal.h>
+#include <trust_router/tr_constraint.h>
+#include <tr_debug.h>
+
+static TID_REQ *request = NULL;
+
+static int handle_test_case(
+                            json_t *tc)
+{
+  json_t *constraints, *valid, *expected;
+  int validp;
+  json_t *result;
+  assert(constraints = json_object_get(tc, "constraints"));
+  assert( valid = json_object_get(tc, "valid"));
+  validp = tr_constraint_set_validate((TR_CONSTRAINT_SET *)constraints);
+  if (validp != json_is_true(valid)) {
+    tr_debug("Unexpected validation result for \n");
+    json_dumpf( constraints, stderr, JSON_INDENT(4));
+    return 0;
+  }
+  if (!validp)
+    return 1;
+  assert( expected = json_object_get(tc, "expected"));
+  result = (json_t *) tr_constraint_set_intersect(request, (TR_CONSTRAINT_SET *) constraints);
+  if (!json_equal(result, expected)) {
+    tr_debug("Unexpected intersection; actual:\n");
+    json_dumpf(result, stderr, JSON_INDENT(4));
+    tr_debug("Expected: \n");
+    json_dumpf(expected, stderr, JSON_INDENT(4));
+    return 0;
+  }
+  return 1;
+}
+
+int main(void) {
+  json_t *tests;
+  int error=0;
+  json_t *tc;
+  size_t index;
+  request = tid_req_new();
+  tests = json_load_file(TESTS, JSON_REJECT_DUPLICATES|JSON_DISABLE_EOF_CHECK, NULL);
+  json_array_foreach(tests, index, tc)
+    if (!handle_test_case(tc))
+      error = 1;
+  if (error)
+    return 1;
+  return 0;
+}
diff --git a/common/tests.json b/common/tests.json
new file mode 100644 (file)
index 0000000..ba607e6
--- /dev/null
@@ -0,0 +1,44 @@
+[
+    {
+       "constraints": [{}],
+       "valid": true,
+       "expected": [{}]
+       },
+    {
+       "constraints": [33],
+       "valid": false
+       },
+    {
+       "constraints": [{
+           "domain": ["ja.net", "*.ja.net", "foo.ja.net"]
+           }],
+       "valid": true,
+       "expected": [{
+           "domain": ["ja.net", "*.ja.net"]
+           }]
+       },
+    {
+       "constraints": [{
+           "domain": ["*"],
+           "realm": ["*"]
+           },
+                       {
+                           "domain": ["*.cam.ac.uk"]
+                           }],
+       "expected": [{
+           "domain": ["*.cam.ac.uk"],
+           "realm": ['*']
+           }],
+       "valid": true
+       },
+    {"constraints": [
+       {"realm": ["painless-security.com", "*.painless-security.com"]},
+       {"domain": ["painless-security.com"]
+        }],
+     "expected": [{"realm": ["painless-security.com", "*.painless-security.com"],
+        "domain": ["painless-security.com"]
+        }],
+     "valid": true
+     }
+        
+            ]
index be851dc..ff92fd0 100644 (file)
 #include <string.h>
 #include <jansson.h>
 #include <dirent.h>
+#include <talloc.h>
 
 #include <tr_config.h>
 #include <tr.h>
 #include <tr_filter.h>
 #include <trust_router/tr_constraint.h>
+
 void tr_print_config (FILE *stream, TR_CFG *cfg) {
   fprintf(stream, "tr_print_config: Not yet implemented.\n");
   return;
 }
 
 void tr_cfg_free (TR_CFG *cfg) {
-  /* TBD -- need to deallocate memory as part of dynamic config */
+  talloc_free(cfg);
   return;
 }
 
 TR_CFG_RC tr_apply_new_config (TR_INSTANCE *tr) {
-
   if (!tr)
     return TR_CFG_BAD_PARAMS;
 
@@ -63,70 +64,65 @@ TR_CFG_RC tr_apply_new_config (TR_INSTANCE *tr) {
   return TR_CFG_SUCCESS;
 }
 
-static TR_CFG_RC tr_cfg_parse_internal (TR_INSTANCE *tr, json_t *jcfg) {
+static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
   json_t *jint = NULL;
   json_t *jmtd = NULL;
   json_t *jtp = NULL;
   json_t *jhname = NULL;
 
-  if ((!tr) || (!tr->new_cfg) || (!jcfg))
+  if ((!trc) || (!jcfg))
     return TR_CFG_BAD_PARAMS;
 
-  if (NULL == (tr->new_cfg->internal = malloc(sizeof(TR_CFG_INTERNAL))))
-    return TR_CFG_NOMEM;
+  if (NULL == trc->internal) {
+    if (NULL == (trc->internal = talloc(trc, TR_CFG_INTERNAL)))
+      return TR_CFG_NOMEM;
 
-  memset(tr->new_cfg->internal, 0, sizeof(TR_CFG_INTERNAL));
+    memset(trc->internal, 0, sizeof(TR_CFG_INTERNAL));
+  }
 
   if (NULL != (jint = json_object_get(jcfg, "tr_internal"))) {
     if (NULL != (jmtd = json_object_get(jint, "max_tree_depth"))) {
       if (json_is_number(jmtd)) {
-       tr->new_cfg->internal->max_tree_depth = json_integer_value(jmtd);
+       trc->internal->max_tree_depth = json_integer_value(jmtd);
       } else {
        fprintf(stderr,"tr_cfg_parse_internal: Parsing error, max_tree_depth is not a number.\n");
        return TR_CFG_NOPARSE;
       }
     } else {
       /* If not configured, use the default */
-      tr->new_cfg->internal->max_tree_depth = TR_DEFAULT_MAX_TREE_DEPTH;
+      trc->internal->max_tree_depth = TR_DEFAULT_MAX_TREE_DEPTH;
     }
     if (NULL != (jtp = json_object_get(jint, "tids_port"))) {
       if (json_is_number(jtp)) {
-       tr->new_cfg->internal->tids_port = json_integer_value(jtp);
+       trc->internal->tids_port = json_integer_value(jtp);
       } else {
        fprintf(stderr,"tr_cfg_parse_internal: Parsing error, port is not a number.\n");
        return TR_CFG_NOPARSE;
       }
     } else {
       /* If not configured, use the default */
-      tr->new_cfg->internal->tids_port = TR_DEFAULT_TIDS_PORT;
+      trc->internal->tids_port = TR_DEFAULT_TIDS_PORT;
     }
     if (NULL != (jhname = json_object_get(jint, "hostname"))) {
       if (json_is_string(jhname)) {
-       tr->new_cfg->internal->hostname = json_string_value(jhname);
+       trc->internal->hostname = json_string_value(jhname);
       } else {
        fprintf(stderr,"tr_cfg_parse_internal: Parsing error, hostname is not a string.\n");
        return TR_CFG_NOPARSE;
       }
     }
-    else {
-      fprintf(stderr, "tr_cfg_parse_internal: Parsing error, hostname is not found.\n");
-      return TR_CFG_NOPARSE;
-    }
-  fprintf(stderr, "tr_cfg_parse_internal: Internal config parsed.\n");
-  return TR_CFG_SUCCESS;
-  }
-  else {
-    fprintf(stderr, "tr_cfg_parse_internal: Parsing error, tr_internal configuration section not found.\n");
-    return TR_CFG_NOPARSE;
+    fprintf(stderr, "tr_cfg_parse_internal: Internal config parsed.\n");
+    return TR_CFG_SUCCESS;
   }
+  return TR_CFG_SUCCESS;
 }
 
-static TR_CONSTRAINT *tr_cfg_parse_one_constraint (TR_INSTANCE *tr, char *ctype, json_t *jc, TR_CFG_RC *rc)
+static TR_CONSTRAINT *tr_cfg_parse_one_constraint (TR_CFG *trc, char *ctype, json_t *jc, TR_CFG_RC *rc)
 {
   TR_CONSTRAINT *cons;
   int i;
 
-  if ((!tr) || (!ctype) || (!jc) || (!rc) ||
+  if ((!trc) || (!ctype) || (!jc) || (!rc) ||
       (!json_is_array(jc)) ||
       (0 >= json_array_size(jc)) ||
       (TR_MAX_CONST_MATCHES < json_array_size(jc)) ||
@@ -136,7 +132,7 @@ static TR_CONSTRAINT *tr_cfg_parse_one_constraint (TR_INSTANCE *tr, char *ctype,
     return NULL;
   }
 
-  if (NULL == (cons = malloc(sizeof(TR_CONSTRAINT)))) {
+  if (NULL == (cons = talloc(trc, TR_CONSTRAINT))) {
     fprintf(stderr, "tr_cfg_parse_one_constraint: Out of memory (cons).\n");
     *rc = TR_CFG_NOMEM;
     return NULL;
@@ -157,7 +153,7 @@ static TR_CONSTRAINT *tr_cfg_parse_one_constraint (TR_INSTANCE *tr, char *ctype,
   return cons;
 }
 
-static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CFG_RC *rc)
+static TR_FILTER *tr_cfg_parse_one_filter (TR_CFG *trc, json_t *jfilt, TR_CFG_RC *rc)
 {
   TR_FILTER *filt = NULL;
   json_t *jftype = NULL;
@@ -190,8 +186,8 @@ static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CF
     return NULL;
   }
 
-  if (NULL == (filt = malloc(sizeof(TR_FILTER)))) {
-    fprintf(stderr, "tr_config_parse_one_filter: Out of memory.\n");
+  if (NULL == (filt = talloc(trc, TR_FILTER))) {
+    fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory.\n");
     *rc = TR_CFG_NOMEM;
     return NULL;
   }
@@ -235,8 +231,8 @@ static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CF
       return NULL;
     }
 
-    if (NULL == (filt->lines[i] = malloc(sizeof(TR_FLINE)))) {
-      fprintf(stderr, "tr_config_parse_one_filter: Out of memory (fline).\n");
+    if (NULL == (filt->lines[i] = talloc(trc, TR_FLINE))) {
+      fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory (fline).\n");
       *rc = TR_CFG_NOMEM;
       tr_filter_free(filt);
       return NULL;
@@ -262,7 +258,7 @@ static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CF
        (0 != json_array_size(jrc)) &&
        (TR_MAX_CONST_MATCHES >= json_array_size(jrc))) {
 
-      if (NULL == (filt->lines[i]->realm_cons = tr_cfg_parse_one_constraint(tr, "realm", jrc, rc))) {
+      if (NULL == (filt->lines[i]->realm_cons = tr_cfg_parse_one_constraint(trc, "realm", jrc, rc))) {
        fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing realm constraint");
       tr_filter_free(filt);
       return NULL;
@@ -274,7 +270,7 @@ static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CF
        (0 != json_array_size(jdc)) &&
        (TR_MAX_CONST_MATCHES >= json_array_size(jdc))) {
 
-      if (NULL == (filt->lines[i]->domain_cons = tr_cfg_parse_one_constraint(tr, "domain", jdc, rc))) {
+      if (NULL == (filt->lines[i]->domain_cons = tr_cfg_parse_one_constraint(trc, "domain", jdc, rc))) {
        fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing domain constraint");
       tr_filter_free(filt);
       return NULL;
@@ -294,8 +290,8 @@ static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CF
        return NULL;
       }
 
-      if (NULL == (filt->lines[i]->specs[j] = malloc(sizeof(TR_FSPEC)))) {
-       fprintf(stderr, "tr_config_parse_one_filter: Out of memory.\n");
+      if (NULL == (filt->lines[i]->specs[j] = talloc(trc, TR_FSPEC))) {
+       fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory.\n");
        *rc = TR_CFG_NOMEM;
        tr_filter_free(filt);
        return NULL;
@@ -305,7 +301,7 @@ static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CF
     
       if ((NULL == (filt->lines[i]->specs[j]->field = tr_new_name((char *)json_string_value(jffield)))) ||
          (NULL == (filt->lines[i]->specs[j]->match = tr_new_name((char *)json_string_value(jfmatch))))) {
-       fprintf(stderr, "tr_config_parse_one_filter: Out of memory.\n");
+       fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory.\n");
        *rc = TR_CFG_NOMEM;
        tr_filter_free(filt);
        return NULL;
@@ -316,7 +312,7 @@ static TR_FILTER *tr_cfg_parse_one_filter (TR_INSTANCE *tr, json_t *jfilt, TR_CF
   return filt;
 }
 
-static TR_RP_CLIENT *tr_cfg_parse_one_rp_client (TR_INSTANCE *tr, json_t *jrp, TR_CFG_RC *rc)
+static TR_RP_CLIENT *tr_cfg_parse_one_rp_client (TR_CFG *trc, json_t *jrp, TR_CFG_RC *rc)
 {
   TR_RP_CLIENT *rp = NULL;
   json_t *jgns = NULL;
@@ -324,7 +320,7 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client (TR_INSTANCE *tr, json_t *jrp, T
   json_t *jftype = NULL;
   int i = 0;
 
-  if ((!jrp) || (!rc)) {
+  if ((!trc) || (!jrp) || (!rc)) {
     fprintf(stderr, "tr_cfg_parse_one_rp_realm: Bad parameters.\n");
     if (rc)
       *rc = TR_CFG_BAD_PARAMS;
@@ -360,8 +356,8 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client (TR_INSTANCE *tr, json_t *jrp, T
     return NULL;
   }
 
-  if (NULL == (rp = malloc(sizeof(TR_RP_CLIENT)))) {
-    fprintf(stderr, "tr_config_parse_one_rp_realm: Out of memory.\n");
+  if (NULL == (rp = talloc(trc, TR_RP_CLIENT))) {
+    fprintf(stderr, "tr_cfg_parse_one_rp_realm: Out of memory.\n");
     *rc = TR_CFG_NOMEM;
     return NULL;
   }
@@ -369,7 +365,7 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client (TR_INSTANCE *tr, json_t *jrp, T
   memset(rp, 0, sizeof(TR_RP_CLIENT));
 
   /* TBD -- support more than one filter entry per RP Client? */
-  if (NULL == (rp->filter = tr_cfg_parse_one_filter(tr, jfilt, rc))) {
+  if (NULL == (rp->filter = tr_cfg_parse_one_filter(trc, jfilt, rc))) {
     fprintf(stderr, "tr_cfg_parse_one_rp_client: Error parsing filter.\n");
     free(rp);
     *rc = TR_CFG_NOPARSE;
@@ -388,44 +384,46 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client (TR_INSTANCE *tr, json_t *jrp, T
   return rp;
 }
 
-static TR_CFG_RC tr_cfg_parse_rp_clients (TR_INSTANCE *tr, json_t *jcfg) {
+static TR_CFG_RC tr_cfg_parse_rp_clients (TR_CFG *trc, json_t *jcfg) {
   json_t *jrps = NULL;
   TR_RP_CLIENT *rp = NULL;
   TR_CFG_RC rc = TR_CFG_SUCCESS;
   int i = 0;
 
-  if ((!tr) || (!tr->new_cfg) || (!jcfg))
+  if ((!trc) || (!jcfg))
     return TR_CFG_BAD_PARAMS;
 
-  if ((NULL == (jrps = json_object_get(jcfg, "rp_clients"))) ||
-      (!json_is_array(jrps))) {
-    return TR_CFG_NOPARSE;
-  }
+  if (NULL != (jrps = json_object_get(jcfg, "rp_clients"))) {
 
-  for (i = 0; i < json_array_size(jrps); i++) {
-    if (NULL == (rp = tr_cfg_parse_one_rp_client(tr, 
-                                                json_array_get(jrps, i), 
-                                                &rc))) {
-       return rc;
+    if (!json_is_array(jrps)) {
+      return TR_CFG_NOPARSE;
+    }
+
+    for (i = 0; i < json_array_size(jrps); i++) {
+      if (NULL == (rp = tr_cfg_parse_one_rp_client(trc, 
+                                                  json_array_get(jrps, i), 
+                                                  &rc))) {
+       return rc;
+      }
+      fprintf(stderr, "tr_cfg_parse_rp_clients: RP client configured -- first gss: %s", rp->gss_names[0]->buf);
+      rp->next = trc->rp_clients;
+      trc->rp_clients = rp;
     }
-    fprintf(stderr, "tr_cfg_parse_rp_clients: RP client configured -- first gss: %s", rp->gss_names[0]->buf);
-    rp->next = tr->new_cfg->rp_clients;
-    tr->new_cfg->rp_clients = rp;
   }
   return rc;
 }
 
-static TR_AAA_SERVER *tr_cfg_parse_one_aaa_server (TR_INSTANCE *tr, json_t *jaddr, TR_CFG_RC *rc) {
+static TR_AAA_SERVER *tr_cfg_parse_one_aaa_server (TR_CFG *trc, json_t *jaddr, TR_CFG_RC *rc) {
   TR_AAA_SERVER *aaa = NULL;
 
-  if ((!tr) || (!tr->new_cfg) || (!jaddr) || (!json_is_string(jaddr))) {
+  if ((!trc) || (!jaddr) || (!json_is_string(jaddr))) {
     fprintf(stderr, "tr_cfg_parse_one_aaa_server: Bad parameters.\n");
     *rc = TR_CFG_BAD_PARAMS;
     return NULL;
   }
 
-  if (NULL == (aaa = malloc(sizeof(TR_AAA_SERVER)))) {
-    fprintf(stderr, "tr_config_parse_one_aaa_server: Out of memory.\n");
+  if (NULL == (aaa = talloc(trc, TR_AAA_SERVER))) {
+    fprintf(stderr, "tr_cfg_parse_one_aaa_server: Out of memory.\n");
     *rc = TR_CFG_NOMEM;
     return NULL;
   }
@@ -437,15 +435,14 @@ static TR_AAA_SERVER *tr_cfg_parse_one_aaa_server (TR_INSTANCE *tr, json_t *jadd
   return aaa;
 }
 
-
-static TR_AAA_SERVER *tr_cfg_parse_aaa_servers (TR_INSTANCE *tr, json_t *jaaas, TR_CFG_RC *rc) 
+static TR_AAA_SERVER *tr_cfg_parse_aaa_servers (TR_CFG *trc, json_t *jaaas, TR_CFG_RC *rc) 
 {
   TR_AAA_SERVER *aaa = NULL;
   TR_AAA_SERVER *temp_aaa = NULL;
   int i = 0;
 
   for (i = 0; i < json_array_size(jaaas); i++) {
-    if (NULL == (temp_aaa = tr_cfg_parse_one_aaa_server(tr, json_array_get(jaaas, i), rc))) {
+    if (NULL == (temp_aaa = tr_cfg_parse_one_aaa_server(trc, json_array_get(jaaas, i), rc))) {
       return NULL;
     }
     /* TBD -- IPv6 addresses */
@@ -456,20 +453,20 @@ static TR_AAA_SERVER *tr_cfg_parse_aaa_servers (TR_INSTANCE *tr, json_t *jaaas,
   return aaa;
 }
 
-static TR_APC *tr_cfg_parse_apcs (TR_INSTANCE *tr, json_t *japcs, TR_CFG_RC *rc)
+static TR_APC *tr_cfg_parse_apcs (TR_CFG *trc, json_t *japcs, TR_CFG_RC *rc)
 {
   TR_APC *apc;
 
   *rc = TR_CFG_SUCCESS;                /* presume success */
 
-  if ((!japcs) || (!rc)) {
+  if ((!trc) || (!japcs) || (!rc)) {
     fprintf(stderr, "tr_cfg_parse_apcs: Bad parameters.\n");
     if (rc) 
       *rc = TR_CFG_BAD_PARAMS;
     return NULL;
   }
 
-  if (NULL == (apc = malloc(sizeof(TR_APC)))) {
+  if (NULL == (apc = talloc(trc, TR_APC))) {
     fprintf (stderr, "tr_cfg_parse_apcs: Out of memory.\n");
     *rc = TR_CFG_NOMEM;
     return NULL;
@@ -491,22 +488,22 @@ static TR_APC *tr_cfg_parse_apcs (TR_INSTANCE *tr, json_t *japcs, TR_CFG_RC *rc)
   return apc;
 }
 
-static TR_IDP_REALM *tr_cfg_parse_one_idp_realm (TR_INSTANCE *tr, json_t *jidp, TR_CFG_RC *rc) {
+static TR_IDP_REALM *tr_cfg_parse_one_idp_realm (TR_CFG *trc, json_t *jidp, TR_CFG_RC *rc) {
   TR_IDP_REALM *idp = NULL;
   json_t *jrid = NULL;
   json_t *jscfg = NULL;
   json_t *jsrvrs = NULL;
   json_t *japcs = NULL;
 
-  if ((!jidp) || (!rc)) {
+  if ((!trc) || (!jidp) || (!rc)) {
     fprintf(stderr, "tr_cfg_parse_one_idp_realm: Bad parameters.\n");
     if (rc)
       *rc = TR_CFG_BAD_PARAMS;
     return NULL;
   }
 
-  if (NULL == (idp = malloc(sizeof(TR_IDP_REALM)))) {
-    fprintf(stderr, "tr_config_parse_one_idp_realm: Out of memory.\n");
+  if (NULL == (idp = talloc(trc, TR_IDP_REALM))) {
+    fprintf(stderr, "tr_cfg_parse_one_idp_realm: Out of memory.\n");
     *rc = TR_CFG_NOMEM;
     return NULL;
   }
@@ -538,7 +535,7 @@ static TR_IDP_REALM *tr_cfg_parse_one_idp_realm (TR_INSTANCE *tr, json_t *jidp,
     return NULL;
   }
 
-  if (NULL == (idp->aaa_servers = tr_cfg_parse_aaa_servers(tr, jsrvrs, rc))) {
+  if (NULL == (idp->aaa_servers = tr_cfg_parse_aaa_servers(trc, jsrvrs, rc))) {
     fprintf(stderr, "tr_cfg_parse_one_idp_realm: Can't parse AAA servers for realm %s.\n", idp->realm_id->buf);
     tr_free_name(idp->realm_id);
     free(idp);
@@ -547,7 +544,7 @@ static TR_IDP_REALM *tr_cfg_parse_one_idp_realm (TR_INSTANCE *tr, json_t *jidp,
 
   if ((NULL != (japcs = json_object_get(jidp, "apcs"))) &&
       (json_is_array(japcs))) {
-    if (NULL == (idp->apcs = tr_cfg_parse_apcs(tr, japcs, rc))) {
+    if (NULL == (idp->apcs = tr_cfg_parse_apcs(trc, japcs, rc))) {
       fprintf(stderr, "tr_cfg_parse_one_idp_realm: Can't parse APCs for realm %s .\n", idp->realm_id->buf);
       tr_free_name(idp->realm_id);
       /* TBD -- free aaa_servers */;
@@ -558,41 +555,71 @@ static TR_IDP_REALM *tr_cfg_parse_one_idp_realm (TR_INSTANCE *tr, json_t *jidp,
   return idp;
 }
 
-static TR_CFG_RC tr_cfg_parse_idp_realms (TR_INSTANCE *tr, json_t *jcfg) 
+static TR_CFG_RC tr_cfg_parse_default_servers (TR_CFG *trc, json_t *jcfg) 
 {
-  json_t *jidps = NULL;
+  json_t *jdss = NULL;
   TR_CFG_RC rc = TR_CFG_SUCCESS;
-  TR_IDP_REALM *idp = NULL;
+  TR_AAA_SERVER *ds = NULL;
   int i = 0;
 
-  if ((!tr) || (!tr->new_cfg) || (!jcfg))
+  if ((!trc) || (!jcfg))
     return TR_CFG_BAD_PARAMS;
 
-  if ((NULL == (jidps = json_object_get(jcfg, "idp_realms"))) ||
-      (!json_is_array(jidps))) {
-    return TR_CFG_NOPARSE;
-  }
+  /* If there are default servers, store them */
+  if ((NULL != (jdss = json_object_get(jcfg, "default_servers"))) &&
+      (json_is_array(jdss)) &&
+      (0 < json_array_size(jdss))) {
 
-  for (i = 0; i < json_array_size(jidps); i++) {
-    if (NULL == (idp = tr_cfg_parse_one_idp_realm(tr
-                                                 json_array_get(jidps, i), 
+    for (i = 0; i < json_array_size(jdss); i++) {
+      if (NULL == (ds = tr_cfg_parse_one_aaa_server(trc
+                                                 json_array_get(jdss, i), 
                                                  &rc))) {
-       return rc;
+       return rc;
+      }
+      fprintf(stderr, "tr_cfg_parse_default_servers: Default server configured.\n");
+      ds->next = trc->default_servers;
+      trc->default_servers = ds;
+    }
+  } 
+
+  return rc;
+}
+
+static TR_CFG_RC tr_cfg_parse_idp_realms (TR_CFG *trc, json_t *jcfg) 
+{
+  json_t *jidps = NULL;
+  TR_CFG_RC rc = TR_CFG_SUCCESS;
+  TR_IDP_REALM *idp = NULL;
+  int i = 0;
+
+  if ((!trc) || (!jcfg))
+    return TR_CFG_BAD_PARAMS;
+
+  /* If there are any IDP Realms, parse them */
+  if ((NULL != (jidps = json_object_get(jcfg, "idp_realms"))) &&
+      (json_is_array(jidps))) {
+    for (i = 0; i < json_array_size(jidps); i++) {
+      if (NULL == (idp = tr_cfg_parse_one_idp_realm(trc,
+                                                   json_array_get(jidps, i), 
+                                                   &rc))) {
+       return rc;
+      }
+      fprintf(stderr, "tr_cfg_parse_idp_realms: IDP realm configured: %s.\n", idp->realm_id->buf);
+      idp->next = trc->idp_realms;
+      trc->idp_realms = idp;
     }
-    fprintf(stderr, "tr_cfg_parse_idp_realms: IDP realm configured: %s.\n", idp->realm_id->buf);
-    idp->next = tr->new_cfg->idp_realms;
-    tr->new_cfg->idp_realms = idp;
   }
+
   return rc;
 }
 
-static TR_IDP_REALM *tr_cfg_parse_comm_idps (TR_INSTANCE *tr, json_t *jidps, TR_CFG_RC *rc)
+static TR_IDP_REALM *tr_cfg_parse_comm_idps (TR_CFG *trc, json_t *jidps, TR_CFG_RC *rc)
 {
   TR_IDP_REALM *idp = NULL;
   TR_IDP_REALM *temp_idp = NULL;
   int i = 0;
 
-  if ((!tr) ||
+  if ((!trc) ||
       (!jidps) ||
       (!json_is_array(jidps))) {
     if (rc)
@@ -601,7 +628,7 @@ static TR_IDP_REALM *tr_cfg_parse_comm_idps (TR_INSTANCE *tr, json_t *jidps, TR_
   }
 
   for (i = 0; i < json_array_size(jidps); i++) {
-    if (NULL == (temp_idp = (tr_cfg_find_idp(tr->new_cfg
+    if (NULL == (temp_idp = (tr_cfg_find_idp(trc
                                             tr_new_name((char *)json_string_value(json_array_get(jidps, i))), 
                                             rc)))) {
       fprintf(stderr, "tr_cfg_parse_comm_idps: Unknown IDP %s.\n", 
@@ -616,13 +643,13 @@ static TR_IDP_REALM *tr_cfg_parse_comm_idps (TR_INSTANCE *tr, json_t *jidps, TR_
   return idp;
 }
 
-static TR_RP_REALM *tr_cfg_parse_comm_rps (TR_INSTANCE *tr, json_t *jrps, TR_CFG_RC *rc)
+static TR_RP_REALM *tr_cfg_parse_comm_rps (TR_CFG *trc, json_t *jrps, TR_CFG_RC *rc)
 {
   TR_RP_REALM *rp = NULL;
   TR_RP_REALM *temp_rp = NULL;
   int i = 0;
 
-  if ((!tr) ||
+  if ((!trc) ||
       (!jrps) ||
       (!json_is_array(jrps))) {
     if (rc)
@@ -631,7 +658,7 @@ static TR_RP_REALM *tr_cfg_parse_comm_rps (TR_INSTANCE *tr, json_t *jrps, TR_CFG
   }
 
   for (i = (json_array_size(jrps)-1); i >= 0; i--) {
-    if (NULL == (temp_rp = malloc(sizeof(TR_RP_REALM)))) {
+    if (NULL == (temp_rp = talloc(trc, TR_RP_REALM))) {
       fprintf(stderr, "tr_cfg_parse_comm_rps: Can't allocate memory for RP Realm.\n");
       if (rc)
        *rc = TR_CFG_NOMEM;
@@ -653,7 +680,7 @@ static TR_RP_REALM *tr_cfg_parse_comm_rps (TR_INSTANCE *tr, json_t *jrps, TR_CFG
   return rp;
 }
 
-static TR_COMM *tr_cfg_parse_one_comm (TR_INSTANCE *tr, json_t *jcomm, TR_CFG_RC *rc) {
+static TR_COMM *tr_cfg_parse_one_comm (TR_CFG *trc, json_t *jcomm, TR_CFG_RC *rc) {
   TR_COMM *comm = NULL;
   json_t *jid = NULL;
   json_t *jtype = NULL;
@@ -661,15 +688,15 @@ static TR_COMM *tr_cfg_parse_one_comm (TR_INSTANCE *tr, json_t *jcomm, TR_CFG_RC
   json_t *jidps = NULL;
   json_t *jrps = NULL;
 
-  if ((!jcomm) || (!rc)) {
+  if ((!trc) || (!jcomm) || (!rc)) {
     fprintf(stderr, "tr_cfg_parse_one_comm: Bad parameters.\n");
     if (rc)
       *rc = TR_CFG_BAD_PARAMS;
     return NULL;
   }
 
-  if (NULL == (comm = malloc(sizeof(TR_COMM)))) {
-    fprintf(stderr, "tr_config_parse_one_comm: Out of memory.\n");
+  if (NULL == (comm = talloc(trc, TR_COMM))) {
+    fprintf(stderr, "tr_cfg_parse_one_comm: Out of memory.\n");
     *rc = TR_CFG_NOMEM;
     return NULL;
   }
@@ -703,7 +730,7 @@ static TR_COMM *tr_cfg_parse_one_comm (TR_INSTANCE *tr, json_t *jcomm, TR_CFG_RC
     comm->type = TR_COMM_APC;
   } else if (0 == strcmp(json_string_value(jtype), "coi")) {
     comm->type = TR_COMM_COI;
-    if (NULL == (comm->apcs = tr_cfg_parse_apcs(tr, japcs, rc))) {
+    if (NULL == (comm->apcs = tr_cfg_parse_apcs(trc, japcs, rc))) {
       fprintf(stderr, "tr_cfg_parse_one_comm: Can't parse APCs for COI %s.\n", comm->id->buf);
       tr_free_name(comm->id);
       free(comm);
@@ -717,7 +744,7 @@ static TR_COMM *tr_cfg_parse_one_comm (TR_INSTANCE *tr, json_t *jcomm, TR_CFG_RC
     return NULL;
   }
 
-  comm->idp_realms = tr_cfg_parse_comm_idps(tr, jidps, rc);
+  comm->idp_realms = tr_cfg_parse_comm_idps(trc, jidps, rc);
   if (TR_CFG_SUCCESS != *rc) {
     fprintf(stderr, "tr_cfg_parse_one_comm: Can't parse IDP realms for comm %s.\n", comm->id->buf);
     tr_free_name(comm->id);
@@ -725,7 +752,7 @@ static TR_COMM *tr_cfg_parse_one_comm (TR_INSTANCE *tr, json_t *jcomm, TR_CFG_RC
     return NULL;
   }
 
-  comm->rp_realms = tr_cfg_parse_comm_rps(tr, jrps, rc);
+  comm->rp_realms = tr_cfg_parse_comm_rps(trc, jrps, rc);
   if (TR_CFG_SUCCESS != *rc) {
     fprintf(stderr, "tr_cfg_parse_comm: Can't parse RP realms for comm %s .\n", comm->id->buf);
     tr_free_name(comm->id);
@@ -737,61 +764,110 @@ static TR_COMM *tr_cfg_parse_one_comm (TR_INSTANCE *tr, json_t *jcomm, TR_CFG_RC
   return comm;
 }
 
-static TR_CFG_RC tr_cfg_parse_comms (TR_INSTANCE *tr, json_t *jcfg) 
+static TR_CFG_RC tr_cfg_parse_comms (TR_CFG *trc, json_t *jcfg) 
 {
   json_t *jcomms = NULL;
   TR_CFG_RC rc = TR_CFG_SUCCESS;
   TR_COMM *comm = NULL;
   int i = 0;
 
-  if ((!tr) || (!tr->new_cfg) || (!jcfg)) {
-    fprintf(stderr, "tr_config_parse_comms: Bad Parameters.\n");
+  if ((!trc) || (!jcfg)) {
+    fprintf(stderr, "tr_cfg_parse_comms: Bad Parameters.\n");
     return TR_CFG_BAD_PARAMS;
   }
 
-  if (NULL == (comm = malloc(sizeof(TR_COMM)))) {
-    fprintf(stderr, "tr_cfg_parse_comms: Out of Memory\n");
-    return TR_CFG_NOMEM;
+  if (NULL != (jcomms = json_object_get(jcfg, "communities"))) {
+    if (!json_is_array(jcomms)) {
+      return TR_CFG_NOPARSE;
+    }
+
+    for (i = 0; i < json_array_size(jcomms); i++) {
+      if (NULL == (comm = tr_cfg_parse_one_comm(trc, 
+                                               json_array_get(jcomms, i), 
+                                               &rc))) {
+       return rc;
+      }
+      fprintf(stderr, "tr_cfg_parse_comms: Community configured: %s.\n", comm->id->buf);
+      comm->next = trc->comms;
+      trc->comms = comm;
+    }
   }
-  memset (comm, 0, sizeof(TR_COMM));
+  return rc;
+}
+
+TR_CFG_RC tr_cfg_validate (TR_CFG *trc) {
+  TR_CFG_RC rc = TR_CFG_SUCCESS;
 
-  if ((NULL == (jcomms = json_object_get(jcfg, "communities"))) ||
-      (!json_is_array(jcomms))) {
-    return TR_CFG_NOPARSE;
+  if (!trc)
+    return TR_CFG_BAD_PARAMS;
+
+  if ((NULL == trc->internal)||
+      (NULL == trc->internal->hostname)) {
+    fprintf(stderr, "tr_cfg_validate: Error: No internal configuration, or no hostname.\n");
+    rc = TR_CFG_ERROR;
   }
 
-  for (i = 0; i < json_array_size(jcomms); i++) {
-    if (NULL == (comm = tr_cfg_parse_one_comm(tr, 
-                                             json_array_get(jcomms, i), 
-                                             &rc))) {
-       return rc;
-    }
-    fprintf(stderr, "tr_cfg_parse_comms: Community configured: %s.\n", comm->id->buf);
-    comm->next = tr->new_cfg->comms;
-    tr->new_cfg->comms = comm;
+  if (NULL == trc->rp_clients) {
+    fprintf(stderr, "tr_cfg_validate: Error: No RP Clients configured\n");
+    rc = TR_CFG_ERROR;
   }
+
+  if (NULL == trc->comms) {
+    fprintf(stderr, "tr_cfg_validate: Error: No Communities configured\n");
+    rc = TR_CFG_ERROR;
+  }
+
+  if ((NULL == trc->default_servers) && (NULL == trc->idp_realms)) {
+    fprintf(stderr, "tr_cfg_validate: Error: No default servers or IDPs configured.\n");
+    rc = TR_CFG_ERROR;
+  }
+  
   return rc;
 }
 
-TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, json_t *jcfg) {
+TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, struct dirent **cfg_files) {
+  json_t *jcfg;
+  json_error_t rc;
+  int n;
+
+  if ((!tr) || (!cfg_files))
+    return TR_CFG_BAD_PARAMS;
 
   /* If there is a partial/abandoned config lying around, free it */
-  if (tr->new_cfg) {
+  if (tr->new_cfg) 
     tr_cfg_free(tr->new_cfg);
-  }
   
-  if (NULL == (tr->new_cfg = malloc(sizeof(TR_CFG))))
+  if (NULL == (tr->new_cfg = talloc(NULL, TR_CFG)))
     return TR_CFG_NOMEM;
 
   memset(tr->new_cfg, 0, sizeof(TR_CFG));
 
-  if ((TR_CFG_SUCCESS != tr_cfg_parse_internal(tr, jcfg)) ||
-      (TR_CFG_SUCCESS != tr_cfg_parse_rp_clients(tr, jcfg)) ||
-      (TR_CFG_SUCCESS != tr_cfg_parse_idp_realms(tr, jcfg)) ||
-      (TR_CFG_SUCCESS != tr_cfg_parse_comms(tr, jcfg))) {
-    tr_cfg_free(tr->new_cfg);
+  /* Parse configuration information from each config file */
+  while (n--) {
+    fprintf(stderr, "tr_read_config: Parsing %s.\n", cfg_files[n]->d_name);
+    if (NULL == (jcfg = json_load_file(cfg_files[n]->d_name, 
+                                      JSON_DISABLE_EOF_CHECK, &rc))) {
+      fprintf (stderr, "tr_read_config: Error parsing config file %s.\n", 
+              cfg_files[n]->d_name);
+      return TR_CFG_NOPARSE;
+    }
+       
+    if ((TR_CFG_SUCCESS != tr_cfg_parse_internal(tr->new_cfg, jcfg)) ||
+       (TR_CFG_SUCCESS != tr_cfg_parse_rp_clients(tr->new_cfg, jcfg)) ||
+       (TR_CFG_SUCCESS != tr_cfg_parse_idp_realms(tr->new_cfg, jcfg)) ||
+       (TR_CFG_SUCCESS != tr_cfg_parse_default_servers(tr->new_cfg, jcfg)) ||
+       (TR_CFG_SUCCESS != tr_cfg_parse_comms(tr->new_cfg, jcfg))) {
+      tr_cfg_free(tr->new_cfg);
+      return TR_CFG_ERROR;
+    }
+  }
+
+  /* make sure we got a complete, consistent configuration */
+  if (TR_CFG_SUCCESS != tr_cfg_validate(tr->new_cfg)) {
+    fprintf(stderr, "tr_parse_config: Error: INVALID CONFIGURATION, EXITING\n");
     return TR_CFG_ERROR;
   }
+
   return TR_CFG_SUCCESS;
 }
 
@@ -839,6 +915,7 @@ TR_RP_CLIENT *tr_cfg_find_rp (TR_CFG *tr_cfg, TR_NAME *rp_gss, TR_CFG_RC *rc)
   return NULL;
 }
 
+#if 0
 json_t *tr_read_config (int n, struct dirent **cfg_files) {
   json_t *jcfg = NULL;
   json_t *temp = NULL;
@@ -854,7 +931,6 @@ json_t *tr_read_config (int n, struct dirent **cfg_files) {
       return NULL;
     }
 
-    /* TBD -- instead of using json_object_update, iterate through files for non-overlap config? */
     if (!jcfg) {
       jcfg = temp;
     }else {
@@ -869,6 +945,7 @@ json_t *tr_read_config (int n, struct dirent **cfg_files) {
 
   return jcfg;
 }
+#endif 
 
 static int is_cfg_file(const struct dirent *dent) {
   int n;
index 3ce6cbe..7307bd1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, JANET(UK)
+ * Copyright (c) 2012-2014, JANET(UK)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *
  */
 #include <jansson.h>
+#include "jansson_iterators.h"
+#include <assert.h>
+#include <talloc.h>
 
 #include <tr_filter.h>
+#include <tr_debug.h>
+
 #include <trust_router/tr_constraint.h>
+#include <tid_internal.h>
+
+/* Returns TRUE (1) if the the string (str) matchs the wildcard string (wc_str), FALSE (0) if not.
+ */
+int tr_prefix_wildcard_match (const char *str, const char *wc_str) {
+  const char *wc_post = wc_str;
+  size_t len = 0;
+  size_t wc_len = 0;
+
+  if ((!str) || (!wc_str))
+    return 0;
+
+  len = strlen(str);
+  if (0 == (wc_len = strlen(wc_str)))
+    return 0;
+
+  /* TBD -- skip leading white space? */
+  if ('*' == wc_str[0]) {
+    wc_post = &(wc_str[1]);
+    wc_len--;
+  }else if (len != wc_len)
+    return 0;
+
+
+  if (wc_len > len)
+    return 0;
+  
+  if (0 == strcmp(&(str[len-wc_len]), wc_post)) {
+    return 1;
+  }
+  else
+    return 0;
+  }
 
 TR_CONSTRAINT_SET *tr_constraint_set_from_fline (TR_FLINE *fline)
 {
@@ -48,7 +86,7 @@ TR_CONSTRAINT_SET *tr_constraint_set_from_fline (TR_FLINE *fline)
   if (fline->domain_cons)
     tr_constraint_add_to_set((TR_CONSTRAINT_SET **)&cset, fline->domain_cons);
   
-   return cset;
+  return (TR_CONSTRAINT_SET *) cset;
 }
 
 /* A constraint set is represented in json as an array of constraint
@@ -70,7 +108,7 @@ void tr_constraint_add_to_set (TR_CONSTRAINT_SET **cset, TR_CONSTRAINT *cons)
 
   /* If we don't already have a json object, create one */
   if (!(*cset))
-    *cset = json_array();
+    *cset = (TR_CONSTRAINT_SET *) json_array();
 
   /* Create a json object representing cons */
   jmatches = json_array();
@@ -83,6 +121,202 @@ void tr_constraint_add_to_set (TR_CONSTRAINT_SET **cset, TR_CONSTRAINT *cons)
   json_object_set_new(jcons, cons->type->buf, jmatches);
   
   /* Add the created object to the cset object */
-  json_array_append_new(*cset, jcons);
+  json_array_append_new((json_t *) *cset, jcons);
 } 
 
+ int tr_constraint_set_validate(TR_CONSTRAINT_SET *cset)
+{
+  json_t *json = (json_t *) cset;
+  size_t i;
+  json_t *set_member;
+  if (!json_is_array(json)){
+    tr_debug("Constraint_set is not an array");
+    return 0;
+  }
+  json_array_foreach(json, i, set_member) {
+    json_t *value;
+    const char *key;
+    if (!json_is_object(set_member)) {
+      tr_debug("Constraint member at %zu is not an object\n", i);
+      return 0;
+    }
+    json_object_foreach( set_member, key, value) {
+      size_t inner_index;
+      json_t *inner_value;
+      if (!json_is_array(value)) {
+       tr_debug("Constraint type %s at index %zu in constraint set is not an array\n", key,
+                i);
+       return 0;
+      }
+      json_array_foreach(value, inner_index, inner_value) {
+       if (!json_is_string(inner_value)) {
+         tr_debug("Constraint type %s at index %zu in constraint set has non-string element %zu\n",
+                  key, i, inner_index);
+         return 0;
+       }
+      }
+       }
+  }
+  return 1;
+}
+
+
+TR_CONSTRAINT_SET *tr_constraint_set_filter( TID_REQ *request,
+                                            TR_CONSTRAINT_SET *orig,
+                                            const char *constraint_type)
+{
+  json_t *orig_cset = (json_t*) orig;
+  json_t  *new_cs = NULL;
+  size_t index;
+  json_t *set_member;
+  if (!tr_constraint_set_validate( (TR_CONSTRAINT_SET *) orig_cset)) {
+    tr_debug ("tr_constraint_set_filter: not a valid constraint set\n");
+    return NULL;
+  }
+  assert (new_cs = json_array());
+  json_array_foreach(orig_cset, index, set_member) {
+    if (json_object_get( set_member, constraint_type))
+      json_array_append(new_cs, set_member);
+  }
+  return (TR_CONSTRAINT_SET *) new_cs;
+}
+
+/**
+ * Within a given constraint object merge any overlapping domain or
+ * realm constraints.  For example ['*','*.net'] can be simplified to
+ * ['*']
+ */
+static void merge_constraints(json_t *constraint, const char *key)
+{
+  json_t *value_1, *value_2, *constraint_array;
+  size_t index_1, index_2;
+  /*
+   * Go through the loop pairwise linear, removing elements where one
+   * element is a subset of the other.  Always shrik the array from
+   * the end so that index_1 never becomes invalid (swapping if
+   * needed).
+   */
+  constraint_array = json_object_get(constraint, key);
+  if (NULL == constraint_array)
+      return;
+  json_array_foreach( constraint_array, index_1, value_1)
+    json_array_foreach( constraint_array, index_2, value_2) {
+    if (index_2 <= index_1)
+      continue;
+    if ( tr_prefix_wildcard_match( json_string_value(value_2),
+                                  json_string_value(value_1))) {
+      json_array_remove(constraint_array, index_2);
+      index_2--;
+    }else if (tr_prefix_wildcard_match( json_string_value(value_1),
+                                       json_string_value(value_2))) {
+      json_array_set(constraint_array, index_1, value_2);
+      json_array_remove(constraint_array, index_2);
+      index_2--;
+    }
+  }
+}
+
+/**
+ * Returns an array of constraint strings that is the intersection of
+ * all constraints in the constraint_set of type #type
+ */
+static json_t *constraint_intersect_internal( TR_CONSTRAINT_SET *constraints,
+                                             const char *constraint_type)
+{
+  json_t *constraint, *result = NULL;
+  size_t i;
+  json_array_foreach( (json_t *) constraints, i, constraint) {
+    merge_constraints( constraint, constraint_type);
+    if (NULL == result) {
+      result = json_object_get(constraint, constraint_type);
+      if (NULL != result)
+       result = json_copy(result);
+    }    else {
+      json_t *intersect, *value_1, *value_2;
+      size_t index_1, index_2;
+      intersect = json_object_get(constraint, constraint_type);
+      /*If an element of the constraint set doesn't have a particular
+       * constraint type, we ignore that element of the constraint set.
+       * However, if no element of the constraint set has a particular
+       *     constraint type we return empty (no access) rather than universal
+       * access.*/
+      if (!intersect)
+       continue;
+    result_loop:
+      json_array_foreach(result, index_1, value_1) {
+       json_array_foreach(intersect, index_2, value_2) {
+         if (tr_prefix_wildcard_match( json_string_value(value_1),
+                                       json_string_value(value_2)))
+           goto result_acceptable;
+         else if (tr_prefix_wildcard_match(json_string_value( value_2),
+                                           json_string_value(value_1))) {
+           json_array_set(result, index_1, value_2);
+           goto result_acceptable;
+       }
+       }
+       json_array_remove(result, index_1);
+       if (index_1 == 0)
+         goto result_loop;
+       index_1--;
+      result_acceptable: continue;
+      }
+    }
+  }
+  return result;
+}
+
+/**
+ * Return the intersection of domain and realm constraints.
+ * Return is live until #request is freed.
+ */
+TR_CONSTRAINT_SET *tr_constraint_set_intersect( TID_REQ *request,
+                                               TR_CONSTRAINT_SET *input)
+{
+  json_t *domain=NULL, *realm=NULL;
+  json_t *result = NULL, *result_array = NULL;
+  if (tr_constraint_set_validate(input)) {
+    domain = constraint_intersect_internal(input, "domain");
+    realm = constraint_intersect_internal(input, "realm");
+  }
+  assert(result = json_object());
+  if (domain)
+    json_object_set_new(result, "domain", domain);
+  if (realm)
+    json_object_set_new(result, "realm", realm);
+  assert(result_array = json_array());
+  json_array_append_new(result_array, result);
+  tid_req_cleanup_json( request, result_array);
+  return (TR_CONSTRAINT_SET *) result_array;
+}
+
+
+int tr_constraint_set_get_match_strings(
+                                       TID_REQ *request,
+                                       TR_CONSTRAINT_SET *constraints,
+                                       const char *constraint_type,
+                                       tr_const_string **output,
+                                       size_t *output_len)
+{
+  json_t *cset = (json_t *) constraints;
+  json_t *member, *matches, *value;;
+  size_t index, array_size;
+  assert (output && output_len);
+  *output = NULL;
+  *output_len = 0;
+  if (json_array_size(cset) != 1) {
+    tr_debug("Constraint set for get_match_strings has more than one member\n");
+    return -1;
+  }
+  member = json_array_get(cset, 0);
+  matches = json_object_get(member, constraint_type);
+  if (!matches)
+    return -1;
+  array_size = json_array_size(matches);
+  if (array_size == 0)
+    return -1;
+  *output = talloc_array_ptrtype(request, *output, array_size);
+  json_array_foreach( matches, index, value)
+    (*output)[index] = json_string_value(value);
+  *output_len = array_size;
+  return 0;
+}
index 3c0d78b..41bac2a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, JANET(UK)
+ * Copyright (c) 2012, 2014, JANET(UK)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include <openssl/dh.h>
 #include <trust_router/tr_dh.h>
+#include <openssl/bn.h>
+#include <openssl/sha.h>
+#include <talloc.h>
+#include <assert.h>
+#include <tid_internal.h>
+
 
 unsigned char tr_2048_dhprime[2048/8] = {
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -197,3 +203,22 @@ int tr_compute_dh_key(unsigned char **pbuf,
 
 
 
+int tr_dh_pub_hash(TID_REQ *request,
+                  unsigned char **out_digest,
+                  size_t *out_len)
+{
+  const BIGNUM *pub = request->tidc_dh->pub_key;
+  unsigned char *bn_bytes = talloc_zero_size(request, BN_num_bytes(pub));
+  unsigned char *digest = talloc_zero_size(request, SHA_DIGEST_LENGTH+1);
+  assert(bn_bytes && digest);
+                                   BN_bn2bin(pub, bn_bytes);
+                                   SHA1(bn_bytes, BN_num_bytes(pub), digest);
+                                   *out_digest = digest;
+                                   *out_len = SHA_DIGEST_LENGTH;
+                                   return 0;
+}
+
+void tr_dh_free(unsigned char *dh_buf)
+{
+  free(dh_buf);
+}
index 4f782dc..d4c9acd 100644 (file)
 #include <string.h>
 #include <tr_filter.h>
 
-/* Returns TRUE (1) if the the string (str) matchs the wildcard string (wc_str), FALSE (0) if not.
- */
-int tr_prefix_wildcard_match (char *str, char *wc_str) {
-  char *wc_post = wc_str;
-  size_t len = 0;
-  size_t wc_len = 0;
-
-  if ((!str) || (!wc_str))
-    return 0;
-
-  len = strlen(str);
-  if (0 == (wc_len = strlen(wc_str)))
-    return 0;
-
-  /* TBD -- skip leading white space? */
-  if ('*' == wc_str[0]) {
-    wc_post = &(wc_str[1]);
-    wc_len--;
-  }
-
-  if (wc_len > len)
-    return 0;
-  
-  if (0 == strcmp(&(str[len-wc_len]), wc_post)) {
-    return 1;
-  }
-  else
-    return 0;
-  }
 
 int tr_filter_process_rp_permitted (TR_NAME *rp_realm, TR_FILTER *rpp_filter, TR_CONSTRAINT_SET *in_constraints, TR_CONSTRAINT_SET **out_constraints, int *out_action) 
 {
index 8eca04d..eb0c6fd 100644 (file)
@@ -52,3 +52,11 @@ TR_AAA_SERVER *tr_idp_aaa_server_lookup(TR_INSTANCE *tr, TR_NAME *idp_realm, TR_
   else 
     return NULL;
 }
+
+TR_AAA_SERVER *tr_default_server_lookup(TR_INSTANCE *tr, TR_NAME *comm)
+{
+  if ((!tr) || (!(tr->active_cfg)))
+    return NULL;
+
+  return(tr->active_cfg->default_servers);
+}
index 6367476..85221f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, JANET(UK)
+ * Copyright (c) 2012-2014 , JANET(UK)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <string.h>
 #include <openssl/dh.h>
 #include <jansson.h>
+#include <assert.h>
+#include <talloc.h>
+
 
 #include <tr_msg.h>
 #include <trust_router/tr_name.h>
-#include <trust_router/tid.h>
+#include <tid_internal.h>
+#include <trust_router/tr_constraint.h>
+#include <tr_debug.h>
 
 enum msg_type tr_msg_get_msg_type(TR_MSG *msg) 
 {
@@ -54,22 +59,28 @@ void tr_msg_set_msg_type(TR_MSG *msg, enum msg_type type)
 
 TID_REQ *tr_msg_get_req(TR_MSG *msg)
 {
-  return msg->tid_req;
+  if (msg->msg_type == TID_REQUEST)
+    return (TID_REQ *)msg->msg_rep;
+  return NULL;
 }
 
 void tr_msg_set_req(TR_MSG *msg, TID_REQ *req)
 {
-  msg->tid_req = req;
+  msg->msg_rep = req;
+  msg->msg_type = TID_REQUEST;
 }
 
 TID_RESP *tr_msg_get_resp(TR_MSG *msg)
 {
-  return msg->tid_resp;
+  if (msg->msg_type == TID_RESPONSE)
+    return (TID_RESP *)msg->msg_rep;
+  return NULL;
 }
 
 void tr_msg_set_resp(TR_MSG *msg, TID_RESP *resp)
 {
-  msg->tid_resp = resp;
+  msg->msg_rep = resp;
+  msg->msg_type = TID_RESPONSE;
 }
 
 static json_t *tr_msg_encode_dh(DH *dh)
@@ -132,7 +143,7 @@ static json_t * tr_msg_encode_tidreq(TID_REQ *req)
   if ((!req) || (!req->rp_realm) || (!req->realm) || !(req->comm))
     return NULL;
 
-  jreq = json_object();
+  assert(jreq = json_object());
 
   jstr = json_string(req->rp_realm->buf);
   json_object_set_new(jreq, "rp_realm", jstr);
@@ -149,7 +160,10 @@ static json_t * tr_msg_encode_tidreq(TID_REQ *req)
   }
 
   json_object_set_new(jreq, "dh_info", tr_msg_encode_dh(req->tidc_dh));
-  
+
+  if (req->cons)
+    json_object_set(jreq, "constraints", (json_t *) req->cons);
+
   return jreq;
 }
 
@@ -162,19 +176,17 @@ static TID_REQ *tr_msg_decode_tidreq(json_t *jreq)
   json_t *jorig_coi = NULL;
   json_t *jdh = NULL;
 
-  if (!(treq = malloc(sizeof(TID_REQ)))) {
+  if (!(treq =tid_req_new())) {
     fprintf (stderr, "tr_msg_decode_tidreq(): Error allocating TID_REQ structure.\n");
     return NULL;
   }
  
-  memset(treq, 0, sizeof(TID_REQ));
-
   /* store required fields from request */
   if ((NULL == (jrp_realm = json_object_get(jreq, "rp_realm"))) ||
       (NULL == (jrealm = json_object_get(jreq, "target_realm"))) ||
       (NULL == (jcomm = json_object_get(jreq, "community")))) {
     fprintf (stderr, "tr_msg_decode(): Error parsing required fields.\n");
-    free(treq);
+    tid_req_free(treq);
     return NULL;
   }
 
@@ -185,7 +197,7 @@ static TID_REQ *tr_msg_decode_tidreq(json_t *jreq)
   /* Get DH Info from the request */
   if (NULL == (jdh = json_object_get(jreq, "dh_info"))) {
     fprintf (stderr, "tr_msg_decode(): Error parsing dh_info.\n");
-    free(treq);
+    tid_req_free(treq);
     return NULL;
   }
   treq->tidc_dh = tr_msg_decode_dh(jdh);
@@ -195,6 +207,16 @@ static TID_REQ *tr_msg_decode_tidreq(json_t *jreq)
     treq->orig_coi = tr_new_name((char *)json_string_value(jorig_coi));
   }
 
+  treq->cons = (TR_CONSTRAINT_SET *) json_object_get(jreq, "constraints");
+  if (treq->cons) {
+    if (!tr_constraint_set_validate(treq->cons)) {
+      tr_debug("Constraint set validation failed\n");
+    tid_req_free(treq);
+    return NULL;
+    }
+    json_incref((json_t *) treq->cons);
+    tid_req_cleanup_json(treq, (json_t *) treq->cons);
+  }
   return treq;
 }
 
@@ -221,45 +243,40 @@ static json_t *tr_msg_encode_one_server(TID_SRVR_BLK *srvr)
   return jsrvr;
 }
 
-static TID_SRVR_BLK *tr_msg_decode_one_server(json_t *jsrvr) 
+static int tr_msg_decode_one_server(json_t *jsrvr, TID_SRVR_BLK *srvr) 
 {
-  TID_SRVR_BLK *srvr;
   json_t *jsrvr_addr = NULL;
   json_t *jsrvr_kn = NULL;
   json_t *jsrvr_dh = NULL;
 
   if (jsrvr == NULL)
-    return NULL;
+    return -1;
 
-  if (NULL == (srvr = malloc(sizeof(TID_SRVR_BLK)))) 
-    return NULL;
-  memset(srvr, 0, sizeof(TID_SRVR_BLK));
 
   if ((NULL == (jsrvr_addr = json_object_get(jsrvr, "server_addr"))) ||
       (NULL == (jsrvr_kn = json_object_get(jsrvr, "key_name"))) ||
       (NULL == (jsrvr_dh = json_object_get(jsrvr, "server_dh")))) {
-    fprintf (stderr, "tr_msg_decode_one_server(): Error parsing required fields.\n");
-    free(srvr);
-    return NULL;
+    tr_debug("tr_msg_decode_one_server(): Error parsing required fields.\n");
+    return -1;
   }
   
   /* TBD -- handle IPv6 Addresses */
   inet_aton(json_string_value(jsrvr_addr), &(srvr->aaa_server_addr));
   srvr->key_name = tr_new_name((char *)json_string_value(jsrvr_kn));
   srvr->aaa_server_dh = tr_msg_decode_dh(jsrvr_dh);
-
-  return srvr;
+  return 0;
 }
 
-static json_t *tr_msg_encode_servers(TID_SRVR_BLK *servers)
+static json_t *tr_msg_encode_servers(TID_RESP *resp)
 {
   json_t *jservers = NULL;
   json_t *jsrvr = NULL;
   TID_SRVR_BLK *srvr = NULL;
+  size_t index;
 
   jservers = json_array();
 
-  for (srvr = servers; srvr != NULL; srvr = srvr->next) {
+  tid_resp_servers_foreach(resp, srvr, index) {
     if ((NULL == (jsrvr = tr_msg_encode_one_server(srvr))) ||
        (-1 == json_array_append_new(jservers, jsrvr))) {
       return NULL;
@@ -271,11 +288,9 @@ static json_t *tr_msg_encode_servers(TID_SRVR_BLK *servers)
   return jservers;
 }
 
-static TID_SRVR_BLK *tr_msg_decode_servers(json_t *jservers) 
+static TID_SRVR_BLK *tr_msg_decode_servers(void * ctx, json_t *jservers, size_t *out_len)
 {
   TID_SRVR_BLK *servers = NULL;
-  TID_SRVR_BLK *next = NULL;
-  TID_SRVR_BLK *srvr = NULL;
   json_t *jsrvr;
   size_t i, num_servers;
 
@@ -286,21 +301,18 @@ static TID_SRVR_BLK *tr_msg_decode_servers(json_t *jservers)
     fprintf(stderr, "tr_msg_decode_servers(): Server array is empty.\n"); 
     return NULL;
   }
+    servers = talloc_zero_array(ctx, TID_SRVR_BLK, num_servers);
 
   for (i = 0; i < num_servers; i++) {
     jsrvr = json_array_get(jservers, i);
-    srvr = tr_msg_decode_one_server(jsrvr);
-
-    /* skip to the end of the list, and add srvr to list of servers */
-    if (NULL == servers) {
-      servers = srvr;
-    }
-    else {
-      for (next = servers; next->next != NULL; next = next->next);
-      next->next = srvr;
+    if (0 != tr_msg_decode_one_server(jsrvr, &servers[i])) {
+      talloc_free(servers);
+      return NULL;
     }
-  }
 
+
+  }
+  *out_len = num_servers;
   return servers;
 }
 
@@ -346,7 +358,7 @@ static json_t * tr_msg_encode_tidresp(TID_RESP *resp)
     fprintf(stderr, "tr_msg_encode_tidresp(): No servers to encode.\n");
     return jresp;
   }
-  jservers = tr_msg_encode_servers(resp->servers);
+  jservers = tr_msg_encode_servers(resp);
   json_object_set_new(jresp, "servers", jservers);
   
   return jresp;
@@ -363,12 +375,11 @@ static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
   json_t *jservers = NULL;
   json_t *jerr_msg = NULL;
 
-  if (!(tresp = malloc(sizeof(TID_RESP)))) {
+  if (!(tresp = talloc_zero(NULL, TID_RESP))) {
     fprintf (stderr, "tr_msg_decode_tidresp(): Error allocating TID_RESP structure.\n");
     return NULL;
   }
  
-  memset(tresp, 0, sizeof(TID_RESP));
 
   /* store required fields from response */
   if ((NULL == (jresult = json_object_get(jresp, "result"))) ||
@@ -380,7 +391,7 @@ static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
       (NULL == (jcomm = json_object_get(jresp, "comm"))) ||
       (!json_is_string(jcomm))) {
     fprintf (stderr, "tr_msg_decode_tidresp(): Error parsing response.\n");
-    free(tresp);
+    talloc_free(tresp);
     return NULL;
   }
 
@@ -388,9 +399,10 @@ static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
     fprintf(stderr, "tr_msg_decode_tidresp(): Success! result = %s.\n", json_string_value(jresult));
     if ((NULL != (jservers = json_object_get(jresp, "servers"))) ||
        (!json_is_array(jservers))) {
-      tresp->servers = tr_msg_decode_servers(jservers); 
+      tresp->servers = tr_msg_decode_servers(tresp, jservers, &tresp->num_servers); 
     } 
     else {
+      talloc_free(tresp);
       return NULL;
     }
     tresp->result = TID_SUCCESS;
@@ -430,13 +442,13 @@ char *tr_msg_encode(TR_MSG *msg)
     case TID_REQUEST:
       jmsg_type = json_string("tid_request");
       json_object_set_new(jmsg, "msg_type", jmsg_type);
-      json_object_set_new(jmsg, "msg_body", tr_msg_encode_tidreq(msg->tid_req));
+      json_object_set_new(jmsg, "msg_body", tr_msg_encode_tidreq(tr_msg_get_req(msg)));
       break;
 
     case TID_RESPONSE:
       jmsg_type = json_string("tid_response");
       json_object_set_new(jmsg, "msg_type", jmsg_type);
-      json_object_set_new(jmsg, "msg_body", tr_msg_encode_tidresp(msg->tid_resp));
+      json_object_set_new(jmsg, "msg_body", tr_msg_encode_tidresp(tr_msg_get_resp(msg)));
       break;
 
       /* TBD -- Add TR message types */
@@ -483,15 +495,15 @@ TR_MSG *tr_msg_decode(char *jbuf, size_t buflen)
 
   if (0 == strcmp(mtype, "tid_request")) {
     msg->msg_type = TID_REQUEST;
-    msg->tid_req = tr_msg_decode_tidreq(jbody);
+    tr_msg_set_req(msg, tr_msg_decode_tidreq(jbody));
   }
   else if (0 == strcmp(mtype, "tid_response")) {
     msg->msg_type = TID_RESPONSE;
-    msg->tid_resp = tr_msg_decode_tidresp(jbody);
+    tr_msg_set_resp(msg, tr_msg_decode_tidresp(jbody));
   }
   else {
     msg->msg_type = TR_UNKNOWN;
-    msg->tid_req = NULL;
+    msg->msg_rep = NULL;
   }
   return msg;
 }
index e34a1c3..ca5c86b 100644 (file)
@@ -1,23 +1,32 @@
 AC_PREREQ(2.63)
-AC_INIT([trust_router],[1.2],
+AC_INIT([trust_router],[1.3.1],
 [bugs@project-moonshot.org])
 AC_CONFIG_MACRO_DIR(m4)
 AC_CONFIG_AUX_DIR(build-aux)
 AC_USE_SYSTEM_EXTENSIONS
-AM_INIT_AUTOMAKE([1.11 foreign])
+AM_INIT_AUTOMAKE([1.11 foreign subdir-objects])
 AM_SILENT_RULES
 AM_MAINTAINER_MODE
 LT_INIT()
 
 AC_PROG_CC
-AC_PROG_RANLIB
+           PKG_PROG_PKG_CONFIG
+           AC_ARG_WITH([systemdsystemunitdir],
+                   AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+                   [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+           if test "x$with_systemdsystemunitdir" != xno; then
+                   AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+           fi
+           AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
 
 AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context])
-AC_CHECK_LIB([com_err], [error_message])AC_CHECK_LIB([sqlite3], [sqlite3_open],,
+AC_CHECK_LIB([com_err], [error_message])
+AC_CHECK_LIB(talloc, talloc_init,,
+[AC_MSG_ERROR([Please install talloc development])])
+AC_CHECK_LIB([sqlite3], [sqlite3_open],,
     [AC_MSG_ERROR([Please install sqlite3 development])])
-
 AC_CHECK_LIB([jansson], [json_object])
 AC_CHECK_LIB([crypto], [DH_new])
-AC_CHECK_HEADERS(gssapi.h gssapi_ext.h jansson.h openssl/dh.h openssl/bn.h)
+AC_CHECK_HEADERS(gssapi.h gssapi_ext.h jansson.h talloc.h openssl/dh.h openssl/bn.h)
 AC_CONFIG_FILES([Makefile gsscon/Makefile])
 AC_OUTPUT
diff --git a/gsscon/.#gsscon_test.c b/gsscon/.#gsscon_test.c
deleted file mode 120000 (symlink)
index f036edb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-mrw@lilac-moonshot.suchdamage.org.13738:1346036289
\ No newline at end of file
index 9052d84..9cf0695 100755 (executable)
@@ -189,43 +189,7 @@ if (clientDisplayName.value != NULL)
     return err;
 }
 
-/* --------------------------------------------------------------------------- */
-
-static int ServicePrincipalIsValidForService (const char *inServicePrincipal)
-{
-    int err = 0;
-    krb5_context context = NULL;
-    krb5_principal principal = NULL;
-    
-    if (!inServicePrincipal) { err = EINVAL; }
-    
-    if (!err) {
-        err = krb5_init_context (&context);
-    }
-    
-    if (!err) {
-        err = krb5_parse_name (context, inServicePrincipal, &principal);
-    }
     
-    if (!err) {
-        /* 
-         * Here is where we check to see if the service principal the client 
-         * used is valid.  Typically we would just check that the first component 
-         * is the name of the service provided by the server.  This check exists
-         * to make sure the server is using the correct key in its keytab since
-         * we passed GSS_C_NO_CREDENTIAL into gss_accept_sec_context().
-         */
-        if (gServiceName && strcmp (gServiceName, 
-                                    krb5_princ_name (context, principal)->data) != 0) {
-            err = KRB5KRB_AP_WRONG_PRINC;
-        }
-    }
-    
-    if (principal) { krb5_free_principal (context, principal); }
-    if (context  ) { krb5_free_context (context); }
-    
-    return err;
-}
 
 
 /* --------------------------------------------------------------------------- */
@@ -326,15 +290,11 @@ int gsscon_authorize (gss_ctx_id_t  inContext,
     //    if (nameToken.value) { gss_release_buffer (&minorStatus, &nameToken); }
     // }
     
-//    if (!err) {
-//        int authorizationErr = ServicePrincipalIsValidForService (servicePr// incipal);
-//        
-//        if (!authorizationErr) {
 
          int authorizationErr = 0;
          authorizationErr = ClientPrincipalIsAuthorizedForService (clientPrincipal);
 
-//        }
+
         
 //        printf ("'%s' is%s authorized for service '%s'\n", 
 //                clientPrincipal, authorizationErr ? " NOT" : "", servicePrincipal);            
diff --git a/include/tid_internal.h b/include/tid_internal.h
new file mode 100644 (file)
index 0000000..0593425
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012-2014, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * Copyright (c) 2012, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TID_INTERNAL_H
+#define TID_INTERNAL_H
+#include <trust_router/tid.h>
+
+#include <jansson.h>
+struct tid_srvr_blk {
+  struct in_addr aaa_server_addr;
+  TR_NAME *key_name;
+  DH *aaa_server_dh;           /* AAA server's public dh information */
+};
+
+struct tid_resp {
+  TID_RC result;
+  TR_NAME *err_msg;
+  TR_NAME *rp_realm;
+  TR_NAME *realm;
+  TR_NAME *comm;
+  TR_CONSTRAINT_SET *cons;
+  TR_NAME *orig_coi;
+  TID_SRVR_BLK *servers;               /* array of servers */
+  size_t num_servers;
+  /* TBD -- Trust Path Used */
+};
+struct tid_req {
+  struct tid_req *next_req;
+  int resp_sent;
+  int conn;
+  gss_ctx_id_t gssctx;
+  int resp_rcvd;
+  TR_NAME *rp_realm;
+  TR_NAME *realm;
+  TR_NAME *comm;
+  TR_CONSTRAINT_SET *cons;
+  TR_NAME *orig_coi;
+  DH *tidc_dh;                 /* Client's public dh information */
+  TIDC_RESP_FUNC *resp_func;
+  void *cookie;
+  json_t *json_references; /** References to objects dereferenced on request destruction*/
+};
+struct tidc_instance {
+  TID_REQ *req_list;
+  // TBD -- Do we still need a separate private key */
+  // char *priv_key;
+  // int priv_len;
+  DH *client_dh;                       /* Client's DH struct with priv and pub keys */
+};
+struct tids_instance {
+  int req_count;
+  char *priv_key;
+  char *ipaddr;
+  const char *hostname;
+  TIDS_REQ_FUNC *req_handler;
+  tids_auth_func *auth_handler;
+  void *cookie;
+};
+
+
+/** Decrement a reference to #json when this tid_req is cleaned up. A
+    new reference is not created; in effect the caller is handing a
+    reference they already hold to the TID_REQ.*/
+void tid_req_cleanup_json(TID_REQ *, json_t *json);
+
+#endif
index dd2b1bf..61adc36 100644 (file)
@@ -35,7 +35,7 @@
 #ifndef TR_H
 #define TR_H
 
-#include <trust_router/tid.h>
+#include <tid_internal.h>
 #include <trust_router/tr_name.h>
 #include <tr_msg.h>
 #include <tr_rp.h>
index 1d5256b..91f877f 100644 (file)
@@ -63,19 +63,20 @@ typedef struct tr_cfg_internal {
 } TR_CFG_INTERNAL;
 
 typedef struct tr_cfg {
-  TR_CFG_INTERNAL *internal;   /* internal trust router config */
-  TR_IDP_REALM *idp_realms;    /* locally associated IDP Realms */
-  TR_RP_CLIENT *rp_clients;    /* locally associated RP Clients */
-  TR_COMM *comms;              /* locally-known communities */
+  TR_CFG_INTERNAL *internal;           /* internal trust router config */
+  TR_IDP_REALM *idp_realms;            /* locally associated IDP Realms */
+  TR_RP_CLIENT *rp_clients;            /* locally associated RP Clients */
+  TR_COMM *comms;                      /* locally-known communities */
+  TR_AAA_SERVER *default_servers;      /* default server list */
   /* TBD -- Global Filters */
   /* TBD -- Trust Router Peers */
   /* TBD -- Trust Links */
 } TR_CFG;
 
 int tr_find_config_files (struct dirent ***cfg_files);
-json_t *tr_read_config (int n, struct dirent **cfgfiles);
-TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, json_t *jcfg);
+TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, struct dirent **cfg_files);
 TR_CFG_RC tr_apply_new_config (TR_INSTANCE *tr);
+TR_CFG_RC tr_cfg_validate (TR_CFG *trc);
 void tr_cfg_free(TR_CFG *cfg);
 void tr_print_config(FILE *stream, TR_CFG *cfg);
 
diff --git a/include/tr_debug.h b/include/tr_debug.h
new file mode 100644 (file)
index 0000000..ac2c4b7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _TR_DEBUG_H
+#define _TR_DEBUG_H
+
+#define tr_debug(...) fprintf( stderr, __VA_ARGS__)
+
+#endif
index 8efdbc4..718dca0 100644 (file)
@@ -73,7 +73,8 @@ typedef struct tr_filter {
 } TR_FILTER;
 
 void tr_filter_free (TR_FILTER *filt);
-int tr_prefix_wildcard_match (char *str, char *wc_str);
+/*In tr_constraint.c and exported, but not really a public symbol; needed by tr_filter.c and by tr_constraint.c*/
+int TR_EXPORT tr_prefix_wildcard_match (const char *str, const char *wc_str);
 int tr_filter_process_rp_permitted (TR_NAME *rp_realm, TR_FILTER *rpp_filter, TR_CONSTRAINT_SET *in_constraints, TR_CONSTRAINT_SET **out_constraints, int *out_action);
 TR_CONSTRAINT_SET *tr_constraint_set_from_fline (TR_FLINE *fline);
 #endif
index d95de3c..0eba315 100644 (file)
@@ -46,7 +46,7 @@ typedef struct tr_aaa_server {
 
 typedef struct tr_idp_realm {
   struct tr_idp_realm *next;
-  struct tr_idp_realm *comm_next; /* for link list in comm config */
+  struct tr_idp_realm *comm_next; /* for linked list in comm config */
   TR_NAME *realm_id;
   int shared_config;
   TR_AAA_SERVER *aaa_servers;
@@ -54,5 +54,5 @@ typedef struct tr_idp_realm {
 } TR_IDP_REALM;
   
 TR_AAA_SERVER *tr_idp_aaa_server_lookup(TR_INSTANCE *tr, TR_NAME *idp_realm, TR_NAME *comm);
-
+TR_AAA_SERVER *tr_default_server_lookup(TR_INSTANCE *tr, TR_NAME *comm);
 #endif
index f5d7c60..4f208e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, JANET(UK)
+ * Copyright (c) 2012-2014, JANET(UK)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,10 +49,7 @@ enum msg_type {
 /* Union of TR message types to hold message of any type. */
 struct tr_msg {
   enum msg_type msg_type;
-  union {
-    TID_REQ *tid_req;
-    TID_RESP *tid_resp;
-  };
+  void *msg_rep;
 };
 
 /* Accessors */
index 74281ca..391faca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, JANET(UK)
+ * Copyright (c) 2012-2014, JANET(UK)
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include <trust_router/tr_name.h>
 #include <trust_router/tr_versioning.h>
-#include <trust_router/tr_constraint.h>
 
 #include <gssapi.h>
 
+
 #define TID_PORT       12309
 
 typedef enum tid_rc {
@@ -51,70 +51,29 @@ typedef enum tid_rc {
   TID_ERROR
 } TID_RC;
 
-typedef struct tid_srvr_blk {
-  struct tid_srvr_blk *next;
-  struct in_addr aaa_server_addr;
-  TR_NAME *key_name;
-  DH *aaa_server_dh;           /* AAA server's public dh information */
-} TID_SRVR_BLK;
-  
-typedef struct tid_resp {
-  TID_RC result;
-  TR_NAME *err_msg;
-  TR_NAME *rp_realm;
-  TR_NAME *realm;
-  TR_NAME *comm;
-  TR_CONSTRAINT_SET *cons;
-  TR_NAME *orig_coi;
-  TID_SRVR_BLK *servers;               /* Linked list of servers */
-  /* TBD -- Trust Path Used */
-} TID_RESP;
+typedef struct tid_srvr_blk  TID_SRVR_BLK;
+
+
+typedef struct _tr_constraint_set  TR_CONSTRAINT_SET;
+
+typedef struct tid_resp TID_RESP;
 
 typedef struct tidc_instance TIDC_INSTANCE;
 typedef struct tids_instance TIDS_INSTANCE;
 typedef struct tid_req TID_REQ;
 
+
 typedef void (TIDC_RESP_FUNC)(TIDC_INSTANCE *, TID_REQ *, TID_RESP *, void *);
 
-struct tid_req {
-  struct tid_req *next_req;
-  int resp_sent;
-  int conn;
-  gss_ctx_id_t gssctx;
-  int resp_rcvd;
-  TR_NAME *rp_realm;
-  TR_NAME *realm;
-  TR_NAME *comm;
-  TR_CONSTRAINT_SET *cons;
-  TR_NAME *orig_coi;
-  DH *tidc_dh;                 /* Client's public dh information */
-  TIDC_RESP_FUNC *resp_func;
-  void *cookie;
-};
-
-struct tidc_instance {
-  TID_REQ *req_list;
-  // TBD -- Do we still need a separate private key */
-  // char *priv_key;
-  // int priv_len;
-  DH *client_dh;                       /* Client's DH struct with priv and pub keys */
-};
-
-typedef int (TIDS_REQ_FUNC)(TIDS_INSTANCE *, TID_REQ *, TID_RESP **, void *);
+
+
+typedef int (TIDS_REQ_FUNC)(TIDS_INSTANCE *, TID_REQ *, TID_RESP *, void *);
 typedef int (tids_auth_func)(gss_name_t client_name, TR_NAME *display_name, void *cookie);
 
 
-struct tids_instance {
-  int req_count;
-  char *priv_key;
-  char *ipaddr;
-  const char *hostname;
-  TIDS_REQ_FUNC *req_handler;
-  tids_auth_func *auth_handler;
-  void *cookie;
-};
 
-/* Utility funciton for TID_REQ structures, in tid/tid_req.c */
+/* Utility functions for TID_REQ structures, in tid/tid_req.c */
+TR_EXPORT TID_REQ *tid_req_new(void);
 TR_EXPORT TID_REQ *tid_req_get_next_req(TID_REQ *req);
 void tid_req_set_next_req(TID_REQ *req, TID_REQ *next_req);
 TR_EXPORT int tid_req_get_resp_sent(TID_REQ *req);
@@ -138,10 +97,11 @@ void tid_req_set_resp_func(TID_REQ *req, TIDC_RESP_FUNC *resp_func);
 TR_EXPORT void *tid_req_get_cookie(TID_REQ *req);
 void tid_req_set_cookie(TID_REQ *req, void *cookie);
 TR_EXPORT TID_REQ *tid_dup_req (TID_REQ *orig_req);
+void TR_EXPORT tid_req_free( TID_REQ *req);
 
 /* Utility functions for TID_RESP structure, in tid/tid_resp.c */
-TR_EXPORT TID_RC tid_resp_get_result(TID_RESP *resp);
-void tid_resp_set_result(TID_RESP *resp, TID_RC result);
+TR_EXPORT int tid_resp_get_result(TID_RESP *resp);
+void tid_resp_set_result(TID_RESP *resp, int result);
 TR_EXPORT TR_NAME *tid_resp_get_err_msg(TID_RESP *resp);
 void tid_resp_set_err_msg(TID_RESP *resp, TR_NAME *err_msg);
 TR_EXPORT TR_NAME *tid_resp_get_rp_realm(TID_RESP *resp);
@@ -152,15 +112,27 @@ TR_EXPORT TR_NAME *tid_resp_get_comm(TID_RESP *resp);
 void tid_resp_set_comm(TID_RESP *resp, TR_NAME *comm);
 TR_EXPORT TR_NAME *tid_resp_get_orig_coi(TID_RESP *resp);
 void tid_resp_set_orig_coi(TID_RESP *resp, TR_NAME *orig_coi);
-TR_EXPORT TID_SRVR_BLK *tid_resp_get_servers(TID_RESP *resp);
-void tid_resp_set_servers(TID_RESP *resp, TID_SRVR_BLK *servers);
-// TBD -- add function to add/remove items from linked list of servers?
+TR_EXPORT TID_SRVR_BLK *tid_resp_get_server(TID_RESP *resp, size_t index);
+TR_EXPORT size_t tid_resp_get_num_servers(const TID_RESP *resp);
+/* Server blocks*/
+TR_EXPORT void tid_srvr_get_address(const TID_SRVR_BLK *,
+                                   const struct sockaddr **out_addr, size_t *out_sa_len);
+TR_EXPORT DH *tid_srvr_get_dh(TID_SRVR_BLK *);
+TR_EXPORT const TR_NAME *tid_srvr_get_key_name(const TID_SRVR_BLK *);
+
+#define tid_resp_servers_foreach(RESP, SERVER, INDEX) \
+  for (INDEX=0,SERVER=NULL;                                            \
+       ((INDEX < tid_resp_get_num_servers(RESP))&&(SERVER = tid_resp_get_server(resp, INDEX))); \
+       INDEX++)
+
 
 /* TID Client functions, in tid/tidc.c */
 TR_EXPORT TIDC_INSTANCE *tidc_create (void);
 TR_EXPORT int tidc_open_connection (TIDC_INSTANCE *tidc, char *server, unsigned int port, gss_ctx_id_t *gssctx);
 TR_EXPORT int tidc_send_request (TIDC_INSTANCE *tidc, int conn, gss_ctx_id_t gssctx, char *rp_realm, char *realm, char *coi, TIDC_RESP_FUNC *resp_handler, void *cookie);
 TR_EXPORT int tidc_fwd_request (TIDC_INSTANCE *tidc, TID_REQ *req, TIDC_RESP_FUNC *resp_handler, void *cookie);
+TR_EXPORT DH *tidc_get_dh(TIDC_INSTANCE *);
+TR_EXPORT DH *tidc_set_dh(TIDC_INSTANCE *, DH *);
 TR_EXPORT void tidc_destroy (TIDC_INSTANCE *tidc);
 
 /* TID Server functions, in tid/tids.c */
index fc20ae0..28f6bd4 100644 (file)
 
 #ifndef TR_CONSTRAINT_H
 #define TR_CONSTRAINT_H
-
 #include <trust_router/tr_name.h>
+#include <trust_router/tid.h>
+
 
 #define TR_MAX_CONST_MATCHES 24
 
-typedef void TR_CONSTRAINT_SET;
 
 typedef struct tr_constraint {
   TR_NAME *type;
   TR_NAME *matches[TR_MAX_CONST_MATCHES];
 } TR_CONSTRAINT;
 
-void tr_constraint_add_to_set (TR_CONSTRAINT_SET **cs, TR_CONSTRAINT *c);
+void TR_EXPORT tr_constraint_add_to_set (TR_CONSTRAINT_SET **cs, TR_CONSTRAINT *c);
+
+int TR_EXPORT tr_constraint_set_validate( TR_CONSTRAINT_SET *);
+/**
+ * Create a new constraint set containing all constraints from #orig
+ * with constraint_type #constraint_type and no others.  This constraint set is
+ * live until #request is freed.
+ */
+TR_EXPORT TR_CONSTRAINT_SET *tr_constraint_set_filter(TID_REQ *request,
+                                  TR_CONSTRAINT_SET *orig,
+                                  const char * constraint_type);
+
+TR_EXPORT TR_CONSTRAINT_SET
+*tr_constraint_set_intersect(TID_REQ *request,
+                            TR_CONSTRAINT_SET *input);
+
+/** Get the set of wildcard strings that matches a fully intersected
+ * constraint set.  Requires that the constraint set only have one
+ * constraint in it, but the constraint may have multiple matches for
+ * a given type.  Returns true on success false on failure.  The
+ * output is live as long as the request is live.
+ */
+int TR_EXPORT tr_constraint_set_get_match_strings(TID_REQ *,
+                                           TR_CONSTRAINT_SET *,
+                                                 const char * constraint_type,
+                                                 tr_const_string **output,
+                                           size_t *output_len);
 
 #endif
index 8965867..7760155 100644 (file)
 #include <openssl/dh.h>
 #include <openssl/bn.h>
 #include <trust_router/tr_versioning.h>
+#include <trust_router/tid.h>
+
 
 TR_EXPORT DH *tr_create_dh_params(unsigned char *key, size_t len);
 TR_EXPORT DH *tr_create_matching_dh(unsigned char *key, size_t len, DH *in_dh);
 TR_EXPORT void tr_destroy_dh_params(DH *dh);
 TR_EXPORT int tr_compute_dh_key(unsigned char **pbuf,  BIGNUM *pub_key, DH *priv_dh);
 
+TR_EXPORT void tr_dh_free(unsigned char *dh_buf);
+int TR_EXPORT tr_dh_pub_hash(TID_REQ *request,
+                            unsigned char **out_digest,
+                            size_t *out_llen);
+
 
 TR_EXPORT void tr_bin_to_hex(const unsigned char * bin, size_t binlen,
                             char * hex_out, size_t hex_len);
index 486bbbc..418edb5 100644 (file)
@@ -37,6 +37,8 @@
 #include <string.h>
 #include <trust_router/tr_versioning.h>
 
+typedef const char *tr_const_string;
+
 typedef struct tr__name {
   char *buf;
   int len;
diff --git a/redhat/default-main.cfg b/redhat/default-main.cfg
new file mode 100644 (file)
index 0000000..51324b4
--- /dev/null
@@ -0,0 +1,5 @@
+{"tr_internal":{"max_tree_depth": 4,
+                "hostname":"tr.moonshot.local",
+               "tids_port" : 12309
+               }
+}
diff --git a/redhat/init b/redhat/init
new file mode 100755 (executable)
index 0000000..7c5900e
--- /dev/null
@@ -0,0 +1,308 @@
+#!/bin/bash
+#
+# ntpd         This shell script takes care of starting and stopping
+#              trust_router.
+#
+# chkconfig: - 58 74
+# description: trust_router is the GSS-EAP trust routing daemon. \
+# GSS-EAP is an IETF standard for providing authentication across \
+# an insecure WAN. \
+
+### BEGIN INIT INFO
+# Provides: trust_router
+# Required-Start: $network $local_fs $remote_fs
+# Required-Stop: $network $local_fs $remote_fs
+# Should-Start: $syslog $named ntpdate
+# Should-Stop: $syslog $named
+# Short-Description: start and stop trust_router
+# Description: trust_router is the GSS-EAP trust routing daemon.
+#              GSS-EAP is an IETF standard for providing authentication
+#              across an insecure WAN.
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+# Source networking configuration.
+. /etc/sysconfig/network
+
+# Load the instance configuration
+[ -f /etc/sysconfig/trust_router ] || exit 6
+. /etc/sysconfig/trust_router
+
+# Create the pidfile directory
+mkdir -p /var/run/trust_router
+chown trustrouter:trustrouter /var/run/trust_router
+
+# Does the trust router and wrapper exist
+[ -x /usr/bin/trust_router ] || exit 5
+[ -x /usr/bin/trust_router-wrapper ] || exit 5
+
+# Does the tidc client exist
+[ -x /usr/bin/tidc ] || exit 5
+[ -x /usr/bin/tidc-wrapper ] || exit 5
+
+prog="trust_router-wrapper"
+
+array_contains() {
+       local i
+
+       for i in "${@:2}" ;
+       do
+               [ "${i}" == "${1}" ] && return 0
+       done
+
+       return 1
+}
+
+execute-tidc() {
+       echo -n "Attempting to authenticate to instance ${current_instance}:${current_port}"
+
+       daemon --user="${current_user}" /usr/bin/tidc-wrapper "${current_test_acceptor}" "${current_test_rprealm}" "${current_test_community}" "${current_test_realm}" "${current_port}"
+       tidc_ret=$?
+
+       echo
+
+       return ${tidc_ret}
+}
+
+get-config() {
+       current_instance=${1}
+
+       if [ "${TR_CONFIG_USER[${current_instance}]+abc}" ] ;
+       then
+               current_user=${TR_CONFIG_USER[${current_instance}]}
+       else
+               current_user=${TR_DEFAULT_USER}
+       fi
+
+       if [ "${TR_CONFIG_PIDDIR[${current_instance}]+abc}" ] ;
+       then
+               current_piddir=${TR_CONFIG_PIDDIR[${current_instance}]}
+       else
+               current_piddir=${TR_DEFAULT_PIDDIR}
+       fi
+
+       if [ "${TR_CONFIG_CFGDIR[${current_instance}]+abc}" ] ;
+       then
+               current_cfgdir=${TR_CONFIG_CFGDIR[${current_instance}]}
+       else
+               current_cfgdir=${TR_DEFAULT_CFGDIR}
+       fi
+
+       if [ "${TR_CONFIG_LOGDIR[${current_instance}]+abc}" ] ;
+       then
+               current_logdir=${TR_CONFIG_LOGDIR[${current_instance}]}
+       else
+               current_logdir=${TR_DEFAULT_LOGDIR}
+       fi
+
+       if [ "${TR_CONFIG_PORT[${current_instance}]+abc}" ] ;
+       then
+               current_port=${TR_CONFIG_PORT[${current_instance}]}
+       else
+               current_port=${TR_DEFAULT_PORT}
+       fi
+
+       if [ "${TR_CONFIG_AUTOSTART[${current_instance}]+abc}" ] ;
+       then
+               current_autostart=${TR_CONFIG_AUTOSTART[${current_instance}]}
+       else
+               current_autostart=${TR_DEFAULT_AUTOSTART}
+       fi
+
+       if [ "${TR_CONFIG_ACCEPTOR[${current_instance}]+abc}" ] ;
+       then
+               current_test_acceptor=${TR_CONFIG_TEST_ACCEPTOR[${current_instance}]}
+       else
+               current_test_acceptor=${TR_DEFAULT_TEST_ACCEPTOR}
+       fi
+
+       if [ "${TR_CONFIG_RPREALM[${current_instance}]+abc}" ] ;
+       then
+               current_test_rprealm=${TR_CONFIG_TEST_RPREALM[${current_instance}]}
+       else
+               current_test_rprealm=${TR_DEFAULT_TEST_RPREALM}
+       fi
+
+       if [ "${TR_CONFIG_TEST_COMMUNITY[${current_instance}]+abc}" ] ;
+       then
+               current_test_community=${TR_CONFIG_TEST_COMMUNITY[${current_instance}]}
+       else
+               current_test_community=${TR_DEFAULT_TEST_COMMUNITY}
+       fi
+
+       if [ "${TR_CONFIG_TEST_REALM[${current_instance}]+abc}" ] ;
+       then
+               current_test_realm=${TR_CONFIG_TEST_REALM[${current_instance}]}
+       else
+               current_test_realm=${TR_DEFAULT_TEST_REALM}
+       fi
+}
+
+get-pidfile() {
+       echo "${current_piddir}/${current_instance}.pid"
+}
+
+start() {
+       [ "${EUID}" != "0" ] && exit 4
+       [ "${NETWORKING}" = "no" ] && exit 1
+
+       start_ret=0
+
+       for i in "${TR_INSTANCES[@]}"
+       do
+               get-config "${i}"
+
+               if ${current_autostart} ;
+               then
+                       start-instance
+                       let "start_ret+=$?"
+               else
+                       echo "Skipping instance ${current_instance}"
+               fi
+       done
+
+       return "${start_ret}"
+}
+
+start-single() {
+               if array_contains "${1}" "${TR_INSTANCES[@]}" ;
+               then
+               get-config "${1}"
+
+               start-instance
+               return $?
+               else
+                       echo "Instance ${1} not found..."
+
+                return 1
+               fi
+}
+
+start-instance() {
+       pidfile=$(get-pidfile)
+       logfile="${current_logdir}/${current_instance}.log"
+       cfgdir="${current_cfgdir}/${current_instance}/"
+
+       OPTIONS="${pidfile} ${cfgdir} ${logfile}"
+
+       if [ -f "${pidfile}" ] ;
+       then
+               local OLD_PID=$(cat "${pidfile}")
+
+               if [ -d "/proc/${OLD_PID}" ] ;
+               then
+                       echo "Instance ${current_instance} is already running..."
+               else
+                       echo "Removing stale PID file..."
+                       rm "${pidfile}"
+
+                       start-instance
+                       return $?
+               fi
+       else
+               echo -n "Starting instance ${current_instance}..."
+               daemon --user="${current_user}" --pidfile="${pidfile}" "${prog}" "${OPTIONS}"
+               echo
+       fi
+
+       # Give it a few seconds for things to settle
+       sleep 2
+
+       execute-tidc
+       return $?
+}
+
+stop() {
+       [ "${EUID}" != "0" ] && exit 4
+        [ "${NETWORKING}" = "no" ] && exit 1
+
+        for i in "${TR_INSTANCES[@]}"
+               do
+                       get-config "${i}"
+
+               pidfile=$(get-pidfile)
+
+               if [ -f "${pidfile}" ] ;
+               then
+                       stop-instance
+               else
+                       echo "Instance ${i} does not appear to be running..."
+               fi
+       done
+}
+
+stop-single() {
+       if array_contains "${1}" "${TR_INSTANCES[@]}" ;
+       then
+               get-config "${1}"
+
+               stop-instance
+       else
+               echo "Instance ${1} not found..."
+
+               return 1
+       fi
+
+       return 0
+}
+
+stop-instance() {
+       if [ -f "$(get-pidfile)" ]  ;
+       then
+               echo -n "Stopping instance ${current_instance}..."
+
+               killproc -p "$(get-pidfile)" "${prog}"
+               echo
+       else
+               echo "Instance ${current_instance} does not appear to be running..."
+       fi
+}
+
+status() {
+               [ "${EUID}" != "0" ] && exit 4
+               [ "${NETWORKING}" = "no" ] && exit 1
+
+       start_ret=0
+
+               for i in "${TR_INSTANCES[@]}"
+        do
+                       get-config "${i}"
+
+               execute-tidc
+                let "exec_ret+=$?"
+        done
+
+               return "${exec_ret}"
+}
+
+
+# See how we were called.
+case "${1}" in
+  start)
+       start
+       ;;
+  start-single)
+       start-single "${2}"
+       ;;
+  stop)
+       stop
+       ;;
+  stop-single)
+       stop-single "${2}"
+       ;;
+  status)
+       status "${prog}"
+       ;;
+  restart|force-reload)
+       stop
+       start
+       ;;
+  reload)
+       exit 3
+       ;;
+  *)
+       echo "Usage: ${0} {start|start-single|stop|stop-single|status|restart|force-reload}"
+       exit 2
+esac
diff --git a/redhat/sysconfig b/redhat/sysconfig
new file mode 100644 (file)
index 0000000..4530de5
--- /dev/null
@@ -0,0 +1,44 @@
+##
+## Declare an id tag for each trust router instance
+##
+
+TR_INSTANCES[0]="default"
+TR_INSTANCES[1]="tr-test"
+
+##
+## Declare the default configuration
+##
+
+TR_DEFAULT_USER="trustrouter"                    # Username to execute the trust router as
+TR_DEFAULT_PIDDIR="/var/run/trust_router"        # Directory to store PIDFile in 
+TR_DEFAULT_CFGDIR="/etc/trust_router/conf.d"     # Config directory
+TR_DEFAULT_LOGDIR="/var/log/trust_router"        # Trust router log directories
+TR_DEFAULT_AUTOSTART=true                        # Default autostart state
+TR_DEFAULT_PORT=12309                            # Port instance should be running on
+TR_DEFAULT_TEST_ACCEPTOR="tr.moonshot.local"     # Acceptor name to expect when testing
+TR_DEFAULT_TEST_RPREALM="apc.moonshot.local"     # RP Realm to assert when testing
+TR_DEFAULT_TEST_COMMUNITY="apc.moonshot.local"   # Community to query when testing
+TR_DEFAULT_TEST_REALM="apc.moonshot.local"       # Realm to request when testing
+
+## 
+## Declare the configuration arrays
+##
+
+declare -A TR_CONFIG_USER
+declare -A TR_CONFIG_PIDDIR
+declare -A TR_CONFIG_CFGDIR
+declare -A TR_CONFIG_LOGDIR
+declare -A TR_CONFIG_PORT
+declare -A TR_CONFIG_AUTOSTART
+declare -A TR_CONFIG_TEST_ACCEPTOR
+declare -A TR_CONFIG_TEST_RPREALM
+declare -A TR_CONFIG_TEST_COMMUNITY
+declare -A TR_CONFIG_TEST_REALM
+##
+## Override the default configuation for each instance as required
+##
+
+TR_CONFIG_PORT[tr-test]=12345
+TR_CONFIG_AUTOSTART[tr-test]=false
+
diff --git a/redhat/tidc-wrapper b/redhat/tidc-wrapper
new file mode 100755 (executable)
index 0000000..20eb974
--- /dev/null
@@ -0,0 +1,4 @@
+#! /usr/bin/env bash
+
+tidc "$@"  > /dev/null 2>&1
+exit "${?}"
diff --git a/redhat/tr-test-main.cfg b/redhat/tr-test-main.cfg
new file mode 100644 (file)
index 0000000..45f845e
--- /dev/null
@@ -0,0 +1,5 @@
+{"tr_internal":{"max_tree_depth": 4,
+                "hostname":"tr.moonshot.local",
+               "tids_port" : 12345
+               }
+}
diff --git a/redhat/trust_router-wrapper b/redhat/trust_router-wrapper
new file mode 100755 (executable)
index 0000000..81bf47e
--- /dev/null
@@ -0,0 +1,11 @@
+#! /usr/bin/env bash
+
+cd "${2}"
+
+/usr/bin/trust_router > "${3}.$(date +'%Y%m%d%H%M')" 2>&1 &
+BGPID=$!
+RET=$?
+
+echo "${BGPID}" > "${1}"
+
+exit "${RET}"
diff --git a/redhat/trusts.cfg b/redhat/trusts.cfg
new file mode 100644 (file)
index 0000000..0998e1f
--- /dev/null
@@ -0,0 +1,128 @@
+{
+  "communities": [
+    {
+      "apcs": [
+        "pci-community.ja.net"
+      ],
+      "community_id": "comm.offcenter.org",
+      "idp_realms": [
+        "idr2.offcenter.org"
+      ],
+      "rp_realms": [
+        "sr3.offcenter.org"
+      ],
+      "type": "coi"
+    },
+    {
+      "apcs": [
+
+      ],
+      "community_id": "pci-community.ja.net",
+      "idp_realms": [
+        "idr1.offcenter.org",
+        "idr2.offcenter.org",
+        "ja.net",
+        "no-longer-untitled.offcenter.org"
+      ],
+      "rp_realms": [
+        "exchange.ja.net",
+        "sr3.offcenter.org"
+      ],
+      "type": "apc"
+    }
+  ],
+  "idp_realms": [
+    {
+      "aaa_servers": [
+        "127.0.0.1"
+      ],
+      "apcs": [
+        "pci-community.ja.net"
+      ],
+      "realm_id": "idr1.offcenter.org",
+      "shared_config": "yes"
+    },
+    {
+      "aaa_servers": [
+        "127.0.0.1"
+      ],
+      "apcs": [
+        "pci-community.ja.net"
+      ],
+      "realm_id": "idr2.offcenter.org",
+      "shared_config": "no"
+    },
+    {
+      "aaa_servers": [
+        "10.1.10.90"
+      ],
+      "apcs": [
+        "pci-community.ja.net"
+      ],
+      "realm_id": "ja.net",
+      "shared_config": "no"
+    },
+    {
+      "aaa_servers": [
+        "127.0.0.1"
+      ],
+      "apcs": [
+        "pci-community.ja.net"
+      ],
+      "realm_id": "no-longer-untitled.offcenter.org",
+      "shared_config": "yes"
+    }
+  ],
+  "rp_clients": [
+    {
+      "filter": {
+        "filter_lines": [
+          {
+            "action": "accept",
+            "domain_constraints": ["*.exchange.ja.net"],
+            "filter_specs": [
+              {
+                "field": "rp_realm",
+                "match": "exchange.ja.net"
+              },
+              {
+                "field": "rp_realm",
+                "match": "*.exchange.ja.net"
+              }
+            ],
+            "realm_constraints": ["*.exchange.ja.net", "a.com"]
+          }
+        ],
+        "type": "rp_permitted"
+      },
+      "gss_names": [
+        "01b80aa9-8753-4691-8f8a-f49f7793546f@portal-realm.ja.net"
+      ]
+    },
+    {
+      "filter": {
+        "filter_lines": [
+          {
+            "action": "accept",
+            "domain_constraints": ["*.bob.sr3.offcenter.org"],
+            "filter_specs": [
+              {
+                "field": "rp_realm",
+                "match": "sr3.offcenter.org"
+              },
+              {
+                "field": "rp_realm",
+                "match": "*.sr3.offcenter.org"
+              }
+            ],
+            "realm_constraints": ["*.sr3.offcenter.org" ]
+          }
+        ],
+        "type": "rp_permitted"
+      },
+      "gss_names": [
+        "895c308a-5624-4055-bb4f-ea24b77e6637@portal-realm.ja.net"
+      ]
+    }
+  ]
+}
diff --git a/schema.sql b/schema.sql
new file mode 100644 (file)
index 0000000..6ae8690
--- /dev/null
@@ -0,0 +1,9 @@
+create table if not exists psk_keys (keyid text primary key, key blob, client_dh_pub raw(20));
+create table if not exists authorizations( client_dh_pub raw(20), coi string, acceptor_realm string, hostname string, apc string);
+create index if not exists authorizations_dhpub on authorizations( client_dh_pub);
+CREATE VIEW if not exists authorizations_keys as select keyid, authorizations.* from psk_keys join authorizations on psk_keys.client_dh_pub = authorizations.client_dh_pub;
+
+.quit
+
+
index 751a504..3088e6b 100644 (file)
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <talloc.h>
 
 #include <gsscon.h>
-#include <trust_router/tid.h>
+#include <tid_internal.h>
 #include <trust_router/tr_dh.h>
 
 void static tidc_print_usage (const char *name)
 {
-  printf("Usage: %s <server> <RP-realm> <target-realm> <community>\n", name);
+  printf("Usage: %s <server> <RP-realm> <target-realm> <community> [<port>]\n", name);
 }
 
 static void tidc_resp_handler (TIDC_INSTANCE * tidc, 
@@ -92,12 +93,14 @@ int main (int argc,
   char *rp_realm = NULL;
   char *realm = NULL;
   char *coi = NULL;
+  int port = TID_PORT;
   int conn = 0;
   int rc;
   gss_ctx_id_t gssctx;
 
+  talloc_set_log_stderr();
   /* Parse command-line arguments */ 
-  if (argc != 5) {
+  if (argc < 5 || argc > 6) {
     tidc_print_usage(argv[0]);
     exit(1);
   }
@@ -108,7 +111,11 @@ int main (int argc,
   realm = (char *)argv[3];
   coi = (char *)argv[4];
 
-  printf("TIDC Client:\nServer = %s, rp_realm = %s, target_realm = %s, community = %s\n", server, rp_realm, realm, coi);
+  if (argc > 5) {
+    port = strtol(argv[5], NULL, 10);
+  }
+
+  printf("TIDC Client:\nServer = %s, rp_realm = %s, target_realm = %s, community = %s, port = %i\n", server, rp_realm, realm, coi, port);
  
   /* Create a TID client instance & the client DH */
   tidc = tidc_create();
@@ -118,7 +125,7 @@ int main (int argc,
   }
 
   /* Set-up TID connection */
-  if (-1 == (conn = tidc_open_connection(tidc, server, TID_PORT, &gssctx))) {
+  if (-1 == (conn = tidc_open_connection(tidc, server, port, &gssctx))) {
     /* Handle error */
     printf("Error in tidc_open_connection.\n");
     return 1;
index 766c24f..e920874 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <talloc.h>
 #include <sqlite3.h>
 
-#include <trust_router/tid.h>
+#include <tr_debug.h>
+#include <tid_internal.h>
+#include <trust_router/tr_constraint.h>
 #include <trust_router/tr_dh.h>
 #include <openssl/rand.h>
 
 static sqlite3 *db = NULL;
 static sqlite3_stmt *insert_stmt = NULL;
+static sqlite3_stmt *authorization_insert = NULL;
 
 static int  create_key_id(char *out_id, size_t len)
 {
@@ -62,32 +66,118 @@ static int  create_key_id(char *out_id, size_t len)
   out_id[bin_len*2] = '\0';
   return 0;
 }
-  
+
+static int sqlify_wc(
+                    TID_REQ *req,
+                    const char **wc,
+                    size_t len,
+                    char **error)
+{
+  size_t lc;
+  *error = NULL;
+  for (lc = 0; lc < len; lc++) {
+    if (strchr(wc[lc], '%')) {
+      *error = talloc_asprintf( req, "Constraint match `%s' is not appropriate for SQL",
+                                 wc[lc]);
+      return -1;
+    }
+    if ('*' ==wc[lc][0]) {
+      char *s;
+      s = talloc_strdup(req, wc[lc]);
+      s[0] = '%';
+      wc[lc] = s;
+    }
+  }
+  return 0;
+}
+
+       
+
+static int handle_authorizations(TID_REQ *req, const unsigned char *dh_hash,
+                                size_t hash_len)
+{
+  TR_CONSTRAINT_SET *intersected = NULL;
+  const char **domain_wc, **realm_wc;
+  size_t domain_len, realm_len;
+  size_t domain_index, realm_index;
+  char *error;
+  int sqlite3_result;
+
+  if (!req->cons) {
+    tr_debug("Request has no constraints, so no authorizations.\n");
+    return 0;
+  }
+  intersected = tr_constraint_set_intersect(req, req->cons);
+  if (!intersected)
+    return -1;
+  if (0 != tr_constraint_set_get_match_strings(req,
+                                              intersected, "domain",
+                                              &domain_wc, &domain_len))
+    return -1;
+  if (0 != tr_constraint_set_get_match_strings(req,
+                                              intersected, "realm",
+                                              &realm_wc, &realm_len))
+    return -1;
+  tr_debug(" %u domain constraint matches and %u realm constraint matches\n",
+          (unsigned) domain_len, (unsigned) realm_len);
+  if (0 != sqlify_wc(req, domain_wc, domain_len, &error)) {
+    tr_debug("Processing domain constraints: %s\n", error);
+    return -1;
+  }else if (0 != sqlify_wc(req, realm_wc, realm_len, &error)) {
+    tr_debug("Processing realm constraints: %s\n", error);
+    return -1;
+  }
+  if (!authorization_insert) {
+    tr_debug( " No database, no authorizations inserted\n");
+    return 0;
+  }
+  for (domain_index = 0; domain_index < domain_len; domain_index++)
+    for (realm_index = 0; realm_index < realm_len; realm_index++) {
+      TR_NAME *community = req->orig_coi;
+      if (!community)
+       community = req->comm;
+      sqlite3_bind_blob(authorization_insert, 1, dh_hash, hash_len, SQLITE_TRANSIENT);
+      sqlite3_bind_text(authorization_insert, 2, community->buf, community->len, SQLITE_TRANSIENT);
+      sqlite3_bind_text(authorization_insert, 3, realm_wc[realm_index], -1, SQLITE_TRANSIENT);
+      sqlite3_bind_text(authorization_insert, 4, domain_wc[domain_index], -1, SQLITE_TRANSIENT);
+      sqlite3_bind_text(authorization_insert, 5, req->comm->buf, req->comm->len, SQLITE_TRANSIENT);
+      sqlite3_result = sqlite3_step(authorization_insert);
+      if (SQLITE_DONE != sqlite3_result)
+       printf("sqlite3: failed to write to database\n");
+      sqlite3_reset(authorization_insert);
+    }
+  return 0;
+}
+
+
 static int tids_req_handler (TIDS_INSTANCE *tids,
                      TID_REQ *req, 
-                     TID_RESP **resp,
+                     TID_RESP *resp,
                      void *cookie)
 {
   unsigned char *s_keybuf = NULL;
   int s_keylen = 0;
   char key_id[12];
+  unsigned char *pub_digest;
+  size_t pub_digest_len;
   
 
   fprintf(stdout, "tids_req_handler: Request received! target_realm = %s, community = %s\n", req->realm->buf, req->comm->buf);
   if (tids)
     tids->req_count++;
 
-  if (!(resp) || !(*resp)) {
+  if (!(resp) || !resp) {
     fprintf(stderr, "tids_req_handler: No response structure.\n");
     return -1;
   }
 
   /* Allocate a new server block */
-  if (NULL == ((*resp)->servers = malloc(sizeof(TID_SRVR_BLK)))){
+  if (NULL == (resp->servers = malloc(sizeof(TID_SRVR_BLK)))){
     fprintf(stderr, "tids_req_handler(): malloc failed.\n");
     return -1;
   }
-  memset((*resp)->servers, 0, sizeof(TID_SRVR_BLK));
+  memset(resp->servers, 0, sizeof(TID_SRVR_BLK));
+  resp->num_servers = 1;
 
   /* TBD -- Set up the server IP Address */
 
@@ -105,12 +195,12 @@ static int tids_req_handler (TIDS_INSTANCE *tids,
   // fprintf(stderr, "Generating the server DH block.\n");
   // fprintf(stderr, "...from client DH block, dh_g = %s, dh_p = %s.\n", BN_bn2hex(req->tidc_dh->g), BN_bn2hex(req->tidc_dh->p));
 
-  if (NULL == ((*resp)->servers->aaa_server_dh = tr_create_matching_dh(NULL, 0, req->tidc_dh))) {
+  if (NULL == (resp->servers->aaa_server_dh = tr_create_matching_dh(NULL, 0, req->tidc_dh))) {
     fprintf(stderr, "tids_req_handler(): Can't create server DH params.\n");
     return -1;
   }
 
-  if (0 == inet_aton(tids->ipaddr, &((*resp)->servers->aaa_server_addr))) {
+  if (0 == inet_aton(tids->ipaddr, &(resp->servers->aaa_server_addr))) {
     fprintf(stderr, "tids_req_handler(): inet_aton() failed.\n");
     return -1;
   }
@@ -118,21 +208,29 @@ static int tids_req_handler (TIDS_INSTANCE *tids,
   /* Set the key name */
   if (-1 == create_key_id(key_id, sizeof(key_id)))
     return -1;
-  (*resp)->servers->key_name = tr_new_name(key_id);
+  resp->servers->key_name = tr_new_name(key_id);
 
   /* Generate the server key */
   // fprintf(stderr, "Generating the server key.\n");
 
   if (0 > (s_keylen = tr_compute_dh_key(&s_keybuf, 
                                        req->tidc_dh->pub_key, 
-                                       (*resp)->servers->aaa_server_dh))) {
+                                       resp->servers->aaa_server_dh))) {
     fprintf(stderr, "tids_req_handler(): Key computation failed.");
     return -1;
   }
+  if (0 != tr_dh_pub_hash(req,
+                         &pub_digest, &pub_digest_len)) {
+    tr_debug("Unable to digest client public key\n");
+    return -1;
+  }
+  if (0 != handle_authorizations(req, pub_digest, pub_digest_len))
+    return -1;
   if (NULL != insert_stmt) {
     int sqlite3_result;
     sqlite3_bind_text(insert_stmt, 1, key_id, -1, SQLITE_TRANSIENT);
     sqlite3_bind_blob(insert_stmt, 2, s_keybuf, s_keylen, SQLITE_TRANSIENT);
+    sqlite3_bind_blob(insert_stmt, 3, pub_digest, pub_digest_len, SQLITE_TRANSIENT);
     sqlite3_result = sqlite3_step(insert_stmt);
     if (SQLITE_DONE != sqlite3_result)
       printf("sqlite3: failed to write to database\n");
@@ -165,6 +263,7 @@ int main (int argc,
   const char *hostname = NULL;
   TR_NAME *gssname = NULL;
 
+  talloc_set_log_stderr();
   /* Parse command-line arguments */ 
   if (argc != 5) {
     fprintf(stdout, "Usage: %s <ip-address> <gss-name> <hostname> <database-name>\n", argv[0]);
@@ -177,8 +276,10 @@ int main (int argc,
     fprintf(stdout, "Error opening database %s\n", argv[4]);
     exit(1);
   }
-  sqlite3_prepare_v2(db, "insert into psk_keys (keyid, key) values(?, ?)",
+  sqlite3_prepare_v2(db, "insert into psk_keys (keyid, key, client_dh_pub) values(?, ?, ?)",
                     -1, &insert_stmt, NULL);
+  sqlite3_prepare_v2(db, "insert into authorizations (client_dh_pub, coi, acceptor_realm, hostname, apc) values(?, ?, ?, ?, ?)",
+                    -1, &authorization_insert, NULL);
 
   /* Create a TID server instance */
   if (NULL == (tids = tids_create())) {
index 6bb269b..23599ad 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <assert.h>
+#include <talloc.h>
+
+#include <tid_internal.h>
+#include <jansson.h>
+
+static int destroy_tid_req(TID_REQ *req)
+{
+  if (req->json_references)
+    json_decref(req->json_references);
+  return 0;
+}
+
+TID_REQ *tid_req_new()
+{
+  TID_REQ *req = talloc_zero(NULL, TID_REQ);
+  if(!req)
+    return NULL;
+  talloc_set_destructor(req, destroy_tid_req);
+  req->json_references = json_array();
+  assert(req->json_references);
+  req->conn = -1;
+  return req;
+}
 
-#include <trust_router/tid.h>
 TID_REQ *tid_req_get_next_req(TID_REQ *req)
 {
   return(req->next_req);
@@ -157,6 +180,7 @@ TID_REQ *tid_dup_req (TID_REQ *orig_req)
 
   /* Memcpy for flat fields, not valid until names are duped. */
   memcpy(new_req, orig_req, sizeof(TID_REQ));
+  json_incref(new_req->json_references);
   
   if ((NULL == (new_req->rp_realm = tr_dup_name(orig_req->rp_realm))) ||
       (NULL == (new_req->realm = tr_dup_name(orig_req->realm))) ||
@@ -173,3 +197,41 @@ TID_REQ *tid_dup_req (TID_REQ *orig_req)
   return new_req;
 }
 
+
+void tid_req_cleanup_json( TID_REQ *req, json_t *ref)
+{
+  (void) json_array_append_new(req->json_references, ref);
+}
+
+void tid_req_free(TID_REQ *req)
+{
+  talloc_free(req);
+}
+
+
+void tid_srvr_get_address(const TID_SRVR_BLK *blk,
+                         const struct sockaddr **out_addr,
+                         size_t *out_len)
+{
+  struct sockaddr_in *sa = NULL;
+    assert(blk);
+    sa = talloc_zero(blk, struct sockaddr_in);
+    sa->sin_family = AF_INET;
+    sa->sin_addr = blk->aaa_server_addr;
+    sa->sin_port = htons(2083);
+    *out_addr = (struct sockaddr *) sa;
+    *out_len = sizeof( struct sockaddr_in);
+}
+
+DH *tid_srvr_get_dh( TID_SRVR_BLK *blk)
+{
+  assert(blk);
+  return blk->aaa_server_dh;
+}
+
+const TR_NAME *tid_srvr_get_key_name(
+                                   const TID_SRVR_BLK *blk)
+{
+  assert(blk);
+  return blk->key_name;
+}
index 6cfbb87..14cc213 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <assert.h>
 
-#include <trust_router/tid.h>
+#include <tid_internal.h>
 
-TR_EXPORT TID_RC tid_resp_get_result(TID_RESP *resp)
+TR_EXPORT int tid_resp_get_result(TID_RESP *resp)
 {
   return(resp->result);
 }
 
-void tid_resp_set_result(TID_RESP *resp, TID_RC result)
+void tid_resp_set_result(TID_RESP *resp, int result)
 {
   resp->result = result;
 }
@@ -97,12 +98,17 @@ void tid_resp_set_orig_coi(TID_RESP *resp, TR_NAME *orig_coi)
   resp->orig_coi = orig_coi;
 }
 
-TR_EXPORT TID_SRVR_BLK *tid_resp_get_servers(TID_RESP *resp)
+TR_EXPORT TID_SRVR_BLK *tid_resp_get_server(TID_RESP *resp,
+                                           size_t index)
 {
-  return(resp->servers);
+  assert(resp);
+  assert(index < resp->num_servers);
+  return(&(resp->servers[index]));
 }
 
-void tid_resp_set_servers(TID_RESP *resp, TID_SRVR_BLK *servers)
+size_t tid_resp_get_num_servers(const TID_RESP *resp)
 {
-  resp->servers = servers;
+  assert(resp);
+  return resp->num_servers;
 }
+
index 9590260..103d354 100644 (file)
@@ -36,7 +36,7 @@
 #include <jansson.h>
 
 #include <trust_router/tr_dh.h>
-#include <trust_router/tid.h>
+#include <tid_internal.h>
 #include <tr_msg.h>
 #include <gsscon.h>
 
@@ -96,11 +96,9 @@ int tidc_send_request (TIDC_INSTANCE *tidc,
   TID_REQ *tid_req = NULL;
 
   /* Create and populate a TID req structure */
-  if (!(tid_req = malloc(sizeof(TID_REQ))))
+  if (!(tid_req = tid_req_new()))
     return -1;
 
-  memset(tid_req, 0, sizeof(TID_REQ));
-
   tid_req->conn = conn;
   tid_req->gssctx = gssctx;
 
@@ -134,7 +132,7 @@ int tidc_fwd_request (TIDC_INSTANCE *tidc,
     return -1;
 
   msg->msg_type = TID_REQUEST;
-  msg->tid_req = tid_req;
+  tr_msg_set_req(msg, tid_req);
 
   /* store the response function and cookie */
   // tid_req->resp_func = resp_handler;
@@ -176,21 +174,21 @@ int tidc_fwd_request (TIDC_INSTANCE *tidc,
   }
 
   /* TBD -- Check if this is actually a valid response */
-  if (!resp_msg->tid_resp) {
+  if (TID_RESPONSE != tr_msg_get_msg_type(resp_msg)) {
     fprintf(stderr, "tidc_fwd_request: Error, no response in the response!\n");
     return -1;
   }
   
   if (resp_handler)
     /* Call the caller's response function */
-    (*resp_handler)(tidc, tid_req, resp_msg->tid_resp, cookie);
+    (*resp_handler)(tidc, tid_req, tr_msg_get_resp(resp_msg), cookie);
   else
     fprintf(stderr, "tidc_fwd_request: NULL response function.\n");
 
   if (msg)
     free(msg);
   if (tid_req)
-    free(tid_req);
+    tid_req_free(tid_req);
   if (req_buf)
     free(req_buf);
   if (resp_buf)
@@ -202,6 +200,13 @@ int tidc_fwd_request (TIDC_INSTANCE *tidc,
 }
 
 
+DH * tidc_get_dh(TIDC_INSTANCE *inst)
+{
+  return inst->client_dh;
+}
 
-
-
+DH *tidc_set_dh(TIDC_INSTANCE *inst, DH *dh)
+{
+  inst->client_dh = dh;
+  return dh;
+}
index 431fa4a..d94fff2 100644 (file)
@@ -41,8 +41,8 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <jansson.h>
-
-#include <trust_router/tid.h>
+#include <talloc.h>
+#include <tid_internal.h>
 #include <gsscon.h>
 #include <tr_msg.h>
 
@@ -50,7 +50,7 @@ static TID_RESP *tids_create_response (TIDS_INSTANCE *tids, TID_REQ *req)
 {
   TID_RESP *resp;
 
-  if ((NULL == (resp = calloc(sizeof(TID_RESP), 1)))) {
+  if ((NULL == (resp = talloc_zero(req, TID_RESP)))) {
     fprintf(stderr, "tids_create_response: Error allocating response structure.\n");
     return NULL;
   }
@@ -84,7 +84,7 @@ static void tids_destroy_response(TIDS_INSTANCE *tids, TID_RESP *resp)
       tr_free_name(resp->comm);
     if (resp->orig_coi)
       tr_free_name(resp->orig_coi);
-    free (resp);
+    talloc_free(resp);
   }
 }
 
@@ -192,33 +192,33 @@ static int tids_read_request (TIDS_INSTANCE *tids, int conn, gss_ctx_id_t *gssct
   return buflen;
 }
 
-static int tids_handle_request (TIDS_INSTANCE *tids, TR_MSG *mreq, TID_RESP **resp) 
+static int tids_handle_request (TIDS_INSTANCE *tids, TR_MSG *mreq, TID_RESP *resp) 
 {
   int rc;
 
   /* Check that this is a valid TID Request.  If not, send an error return. */
-  if ((!mreq->tid_req) ||
-      (!mreq->tid_req->rp_realm) ||
-      (!mreq->tid_req->realm) ||
-      (!mreq->tid_req->comm)) {
+  if ((!tr_msg_get_req(mreq)) ||
+      (!tr_msg_get_req(mreq)->rp_realm) ||
+      (!tr_msg_get_req(mreq)->realm) ||
+      (!tr_msg_get_req(mreq)->comm)) {
     fprintf(stderr, "tids_handle_request():Not a valid TID Request.\n");
-    (*resp)->result = TID_ERROR;
-    (*resp)->err_msg = tr_new_name("Bad request format");
+    resp->result = TID_ERROR;
+    resp->err_msg = tr_new_name("Bad request format");
     return -1;
   }
 
   /* Call the caller's request handler */
   /* TBD -- Handle different error returns/msgs */
-  if (0 > (rc = (*tids->req_handler)(tids, mreq->tid_req, &(*resp), tids->cookie))) {
+  if (0 > (rc = (*tids->req_handler)(tids, tr_msg_get_req(mreq), resp, tids->cookie))) {
     /* set-up an error response */
-    (*resp)->result = TID_ERROR;
-    if (!(*resp)->err_msg)     /* Use msg set by handler, if any */
-      (*resp)->err_msg = tr_new_name("Internal processing error");
+    resp->result = TID_ERROR;
+    if (!resp->err_msg)        /* Use msg set by handler, if any */
+      resp->err_msg = tr_new_name("Internal processing error");
   }
   else {
     /* set-up a success response */
-    (*resp)->result = TID_SUCCESS;
-    (*resp)->err_msg = NULL;   /* No error msg on successful return */
+    resp->result = TID_SUCCESS;
+    resp->err_msg = NULL;      /* No error msg on successful return */
   }
     
   return rc;
@@ -261,7 +261,7 @@ int tids_send_response (TIDS_INSTANCE *tids, TID_REQ *req, TID_RESP *resp)
     return 0;
 
   mresp.msg_type = TID_RESPONSE;
-  mresp.tid_resp = resp;
+  tr_msg_set_resp(&mresp, resp);
   
   if (NULL == (resp_buf = tr_msg_encode(&mresp))) {
     fprintf(stderr, "tids_send_response: Error encoding json response.\n");
@@ -310,27 +310,27 @@ static void tids_handle_connection (TIDS_INSTANCE *tids, int conn)
     }
 
     /* Put connection information into the request structure */
-    mreq->tid_req->conn = conn;
-    mreq->tid_req->gssctx = gssctx;
+    tr_msg_get_req(mreq)->conn = conn;
+    tr_msg_get_req(mreq)->gssctx = gssctx;
 
     /* Allocate a response structure and populate common fields */
-    if (NULL == (resp = tids_create_response (tids, mreq->tid_req))) {
+    if (NULL == (resp = tids_create_response (tids, tr_msg_get_req(mreq)))) {
       fprintf(stderr, "tids_handle_connection: Error creating response structure.\n");
       /* try to send an error */
-      tids_send_err_response(tids, mreq->tid_req, "Error creating response.\n");
+      tids_send_err_response(tids, tr_msg_get_req(mreq), "Error creating response.\n");
       return;
     }
 
-    if (0 > (rc = tids_handle_request(tids, mreq, &resp))) {
+    if (0 > (rc = tids_handle_request(tids, mreq, resp))) {
       fprintf(stderr, "tids_handle_connection: Error from tids_handle_request(), rc = %d.\n", rc);
       /* Fall through, to send the response, either way */
     }
 
-    if (0 > (rc = tids_send_response(tids, mreq->tid_req, resp))) {
+    if (0 > (rc = tids_send_response(tids, tr_msg_get_req(mreq), resp))) {
       fprintf(stderr, "tids_handle_connection: Error from tids_send_response(), rc = %d.\n", rc);
       /* if we didn't already send a response, try to send a generic error. */
-      if (!mreq->tid_req->resp_sent)
-       tids_send_err_response(tids, mreq->tid_req, "Error sending response.\n");
+      if (!tr_msg_get_req(mreq)->resp_sent)
+       tids_send_err_response(tids, tr_msg_get_req(mreq), "Error sending response.\n");
       /* Fall through to free the response, either way. */
     }
     
diff --git a/tids.service b/tids.service
new file mode 100644 (file)
index 0000000..d36b091
--- /dev/null
@@ -0,0 +1,15 @@
+[Unit]
+Description = Trust Identity Protocol Server
+Before=freeradius.service
+
+[Service]
+EnvironmentFile=/etc/default/trust_router
+ExecStartPre=/bin/sh -c "/usr/bin/sqlite3 </usr/share/trust_router/schema.sql /var/lib/trust_router/keys"
+ExecStart=/usr/bin/tids  ${ipaddr} ${gssname} ${hostname} /var/lib/trust_router/keys
+Restart=always
+StandardOutput=syslog
+StandardError=inherit
+User=trustrouter
+
+[Install]
+WantedBy=multi-user.target
index 6830f6d..9de6ad0 100644 (file)
@@ -37,7 +37,7 @@
 
 #include <tr.h>
 #include <tr_filter.h>
-#include <trust_router/tid.h>
+#include <tid_internal.h>
 #include <tr_config.h>
 #include <tr_comm.h>
 #include <tr_idp.h>
@@ -68,7 +68,7 @@ static void tr_tidc_resp_handler (TIDC_INSTANCE *tidc,
 
 static int tr_tids_req_handler (TIDS_INSTANCE *tids,
                      TID_REQ *orig_req, 
-                     TID_RESP **resp,
+                     TID_RESP *resp,
                      void *tr)
 {
   TIDC_INSTANCE *tidc = NULL;
@@ -81,7 +81,7 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
   int oaction = TR_FILTER_ACTION_REJECT;
   int rc = 0;
 
-  if ((!tids) || (!orig_req) || (!resp) || (!(*resp)) || (!tr)) {
+  if ((!tids) || (!orig_req) || (!resp) ||  (!tr)) {
     fprintf(stderr, "tids_req_handler: Bad parameters\n");
     return -1;
   }
@@ -169,10 +169,15 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
   if (NULL == (aaa_servers = tr_idp_aaa_server_lookup((TR_INSTANCE *)tids->cookie, 
                                                      orig_req->realm, 
                                                      orig_req->comm))) {
-      fprintf(stderr, "tr_tids_req_handler: No AAA Servers for realm %s.\n", orig_req->realm->buf);
+      fprintf(stderr, "tr_tids_req_handler: No AAA Servers for realm %s, defaulting.\n", orig_req->realm->buf);
+      if (NULL == (aaa_servers = tr_default_server_lookup ((TR_INSTANCE *)tids->cookie,
+                                                          orig_req->comm))) {
+       fprintf(stderr, "tr_tids_req_handler: No default AAA servers, discarded.\n");
       tids_send_err_response(tids, orig_req, "No path to AAA Server(s) for realm");
       return -1;
-    }
+      }
+  }
+
   /* send a TID request to the AAA server(s), and get the answer(s) */
   /* TBD -- Handle multiple servers */
 
@@ -257,12 +262,7 @@ int main (int argc, const char *argv[])
     exit(1);
   }
 
-  /* read and parse initial configuration */
-  if (NULL == (jcfg = tr_read_config (n, cfg_files))) {
-    fprintf (stderr, "Error reading or parsing configuration files, exiting.\n");
-    exit(1);
-  }
-  if (TR_CFG_SUCCESS != tr_parse_config(tr, jcfg)) {
+  if (TR_CFG_SUCCESS != tr_parse_config(tr, cfg_files)) {
     fprintf (stderr, "Error decoding configuration information, exiting.\n");
     exit(1);
   }
index 58e9c4c..4247fe4 100644 (file)
@@ -1,5 +1,6 @@
+%global optflags %{optflags} -Wno-parentheses
 Name:           trust_router
-Version:        1.2
+Version:        1.3.2
 Release:        1%{?dist}
 Summary:        Moonshot Trust Router
 
@@ -11,8 +12,8 @@ BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 BuildRequires:  krb5-devel 
 BuildRequires: jansson-devel >= 2.4
-BuildRequires: sqlite-devel, openssl-devel
-Requires:       moonshot-gss-eap
+BuildRequires: sqlite-devel, openssl-devel, libtalloc-devel
+Requires:       moonshot-gss-eap, sqlite
 
 %description
 The trust router provides a mechanism for discovering the topology of
@@ -53,20 +54,75 @@ rm -rf $RPM_BUILD_ROOT
 make install DESTDIR=$RPM_BUILD_ROOT
 find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
 
+# Install config files
+install -D -m 755 redhat/init $RPM_BUILD_ROOT/%{_initrddir}/trust_router
+install -D -m 640 redhat/trusts.cfg $RPM_BUILD_ROOT/%{_sysconfdir}/trust_router/trusts.cfg
+install -D -m 640 redhat/default-main.cfg $RPM_BUILD_ROOT/%{_sysconfdir}/trust_router/conf.d/default/main.cfg
+install -D -m 640 redhat/tr-test-main.cfg $RPM_BUILD_ROOT/%{_sysconfdir}/trust_router/conf.d/tr-test/main.cfg
+install -D -m 640 redhat/sysconfig $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/trust_router
+
+# Link shared config
+ln -s ../../trusts.cfg $RPM_BUILD_ROOT/%{_sysconfdir}/trust_router/conf.d/default/trusts.cfg
+ln -s ../../trusts.cfg $RPM_BUILD_ROOT/%{_sysconfdir}/trust_router/conf.d/tr-test/trusts.cfg
+
+# Install wrapper scripts
+install -D -m 755 redhat/tidc-wrapper $RPM_BUILD_ROOT/%{_bindir}/tidc-wrapper
+install -D -m 755 redhat/trust_router-wrapper $RPM_BUILD_ROOT/%{_bindir}/trust_router-wrapper
+
+# As we're building an RPM, we don't need the init scripts etc. in /usr/share
+rm -rf $RPM_BUILD_ROOT/%{_datadir}/trust_router/redhat
+
 
 %clean
 rm -rf $RPM_BUILD_ROOT
 
 
+%pre
+getent group trustrouter > /dev/null || groupadd -r trustrouter
+getent passwd trustrouter > /dev/null || useradd -r -g trustrouter -d /var/lib/trustrouter -s /sbin/nologin -c "GSS-EAP Trust Router service account" trustrouter
+exit 0
+
+
 %post libs -p /sbin/ldconfig
 
 %postun libs -p /sbin/ldconfig
 
+%post
+# Data directory
+test -d /var/lib/trust_router ||mkdir /var/lib/trust_router
+chown trustrouter:trustrouter /var/lib/trust_router
+sqlite3 </usr/share/trust_router/schema.sql /var/lib/trust_router/keys
+chown trustrouter:trustrouter /var/lib/trust_router/keys
+chmod 660 /var/lib/trust_router/keys
+
+# Log Directory
+test -d /var/log/trust_router ||mkdir /var/log/trust_router
+chown root:trustrouter /var/log/trust_router
+chmod 770 /var/log/trust_router
+
+
 
 %files
 %defattr(-,root,root,-)
 %doc README
 %{_bindir}/*
+%{_datadir}/trust_router/schema.sql
+#/lib/systemd/system/tids.service
+
+%{_initrddir}/trust_router
+
+%config(noreplace) %{_sysconfdir}/sysconfig/trust_router
+
+%dir %attr(755,root,trustrouter) %{_sysconfdir}/trust_router
+%dir %attr(755,root,trustrouter) %{_sysconfdir}/trust_router/conf.d/
+%dir %attr(755,root,trustrouter) %{_sysconfdir}/trust_router/conf.d/default
+%dir %attr(755,root,trustrouter) %{_sysconfdir}/trust_router/conf.d/tr-test
+
+%attr(640,root,trustrouter) %config(noreplace) %{_sysconfdir}/trust_router/trusts.cfg
+%attr(640,root,trustrouter) %config(noreplace) %{_sysconfdir}/trust_router/conf.d/default/main.cfg
+%attr(640,root,trustrouter) %config(noreplace) %{_sysconfdir}/trust_router/conf.d/tr-test/main.cfg
+%attr(640,root,trustrouter) %config(noreplace) %{_sysconfdir}/trust_router/conf.d/default/trusts.cfg
+%attr(640,root,trustrouter) %config(noreplace) %{_sysconfdir}/trust_router/conf.d/tr-test/trusts.cfg
 
 %files libs
 %defattr(-,root,root,-)