Refactor TR_FLINE using GPtrArray
authorJennifer Richards <jennifer@painless-security.com>
Sat, 21 Apr 2018 06:04:27 +0000 (02:04 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Sat, 21 Apr 2018 06:04:27 +0000 (02:04 -0400)
common/tr_config_filters.c
common/tr_config_rp_clients.c
common/tr_filter.c
common/tr_filter_encoders.c
include/tr_filter.h

index 5be737f..063f812 100644 (file)
@@ -99,6 +99,7 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
   TALLOC_CTX *tmp_ctx = talloc_new(NULL);
   TR_FILTER *filt = NULL;
   TR_FLINE *fline = NULL;
+  TR_FSPEC *fspec = NULL;
   json_t *jfaction = NULL;
   json_t *jfline = NULL;
   json_t *jfspecs = NULL;
@@ -143,12 +144,6 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
       goto cleanup;
     }
 
-    if (TR_MAX_FILTER_SPECS < json_array_size(jfspecs)) {
-      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;
-    }
-
     fline = tr_fline_new(tmp_ctx);
     if (fline == NULL) {
       tr_debug("tr_cfg_parse_one_filter: Out of memory allocating filter line %d.", i + 1);
@@ -234,14 +229,14 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
       }
 
       /* allocate the filter spec */
-      if (NULL == (fline->specs[j] = tr_fspec_new(fline))) {
+      if (NULL == (fspec = tr_fspec_new(fline))) {
         tr_debug("tr_cfg_parse_one_filter: Out of memory.");
         *rc = TR_CFG_NOMEM;
         goto cleanup;
       }
 
       /* fill in the field */
-      if (NULL == (fline->specs[j]->field = tr_new_name(json_string_value(jfield)))) {
+      if (NULL == (fspec->field = tr_new_name(json_string_value(jfield)))) {
         tr_debug("tr_cfg_parse_one_filter: Out of memory.");
         *rc = TR_CFG_NOMEM;
         goto cleanup;
@@ -254,7 +249,7 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
           *rc = TR_CFG_NOMEM;
           goto cleanup;
         }
-        tr_fspec_add_match(fline->specs[j], name);
+        tr_fspec_add_match(fspec, name);
       } else {
         /* jmatch is an array (we checked earlier) */
         json_array_foreach(jmatch, k, this_jmatch) {
@@ -263,23 +258,28 @@ static TR_FILTER *tr_cfg_parse_one_filter(TALLOC_CTX *mem_ctx, json_t *jfilt, TR
             *rc = TR_CFG_NOMEM;
             goto cleanup;
           }
-          tr_fspec_add_match(fline->specs[j], name);
+          tr_fspec_add_match(fspec, name);
         }
       }
-      if (!tr_filter_validate_spec_field(ftype, fline->specs[j])){
+      if (!tr_filter_validate_spec_field(ftype, fspec)){
         tr_debug("tr_cfg_parse_one_filter: Invalid filter field \"%.*s\" for %s filter, spec %d, filter %d.",
-                 fline->specs[j]->field->len,
-                 fline->specs[j]->field->buf,
+                 fspec->field->len,
+                 fspec->field->buf,
                  tr_filter_type_to_string(filt->type),
                  i, j);
         *rc = TR_CFG_ERROR;
         goto cleanup;
       }
+
+      if(tr_fline_add_spec(fline, fspec) == NULL) {
+        tr_debug("tr_cfg_parse_one_filter: Unable to add spec %d to line %d of %s filter.",
+                 j, i, tr_filter_type_to_string(filt->type));
+      }
     }
 
     if (NULL == tr_filter_add_line(filt, fline)) {
       tr_debug("tr_cfg_parse_one_filter: Error adding line %d for %s filter",
-               i+1, tr_filter_type_to_string(filt->type));
+               i, tr_filter_type_to_string(filt->type));
       *rc = TR_CFG_NOMEM;
       goto cleanup;
     }
index 3487cb7..f12e42e 100644 (file)
@@ -114,6 +114,7 @@ static TR_FILTER_SET *tr_cfg_default_filters(TALLOC_CTX *mem_ctx, TR_NAME *realm
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_FILTER *filt=NULL;
   TR_FLINE *fline = NULL;
+  TR_FSPEC *fspec = NULL;
   TR_FILTER_SET *filt_set=NULL;
   TR_CONSTRAINT *cons=NULL;
   TR_NAME *name=NULL;
@@ -157,8 +158,9 @@ static TR_FILTER_SET *tr_cfg_default_filters(TALLOC_CTX *mem_ctx, TR_NAME *realm
   }
 
   fline->action=TR_FILTER_ACTION_ACCEPT;
-  fline->specs[0]=tr_fspec_new(fline);
-  fline->specs[0]->field=n_rp_realm_1;
+  
+  fspec=tr_fspec_new(tmp_ctx);
+  fspec->field=n_rp_realm_1;
   n_rp_realm_1=NULL; /* we don't own this name any more */
 
   name=tr_dup_name(realm);
@@ -167,12 +169,18 @@ static TR_FILTER_SET *tr_cfg_default_filters(TALLOC_CTX *mem_ctx, TR_NAME *realm
     *rc=TR_CFG_NOMEM;
     goto cleanup;
   }
-  tr_fspec_add_match(fline->specs[0], name);
+  tr_fspec_add_match(fspec, name);
   name=NULL; /* we no longer own the name */
 
+  if (tr_fline_add_spec(fline, fspec) == NULL) {
+    tr_debug("tr_cfg_default_filters: could not add first spec to filter line");
+    *rc = TR_CFG_NOMEM;
+    goto cleanup;
+  }
+
   /* now do the wildcard name */
-  fline->specs[1]=tr_fspec_new(fline);
-  fline->specs[1]->field=n_rp_realm_2;
+  fspec=tr_fspec_new(tmp_ctx);
+  fspec->field=n_rp_realm_2;
   n_rp_realm_2=NULL; /* we don't own this name any more */
 
   if (NULL==(name=tr_name_cat(n_prefix, realm))) {
@@ -181,9 +189,15 @@ static TR_FILTER_SET *tr_cfg_default_filters(TALLOC_CTX *mem_ctx, TR_NAME *realm
     goto cleanup;
   }
 
-  tr_fspec_add_match(fline->specs[1], name);
+  tr_fspec_add_match(fspec, name);
   name=NULL; /* we no longer own the name */
 
+  if (tr_fline_add_spec(fline, fspec) == NULL) {
+    tr_debug("tr_cfg_default_filters: could not add second spec to filter line");
+    *rc = TR_CFG_NOMEM;
+    goto cleanup;
+  }
+
   /* domain constraint */
   if (NULL==(cons=tr_constraint_new(fline))) {
     tr_debug("tr_cfg_default_filters: could not allocate domain constraint.");
index 113062e..828c7c4 100644 (file)
@@ -411,14 +411,15 @@ int tr_filter_apply(TR_FILTER_TARGET *target,
   TALLOC_CTX *tmp_ctx = talloc_new(NULL);
   TR_FILTER_ITER *filt_iter = tr_filter_iter_new(tmp_ctx);
   TR_FLINE *this_fline = NULL;
-  unsigned int jj=0;
+  TR_FLINE_ITER *fline_iter = tr_fline_iter_new(tmp_ctx);
+  TR_FSPEC *this_fspec = NULL;
   int retval=TR_FILTER_NO_MATCH;
 
   /* Default action is reject */
   *out_action = TR_FILTER_ACTION_REJECT;
 
   /* Validate filter */
-  if ((filt_iter == NULL) || (filt==NULL) || (filt->type==TR_FILTER_TYPE_UNKNOWN)) {
+  if ((filt_iter == NULL) || (fline_iter == NULL) || (filt==NULL) || (filt->type==TR_FILTER_TYPE_UNKNOWN)) {
     talloc_free(tmp_ctx);
     return TR_FILTER_NO_MATCH;
   }
@@ -430,19 +431,19 @@ int tr_filter_apply(TR_FILTER_TARGET *target,
     /* Assume we are going to succeed. If any specs fail to match, we'll set
      * this to TR_FILTER_NO_MATCH. */
     retval=TR_FILTER_MATCH;
-    for (jj=0; jj<TR_MAX_FILTER_SPECS; jj++) {
-      /* skip empty specs (these shouldn't really happen either) */
-      if (this_fline->specs[jj]==NULL)
-        continue;
-
-      if (!tr_fspec_matches(this_fline->specs[jj], filt->type, target)) {
+    this_fspec = tr_fline_iter_first(fline_iter, this_fline);
+    while(this_fspec) {
+      if (!tr_fspec_matches(this_fspec, filt->type, target)) {
         retval=TR_FILTER_NO_MATCH; /* set this in case this is the last filter line */
         break; /* give up on this filter line */
       }
+    this_fspec = tr_fline_iter_next(fline_iter);
     }
 
     if (retval==TR_FILTER_MATCH)
       break;
+
+    this_fline = tr_filter_iter_next(filt_iter);
   }
 
   if (retval==TR_FILTER_MATCH) {
@@ -556,17 +557,40 @@ void tr_fline_free(TR_FLINE *fline)
   talloc_free(fline);
 }
 
+TR_FSPEC *tr_fline_add_spec(TR_FLINE *fline, TR_FSPEC *spec)
+{
+  guint old_len = fline->specs->len;
+  g_ptr_array_add(fline->specs, spec);
+
+  if (old_len == fline->specs->len)
+    return NULL; /* failed to add */
+
+  talloc_steal(fline, spec);
+  return spec;
+}
+
+static int tr_fline_destructor(void *object)
+{
+  TR_FLINE *fline = talloc_get_type_abort(object, TR_FLINE);
+  if (fline->specs)
+    g_ptr_array_unref(fline->specs);
+  return 0;
+}
+
 TR_FLINE *tr_fline_new(TALLOC_CTX *mem_ctx)
 {
   TR_FLINE *fl = talloc(mem_ctx, TR_FLINE);
-  int ii = 0;
 
   if (fl != NULL) {
     fl->action = TR_FILTER_ACTION_UNKNOWN;
     fl->realm_cons = NULL;
     fl->domain_cons = NULL;
-    for (ii = 0; ii < TR_MAX_FILTER_SPECS; ii++)
-      fl->specs[ii] = NULL;
+    fl->specs = g_ptr_array_new();
+    if (fl->specs == NULL) {
+      talloc_free(fl);
+      return NULL;
+    }
+    talloc_set_destructor((void *)fl, tr_fline_destructor);
   }
   return fl;
 }
@@ -650,6 +674,16 @@ void tr_filter_iter_free(TR_FILTER_ITER *iter)
   talloc_free(iter);
 }
 
+TR_FLINE *tr_filter_iter_first(TR_FILTER_ITER *iter, TR_FILTER *filter)
+{
+  if (!iter || !filter)
+    return NULL;
+
+  iter->filter = filter;
+  iter->ii = 0;
+  return tr_filter_iter_next(iter);
+}
+
 TR_FLINE *tr_filter_iter_next(TR_FILTER_ITER *iter)
 {
   if (!iter)
@@ -660,14 +694,38 @@ TR_FLINE *tr_filter_iter_next(TR_FILTER_ITER *iter)
   return NULL;
 }
 
-TR_FLINE *tr_filter_iter_first(TR_FILTER_ITER *iter, TR_FILTER *filter)
+TR_FLINE_ITER *tr_fline_iter_new(TALLOC_CTX *mem_ctx)
 {
-  if (!iter || !filter)
+  TR_FLINE_ITER *iter = talloc(mem_ctx, TR_FLINE_ITER);
+  if (iter) {
+    iter->fline = NULL;
+  }
+  return iter;
+}
+
+void tr_fline_iter_free(TR_FLINE_ITER *iter)
+{
+  talloc_free(iter);
+}
+
+TR_FSPEC * tr_fline_iter_first(TR_FLINE_ITER *iter, TR_FLINE *fline)
+{
+  if (!iter || !fline)
     return NULL;
 
-  iter->filter = filter;
+  iter->fline = fline;
   iter->ii = 0;
-  return tr_filter_iter_next(iter);
+  return tr_fline_iter_next(iter);
+}
+
+TR_FSPEC * tr_fline_iter_next(TR_FLINE_ITER *iter)
+{
+  if (!iter)
+    return NULL;
+
+  if (iter->ii < iter->fline->specs->len)
+    return g_ptr_array_index(iter->fline->specs, iter->ii++);
+  return NULL;
 }
 
 TR_FSPEC_ITER *tr_fspec_iter_new(TALLOC_CTX *mem_ctx)
@@ -713,11 +771,12 @@ TR_NAME *tr_fspec_iter_next(TR_FSPEC_ITER *iter)
 int tr_filter_validate(TR_FILTER *filt)
 {
   TALLOC_CTX *tmp_ctx = talloc_new(NULL);
-  size_t jj=0;
   TR_FILTER_ITER *filt_iter = tr_filter_iter_new(tmp_ctx);
   TR_FLINE *this_fline = NULL;
+  TR_FLINE_ITER *fline_iter = tr_fline_iter_new(tmp_ctx);
+  TR_FSPEC *this_fspec = NULL;
   
-  if (!filt) {
+  if ((!filt) || (!filt_iter) || (!fline_iter)) {
     talloc_free(tmp_ctx);
     return 0;
   }
@@ -748,20 +807,19 @@ int tr_filter_validate(TR_FILTER *filt)
         return 0;
     }
 
-    for (jj=0; jj<TR_MAX_FILTER_SPECS; jj++) {
-      if (this_fline->specs[jj]==NULL)
-        continue; /* an empty filter spec is valid */
-
-      if (!tr_filter_validate_spec_field(filt->type, this_fline->specs[jj])) {
+    this_fspec = tr_fline_iter_first(fline_iter, this_fline);
+    while(this_fspec) {
+      if (!tr_filter_validate_spec_field(filt->type, this_fspec)) {
         talloc_free(tmp_ctx);
         return 0;
       }
 
       /* check that at least one match is defined*/
-      if (this_fline->specs[jj]->match->len == 0) {
+      if (this_fspec->match->len == 0) {
         talloc_free(tmp_ctx);
         return 0;
       }
+      this_fspec = tr_fline_iter_next(fline_iter);
     }
     this_fline = tr_filter_iter_next(filt_iter);
   }
index 0c53174..d6dd73f 100644 (file)
@@ -133,6 +133,34 @@ cleanup:
   return retval;
 }
 
+static json_t *tr_fspecs_to_json_array(TR_FLINE *fline)
+{
+  json_t *jarray = json_array();
+  json_t *retval = NULL;
+  TR_FLINE_ITER *iter = tr_fline_iter_new(NULL);
+  TR_FSPEC *this_fspec = NULL;
+
+  if ((jarray == NULL) || (iter == NULL))
+    goto cleanup;
+
+  this_fspec = tr_fline_iter_first(iter, fline);
+  while(this_fspec) {
+    ARRAY_APPEND_OR_FAIL(jarray, tr_fspec_to_json(this_fspec));
+    this_fspec = tr_fline_iter_next(iter);
+  }
+  /* success */
+  retval = jarray;
+  json_incref(retval);
+
+cleanup:
+  if (jarray)
+    json_decref(jarray);
+  if (iter)
+    tr_fline_iter_free(iter);
+
+  return retval;
+}
+
 static json_t *tr_fline_to_json(TR_FLINE *fline)
 {
   json_t *fline_json = NULL;
@@ -145,9 +173,7 @@ static json_t *tr_fline_to_json(TR_FLINE *fline)
   OBJECT_SET_OR_FAIL(fline_json, "action",
                      json_string( (fline->action == TR_FILTER_ACTION_ACCEPT) ? "accept" : "reject"));
   OBJECT_SET_OR_FAIL(fline_json, "specs",
-                     items_to_json_array((void **)fline->specs,
-                                         (ITEM_ENCODER_FUNC *) tr_fspec_to_json,
-                                         TR_MAX_FILTER_SPECS));
+                     tr_fspecs_to_json_array(fline));
   if (fline->realm_cons) {
     OBJECT_SET_OR_FAIL(fline_json, "realm_constraints",
                        items_to_json_array((void **) fline->realm_cons->matches,
index ccec738..d5e2b86 100644 (file)
@@ -44,8 +44,6 @@
 #include <trust_router/tid.h>
 #include <trust_router/trp.h>
 
-#define TR_MAX_FILTER_SPECS 8
-
 /* Filter actions */
 typedef enum tr_filter_action {
   TR_FILTER_ACTION_REJECT = 0,
@@ -77,11 +75,16 @@ typedef struct tr_fspec_iter {
 
 typedef struct tr_fline {
   TR_FILTER_ACTION action;
-  TR_FSPEC *specs[TR_MAX_FILTER_SPECS];
+  GPtrArray *specs;
   TR_CONSTRAINT *realm_cons;
   TR_CONSTRAINT *domain_cons;
 } TR_FLINE;
 
+typedef struct tr_fline_iter {
+  TR_FLINE *fline;
+  guint ii;
+} TR_FLINE_ITER;
+
 typedef struct tr_filter {
   TR_FILTER_TYPE type;
   GPtrArray *lines;
@@ -123,13 +126,11 @@ TR_FILTER_TYPE tr_filter_get_type(TR_FILTER *filt);
 TR_FLINE *tr_filter_add_line(TR_FILTER *filt, TR_FLINE *line);
 
 TR_FLINE *tr_fline_new(TALLOC_CTX *mem_ctx);
-
 void tr_fline_free(TR_FLINE *fline);
+TR_FSPEC *tr_fline_add_spec(TR_FLINE *fline, TR_FSPEC *spec);
 
 TR_FSPEC *tr_fspec_new(TALLOC_CTX *mem_ctx);
-
 void tr_fspec_free(TR_FSPEC *fspec);
-
 TR_NAME *tr_fspec_add_match(TR_FSPEC *fspec, TR_NAME *match);
 
 int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, TR_FILTER_TARGET *target);
@@ -139,6 +140,11 @@ void tr_filter_iter_free(TR_FILTER_ITER *iter);
 TR_FLINE *tr_filter_iter_first(TR_FILTER_ITER *iter, TR_FILTER *filter);
 TR_FLINE *tr_filter_iter_next(TR_FILTER_ITER *iter);
 
+TR_FLINE_ITER *tr_fline_iter_new(TALLOC_CTX *mem_ctx);
+void tr_fline_iter_free(TR_FLINE_ITER *iter);
+TR_FSPEC * tr_fline_iter_first(TR_FLINE_ITER *iter, TR_FLINE *fline);
+TR_FSPEC * tr_fline_iter_next(TR_FLINE_ITER *iter);
+
 TR_FSPEC_ITER *tr_fspec_iter_new(TALLOC_CTX *mem_ctx);
 void tr_fspec_iter_free(TR_FSPEC_ITER *iter);
 TR_NAME *tr_fspec_iter_first(TR_FSPEC_ITER *iter, TR_FSPEC *fspec);