Parse RP clients from new-style configuration files.
authorJennifer Richards <jennifer@painless-security.com>
Fri, 19 Aug 2016 20:41:10 +0000 (16:41 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Fri, 19 Aug 2016 20:41:10 +0000 (16:41 -0400)
common/cfg_test/cfg_test.c
common/tr_config.c
common/tr_constraint.c
common/tr_rp.c
include/tr_rp.h

index 896b8ac..be2085b 100644 (file)
@@ -65,6 +65,23 @@ static int verify_idp_cfg(TR_CFG *cfg)
   return 0;
 }
 
+static int verify_rp_cfg(TR_CFG *cfg)
+{
+  int ii=0;
+  TR_NAME *name=NULL;
+
+  assert(cfg!=NULL);
+  assert(cfg->rp_clients!=NULL);
+  assert(cfg->rp_clients->next==NULL);
+  assert(cfg->rp_clients->comm_next==NULL);
+  for (ii=1; ii<TR_MAX_GSS_NAMES; ii++)
+    assert(cfg->rp_clients->gss_names[ii]==NULL);
+  assert(cfg->rp_clients->gss_names[0]!=NULL);
+  name=tr_new_name("gss@example.com");
+  assert(tr_name_cmp(name, cfg->rp_clients->gss_names[0])==0);
+  return 0;
+}
+
 int main(void)
 {
   TALLOC_CTX *mem_ctx=talloc_new(NULL);
@@ -96,14 +113,56 @@ int main(void)
     break;
   }
 
-  printf("Verifying parse results... ");
+  printf("Verifying IDP parse results... ");
   if (verify_idp_cfg(cfg)!=0) {
     printf("Error!\n");
     exit(-1);
   }
   printf("success!\n");
 
+  printf("Verifying RP parse results... ");
+  if (verify_rp_cfg(cfg)!=0) {
+    printf("Error!\n");
+    exit(-1);
+  }
+  printf("success!\n");
+
   talloc_report_full(mem_ctx, stderr);
   tr_cfg_free(cfg);
+
+  printf("Cleared configuration for next test.\n\n");
+
+  cfg=tr_cfg_new(mem_ctx);
+  
+  printf("Parsing rp.cfg.\n");
+  rc=tr_cfg_parse_one_config_file(cfg, "rp.cfg");
+  switch(rc) {
+  case TR_CFG_SUCCESS:
+    tr_debug("main: TR_CFG_SUCCESS");
+    break;
+  case TR_CFG_ERROR:
+    tr_debug("main: TR_CFG_ERROR");
+    break;
+  case TR_CFG_BAD_PARAMS:
+    tr_debug("main: TR_CFG_BAD_PARAMS");
+    break;
+  case TR_CFG_NOPARSE:
+    tr_debug("main: TR_CFG_NOPARSE");
+    break;
+  case TR_CFG_NOMEM:
+    tr_debug("main: TR_CFG_NOMEM");
+    break;
+  }
+
+#if 0
+  printf("Verifying RP parse results... ");
+  if (verify_rp_cfg(cfg)!=0) {
+    printf("Error!\n");
+    exit(-1);
+  }
+  printf("success!\n");
+#endif
+
+  talloc_free(mem_ctx);
   return 0;
 }
index cb956c1..bfe8fe8 100644 (file)
@@ -362,7 +362,7 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
       goto cleanup;
     }
  
-    if ((NULL==(jfspecs=json_object_get(json_array_get(jfilt, i), "filter_specs"))) ||
+    if ((NULL==(jfspecs=json_object_get(json_array_get(jfilt, i), "specs"))) ||
         (!json_is_array(jfspecs)) ||
         (0==json_array_size(jfspecs))) {
       tr_debug("tr_cfg_parse_one_filter: Error parsing filter specs.");
@@ -371,7 +371,7 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
     }
   
     if (TR_MAX_FILTER_SPECS < json_array_size(jfspecs)) {
-      tr_debug("tr_cfg_parse_one_filter: Filter has too many filter_specs, maximimum of %d.", TR_MAX_FILTER_SPECS);
+      tr_debug("tr_cfg_parse_one_filter: Filter has too many specs, maximimum of %d.", TR_MAX_FILTER_SPECS);
       *rc=TR_CFG_NOPARSE;
       goto cleanup;
     }
@@ -413,52 +413,51 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
         }
       }
     }
-  }
 
-  if (NULL!=(jdc=json_object_get(json_array_get(jfilt, i), "domain_constraints"))) {
-    if (!json_is_array(jdc)) {
-      tr_err("tr_cfg_parse_one_filter: cannot parse domain_constraints, not an array.");
-      *rc=TR_CFG_NOPARSE;
-      goto cleanup;
-    } else if (json_array_size(jdc)>TR_MAX_CONST_MATCHES) {
-      tr_err("tr_cfg_parse_one_filter: domain_constraints has too many entries, maximum of %d.",
-             TR_MAX_CONST_MATCHES);
-      *rc=TR_CFG_NOPARSE;
-      goto cleanup;
-    } else if (json_array_size(jdc)>0) {
-      if (NULL==(filt->lines[i]->domain_cons=tr_cfg_parse_one_constraint(filt->lines[i], "domain", jdc, rc))) {
-        tr_debug("tr_cfg_parse_one_filter: Error parsing domain constraint");
+    if (NULL!=(jdc=json_object_get(json_array_get(jfilt, i), "domain_constraints"))) {
+      if (!json_is_array(jdc)) {
+        tr_err("tr_cfg_parse_one_filter: cannot parse domain_constraints, not an array.");
         *rc=TR_CFG_NOPARSE;
         goto cleanup;
+      } else if (json_array_size(jdc)>TR_MAX_CONST_MATCHES) {
+        tr_err("tr_cfg_parse_one_filter: domain_constraints has too many entries, maximum of %d.",
+               TR_MAX_CONST_MATCHES);
+        *rc=TR_CFG_NOPARSE;
+        goto cleanup;
+      } else if (json_array_size(jdc)>0) {
+        if (NULL==(filt->lines[i]->domain_cons=tr_cfg_parse_one_constraint(filt->lines[i], "domain", jdc, rc))) {
+          tr_debug("tr_cfg_parse_one_filter: Error parsing domain constraint");
+          *rc=TR_CFG_NOPARSE;
+          goto cleanup;
+        }
       }
     }
-  }
 
-  /*For each filter spec within the filter line... */
-  for (j=0; j <json_array_size(jfspecs); j++) {
-    if ((NULL==(jffield=json_object_get(json_array_get(jfspecs, j), "field"))) ||
-        (!json_is_string(jffield)) ||
-        (NULL==(jfmatch=json_object_get(json_array_get(jfspecs, j), "match"))) ||
-        (!json_is_string(jfmatch))) {
-      tr_debug("tr_cfg_parse_one_filter: Error parsing filter field and match for filter spec %d, filter line %d.", i, j);
-      *rc=TR_CFG_NOPARSE;
-      goto cleanup;
-    }
+    /*For each filter spec within the filter line... */
+    for (j=0; j <json_array_size(jfspecs); j++) {
+      if ((NULL==(jffield=json_object_get(json_array_get(jfspecs, j), "field"))) ||
+          (!json_is_string(jffield)) ||
+          (NULL==(jfmatch=json_object_get(json_array_get(jfspecs, j), "match"))) ||
+          (!json_is_string(jfmatch))) {
+        tr_debug("tr_cfg_parse_one_filter: Error parsing filter field and match for filter spec %d, filter line %d.", i, j);
+        *rc=TR_CFG_NOPARSE;
+        goto cleanup;
+      }
 
-    if (NULL==(filt->lines[i]->specs[j]=tr_fspec_new(filt->lines[i]))) {
-      tr_debug("tr_cfg_parse_one_filter: Out of memory.");
-      *rc=TR_CFG_NOMEM;
-      goto cleanup;
-    }
+      if (NULL==(filt->lines[i]->specs[j]=tr_fspec_new(filt->lines[i]))) {
+        tr_debug("tr_cfg_parse_one_filter: Out of memory.");
+        *rc=TR_CFG_NOMEM;
+        goto cleanup;
+      }
 
-    if ((NULL==(filt->lines[i]->specs[j]->field=tr_new_name(json_string_value(jffield)))) ||
+      if ((NULL==(filt->lines[i]->specs[j]->field=tr_new_name(json_string_value(jffield)))) ||
           (NULL==(filt->lines[i]->specs[j]->match=tr_new_name(json_string_value(jfmatch))))) {
-      tr_debug("tr_cfg_parse_one_filter: Out of memory.");
-      *rc=TR_CFG_NOMEM;
-      goto cleanup;
+        tr_debug("tr_cfg_parse_one_filter: Out of memory.");
+        *rc=TR_CFG_NOMEM;
+        goto cleanup;
+      }
     }
   }
-  
   *rc=TR_CFG_SUCCESS;
   talloc_steal(mem_ctx, filt);
   
@@ -467,6 +466,49 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
   return filt;
 }
 
+static TR_FILTER *tr_cfg_parse_filters(TALLOC_CTX *mem_ctx, json_t *jfilts, TR_CFG_RC *rc)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  json_t *jfilt;
+  TR_FILTER *filt=NULL;
+  int ii=0;
+
+  *rc=TR_CFG_ERROR;
+
+  /* no filters */
+  if (jfilts==NULL) {
+    *rc=TR_CFG_SUCCESS;
+    goto cleanup;
+  }
+
+  jfilt=json_object_get(jfilts, "tid_inbound");
+  if (jfilt!=NULL) {
+    filt=tr_cfg_parse_one_filter(tmp_ctx, jfilt, TR_FILTER_TYPE_TID_INCOMING, rc);
+    if (*rc!=TR_CFG_SUCCESS) {
+      tr_debug("tr_cfg_parse_filters: Error parsing tid_inbound filter.");
+      *rc=TR_CFG_NOPARSE;
+      goto cleanup;
+    }
+  } else {
+    tr_debug("tr_cfg_parse_filters: Unknown filter types in filter block.");
+    *rc=TR_CFG_NOPARSE;
+    goto cleanup;
+  }
+  
+  *rc=TR_CFG_SUCCESS;
+
+ cleanup:
+  if (*rc==TR_CFG_SUCCESS)
+    talloc_steal(mem_ctx, filt);
+  else {
+    talloc_free(filt);
+    filt=NULL;
+  }
+
+  talloc_free(tmp_ctx);
+  return filt;
+}
+
 static TR_AAA_SERVER *tr_cfg_parse_one_aaa_server(TALLOC_CTX *mem_ctx, json_t *jaddr, TR_CFG_RC *rc)
 {
   TR_AAA_SERVER *aaa = NULL;
@@ -659,10 +701,6 @@ static TR_IDP_REALM *tr_cfg_parse_one_idp_realm(TALLOC_CTX *mem_ctx, json_t *jre
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_IDP_REALM *realm=NULL;
-  json_t *jremote=NULL;
-  json_t *jscfg=NULL;
-  json_t *jsrvrs=NULL;
-  json_t *japcs=NULL;
   TR_CFG_RC call_rc=TR_CFG_ERROR;
 
   *rc=TR_CFG_ERROR; /* default to error if not set */
@@ -761,6 +799,143 @@ cleanup:
   return realms;
 }
 
+static TR_CFG_RC tr_cfg_parse_gss_names(TR_RP_CLIENT *client, json_t *jgss_names)
+{
+  json_t *jname=NULL;
+  int ii=0;
+  TR_NAME *name=NULL;
+
+  if ((client==NULL) || (jgss_names==NULL)) {
+    tr_err("tr_cfg_parse_gss_names: Bad parameters.");
+    return TR_CFG_BAD_PARAMS;
+  }
+
+  if (!json_is_array(jgss_names)) {
+    tr_err("tr_cfg_parse_gss_names: gss_names not an array.");
+    return TR_CFG_NOPARSE;
+  }
+
+  for (ii=0; ii<json_array_size(jgss_names); ii++) {
+    jname=json_array_get(jgss_names, ii);
+    if (!json_is_string(jname)) {
+      tr_err("tr_cfg_parse_gss_names: Encountered non-string gss name.");
+      return TR_CFG_NOPARSE;
+    }
+    name=tr_new_name(json_string_value(jname));
+    if (name==NULL) {
+      tr_err("tr_cfg_parse_gss_names: Out of memory allocating gss name.");
+      return TR_CFG_NOMEM;
+    }
+    if (tr_rp_client_add_gss_name(client, name)!=0) {
+      tr_free_name(name);
+      tr_err("tr_cfg_parse_gss_names: Unable to add gss name to RP client.");
+      return TR_CFG_ERROR;
+    }
+  }
+
+  return TR_CFG_SUCCESS;
+}
+
+/* parses rp client */
+static TR_RP_CLIENT *tr_cfg_parse_one_rp_client(TALLOC_CTX *mem_ctx, json_t *jrealm, TR_CFG_RC *rc)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TR_RP_CLIENT *client=NULL;
+  TR_CFG_RC call_rc=TR_CFG_ERROR;
+  TR_FILTER *new_filt=NULL;
+
+  *rc=TR_CFG_ERROR; /* default to error if not set */
+
+  if ((!jrealm) || (!rc)) {
+    tr_err("tr_cfg_parse_one_rp_client: Bad parameters.");
+    if (rc)
+      *rc=TR_CFG_BAD_PARAMS;
+    goto cleanup;
+  }
+
+  if (NULL==(client=tr_rp_client_new(tmp_ctx))) {
+    tr_err("tr_cfg_parse_one_rp_client: could not allocate rp client.");
+    *rc=TR_CFG_NOMEM;
+    goto cleanup;
+  }
+
+  call_rc=tr_cfg_parse_gss_names(client, json_object_get(jrealm, "gss_names"));
+  if (call_rc!=TR_CFG_SUCCESS) {
+    tr_err("tr_cfg_parse_one_rp_client: could not parse gss_names.");
+    *rc=TR_CFG_NOPARSE;
+    goto cleanup;
+  }
+
+  /* parse filters */
+  new_filt=tr_cfg_parse_filters(tmp_ctx, json_object_get(jrealm, "filters"), &call_rc);
+  if (call_rc!=TR_CFG_SUCCESS) {
+    tr_err("tr_cfg_parse_one_rp_client: could not parse filters.");
+    *rc=TR_CFG_NOPARSE;
+    goto cleanup;
+  }
+
+  tr_rp_client_set_filter(client, new_filt);
+  *rc=TR_CFG_SUCCESS;
+
+  cleanup:
+    if (*rc==TR_CFG_SUCCESS)
+      talloc_steal(mem_ctx, client);
+    else {
+      talloc_free(client);
+      client=NULL;
+    }
+
+    talloc_free(tmp_ctx);
+    return client;
+  }
+
+  /* Determine whether the realm is an RP realm */
+static int tr_cfg_is_rp_realm(json_t *jrealm)
+{
+  /* Check that we have a gss name. */
+  if (NULL != json_object_get(jrealm, "gss_names"))
+    return 1;
+  else
+    return 0;
+}
+
+/* Parse any rp clients in the j_realms object. Ignores other realms. */
+static TR_RP_CLIENT *tr_cfg_parse_rp_clients(TALLOC_CTX *mem_ctx, json_t *jrealms, TR_CFG_RC *rc)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TR_RP_CLIENT *clients=NULL;
+  TR_RP_CLIENT *new_client=NULL;
+  json_t *this_jrealm=NULL;
+  int ii=0;
+
+  *rc=TR_CFG_ERROR;
+  if ((jrealms==NULL) || (!json_is_array(jrealms))) {
+    tr_err("tr_cfg_parse_rp_clients: realms not an array");
+    *rc=TR_CFG_BAD_PARAMS;
+    goto cleanup;
+  }
+
+  for (ii=0; ii<json_array_size(jrealms); ii++) {
+    this_jrealm=json_array_get(jrealms, ii);
+    if (tr_cfg_is_rp_realm(this_jrealm)) {
+      new_client=tr_cfg_parse_one_rp_client(tmp_ctx, this_jrealm, rc);
+      if ((*rc)!=TR_CFG_SUCCESS) {
+        tr_err("tr_cfg_parse_rp_clients: error decoding realm entry %d", ii+1);
+        *rc=TR_CFG_NOPARSE;
+        goto cleanup;
+      }
+      clients=tr_rp_client_add(clients, new_client);
+    }
+  }
+  
+  *rc=TR_CFG_SUCCESS;
+  talloc_steal(mem_ctx, clients);
+
+cleanup:
+  talloc_free(tmp_ctx);
+  return clients;
+}
+
 /* takes a talloc context, but currently does not use it */
 static TR_NAME *tr_cfg_parse_org_name(TALLOC_CTX *mem_ctx, json_t *j_org, TR_CFG_RC *rc)
 {
@@ -839,7 +1014,7 @@ static TR_CFG_RC tr_cfg_parse_one_local_org(TR_CFG *trc, json_t *jlorg)
   json_t *j_org=NULL;
   json_t *j_realms=NULL;
   TR_IDP_REALM *new_idp_realms=NULL;
-  TR_RP_REALM *new_rp_realms=NULL;
+  TR_RP_CLIENT *new_rp_clients=NULL;
 
   tr_debug("tr_cfg_parse_one_local_org: parsing local organization");
 
@@ -868,11 +1043,9 @@ static TR_CFG_RC tr_cfg_parse_one_local_org(TR_CFG *trc, json_t *jlorg)
     if (rc!=TR_CFG_SUCCESS)
       goto cleanup;
 
-#if 0
-    new_rp_realms=tr_cfg_parse_rp_realms(tmp_ctx, j_realms, &rc);
+    new_rp_clients=tr_cfg_parse_rp_clients(tmp_ctx, j_realms, &rc);
     if (rc!=TR_CFG_SUCCESS)
       goto cleanup;
-#endif
   }
   retval=TR_CFG_SUCCESS;
   
@@ -884,10 +1057,11 @@ cleanup:
       talloc_steal(trc, trc->idp_realms); /* make sure the head is in the right context */
       trc->comms=tr_cfg_comm_idp_update(trc, trc->comms, new_idp_realms, &rc); /* put realm info in community table */
     }
-#if 0
-    if (new_rp_realms!=NULL)
-      trc->rp_realms=tr_rp_realm_add(trc->rp_realms, new_rp_realms); /* fixes talloc contexts */
-#endif
+
+    if (new_rp_clients!=NULL) {
+      trc->rp_clients=tr_rp_client_add(trc->rp_clients, new_rp_clients); /* fixes talloc contexts */
+      talloc_steal(trc, trc->rp_clients); /* make sure head is in the right context */
+    }
   }
 
   talloc_free(tmp_ctx);
index 2a14947..44a60ba 100644 (file)
@@ -64,7 +64,7 @@ TR_CONSTRAINT *tr_constraint_new(TALLOC_CTX *mem_ctx)
 
   if (cons!=NULL) {
     cons->type=NULL;
-    for (ii=0; ii<<TR_MAX_CONST_MATCHES; ii++)
+    for (ii=0; ii<TR_MAX_CONST_MATCHES; ii++)
       cons->matches[ii]=NULL;
     talloc_set_destructor((void *)cons, tr_constraint_destructor);
   }
index da11dc1..a132596 100644 (file)
 #include <tr_rp.h>
 #include <tr_debug.h>
 
-TR_RP_CLIENT *tr_rp_client_lookup(TR_RP_CLIENT *rp_clients, TR_NAME *gss_name) {
+static int tr_rp_client_destructor(void *obj)
+{
+  TR_RP_CLIENT *client=talloc_get_type_abort(obj, TR_RP_CLIENT);
+  int ii=0;
+
+  for (ii=0; ii<TR_MAX_GSS_NAMES; ii++) {
+    if (client->gss_names[ii]!=NULL)
+      tr_free_name(client->gss_names[ii]);
+  }
+  return 0;
+}
+
+TR_RP_CLIENT *tr_rp_client_new(TALLOC_CTX *mem_ctx)
+{
+  TR_RP_CLIENT *client=talloc(mem_ctx, TR_RP_CLIENT);
+  int ii=0;
+
+  if (client!=NULL) {
+    client->next=NULL;
+    client->comm_next=NULL;
+    for (ii=0; ii<TR_MAX_GSS_NAMES; ii++)
+      client->gss_names[ii]=NULL;
+    client->filter=NULL;
+    talloc_set_destructor((void *)client, tr_rp_client_destructor);
+  }
+  return client;
+}
+
+void tr_rp_client_free(TR_RP_CLIENT *client)
+{
+  talloc_free(client);
+}
+
+static TR_RP_CLIENT *tr_rp_client_tail(TR_RP_CLIENT *client)
+{
+  while (client!=NULL)
+    client=client->next;
+  return client;
+}
+
+TR_RP_CLIENT *tr_rp_client_add(TR_RP_CLIENT *clients, TR_RP_CLIENT *new)
+{
+  if (clients==NULL)
+    clients=new;
+  else {
+    tr_rp_client_tail(clients)->next=new;
+    while (new!=NULL) {
+      talloc_steal(clients, new); /* put it in the right context */
+      new=new->next;
+    }
+  }
+  return clients;
+}
+
+
+int tr_rp_client_add_gss_name(TR_RP_CLIENT *rp_client, TR_NAME *gss_name)
+{
+  int ii=0;
+  for (ii=0; ii<TR_MAX_GSS_NAMES; ii++) {
+    if (NULL==rp_client->gss_names[ii]) {
+      rp_client->gss_names[ii]=gss_name;
+      return 0; /* success */
+    }
+  }
+  return -1; /* error */
+}
+
+int tr_rp_client_set_filter(TR_RP_CLIENT *client, TR_FILTER *filt)
+{
+  if (client->filter!=NULL)
+    tr_filter_free(client->filter);
+  client->filter=filt;
+  talloc_steal(client, filt);
+  return 0; /* success */
+}
+
+TR_RP_CLIENT *tr_rp_client_lookup(TR_RP_CLIENT *rp_clients, TR_NAME *gss_name)
+{
   TR_RP_CLIENT *rp = NULL;
   int i = 0;
 
index ed74344..c991ff7 100644 (file)
@@ -35,6 +35,8 @@
 #ifndef TR_RP_H
 #define TR_RP_H
 
+#include <talloc.h>
+
 #include <tr_filter.h>
 
 #define TR_MAX_GSS_NAMES 5
@@ -53,6 +55,12 @@ typedef struct tr_rp_realm {
 } TR_RP_REALM;
 
 /* prototypes */
+TR_RP_CLIENT *tr_rp_client_new(TALLOC_CTX *mem_ctx);
+void tr_rp_client_free(TR_RP_CLIENT *client);
+TR_RP_CLIENT *tr_rp_client_add(TR_RP_CLIENT *clients, TR_RP_CLIENT *new);
+int tr_rp_client_add_gss_name(TR_RP_CLIENT *client, TR_NAME *name);
+int tr_rp_client_set_filter(TR_RP_CLIENT *client, TR_FILTER *filt);
+
 TR_RP_CLIENT *tr_rp_client_lookup(TR_RP_CLIENT *rp_clients, TR_NAME *gss_name);
 TR_RP_REALM *tr_rp_realm_add(TR_RP_REALM *head, TR_RP_REALM *new);
 #endif