Fix typo, reorder methods in tr_aaa_server.c
[trust_router.git] / common / tr_constraint.c
index 37bc27e..f9fcf61 100644 (file)
  *
  */
 #include <jansson.h>
+#if JANSSON_VERSION_HEX < 0x020500
 #include "jansson_iterators.h"
+#endif
 #include <assert.h>
 #include <talloc.h>
 
 #include <tr_filter.h>
-#include <tr_debug.h>
-
-#include <trust_router/tr_constraint.h>
 #include <tid_internal.h>
+#include <tr_debug.h>
+#include <tr_constraint_internal.h>
 
-
+/**
+ * Helper for tr_constraint_destructor - calls tr_free_name on its first argument
+ *
+ * @param item void pointer to a TR_NAME
+ * @param cookie ignored
+ */
+static void constraint_destruct_helper(void *item, void *cookie)
+{
+  TR_NAME *name = (TR_NAME *) item;
+  tr_free_name(name);
+}
 static int tr_constraint_destructor(void *obj)
 {
   TR_CONSTRAINT *cons = talloc_get_type_abort(obj, TR_CONSTRAINT);
-  int ii = 0;
 
-  if (cons->type != NULL)
+  if (cons->type)
     tr_free_name(cons->type);
-  for (ii = 0; ii < TR_MAX_CONST_MATCHES; ii++) {
-    if (cons->matches[ii] != NULL)
-      tr_free_name(cons->matches[ii]);
-  }
+
+  if (cons->matches)
+    tr_list_foreach(cons->matches, constraint_destruct_helper, NULL);
+
   return 0;
 }
 
 TR_CONSTRAINT *tr_constraint_new(TALLOC_CTX *mem_ctx)
 {
   TR_CONSTRAINT *cons = talloc(mem_ctx, TR_CONSTRAINT);
-  int ii = 0;
 
   if (cons != NULL) {
     cons->type = NULL;
-    for (ii = 0; ii < TR_MAX_CONST_MATCHES; ii++)
-      cons->matches[ii] = NULL;
+    cons->matches = tr_list_new(cons);
+    if (cons->matches == NULL) {
+      talloc_free(cons);
+      return NULL;
+    }
     talloc_set_destructor((void *) cons, tr_constraint_destructor);
   }
   return cons;
@@ -76,30 +88,70 @@ void tr_constraint_free(TR_CONSTRAINT *cons)
   talloc_free(cons);
 }
 
+/**
+ * Helper for tr_constraint_dup - duplicates a TR_NAME and adds it as a TR_CONSTRAINT match
+ *
+ * No return value. If this succeeds, it will have added a new entry to the TR_CONSTRAINT
+ * match list. Check the length of that - you won't be able to tell whether the allocation
+ * of the duplicate TR_NAME or the addition to the list failed, but either of those is probably
+ * due to a memory allocation failure, in which case the system is probably crashing anyway.
+ *
+ * @param item void pointer to a TR_NAME to add as a match
+ * @param cookie void pointer to a TR_CONSTRAINT to add the match to
+ */
+static void cons_dup_helper(void *item, void *cookie)
+{
+  TR_CONSTRAINT *new_cons = talloc_get_type_abort(cookie, TR_CONSTRAINT);
+  TR_NAME *new_name = tr_dup_name((TR_NAME *) item);
+  if (new_name) {
+    /* check that new_name is added, free if it fails */
+    if (tr_constraint_add_match(new_cons, new_name) == NULL)
+      tr_free_name(new_name);
+  }
+}
+/**
+ * Duplicate a TR_CONSTRAINT
+ *
+ * @param mem_ctx talloc context for the result
+ * @param cons TR_CONSTRAINT to duplicate
+ * @return pointer to the new TR_CONSTRAINT, or NULL on error
+ */
 TR_CONSTRAINT *tr_constraint_dup(TALLOC_CTX *mem_ctx, TR_CONSTRAINT *cons)
 {
-  TALLOC_CTX *tmp_ctx = NULL;
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
   TR_CONSTRAINT *new = NULL;
-  int ii = 0;
 
   if (cons == NULL)
-    return NULL;
+    goto cleanup;
 
-  tmp_ctx = talloc_new(NULL);
   new = tr_constraint_new(tmp_ctx);
+  if (new == NULL)
+    goto cleanup;
+
+  new->type = tr_dup_name(cons->type);
+  if (new->type == NULL) {
+    new = NULL;
+    goto cleanup;
+  }
 
-  if (new != NULL) {
-    new->type = tr_dup_name(cons->type);
-    for (ii = 0; ii < TR_MAX_CONST_MATCHES; ii++)
-      new->matches[ii] = tr_dup_name(cons->matches[ii]);
-    talloc_steal(mem_ctx, new);
+  tr_list_foreach(cons->matches, cons_dup_helper, new); /* copies matches to new->matches */
+  /* check that we were successful - if we were, then the lists will be the same length */
+  if (tr_list_length(new->matches) != tr_list_length(cons->matches)) {
+    new = NULL;
+    goto cleanup; /* at least one dup or add failed */
   }
 
+  /* success */
+  talloc_steal(mem_ctx, new);
+
+cleanup:
   talloc_free(tmp_ctx);
   return new;
 }
 
-/* Returns TRUE (1) if the the string (str) matchs the wildcard string (wc_str), FALSE (0) if not.
+/* Returns TRUE (1) if the the string (str) matches the wildcard string (wc_str), FALSE (0) if not.
+ * Allows for a single '*' as the wildcard character if it is the first character. Leading white
+ * space is significant.
  */
 int tr_prefix_wildcard_match(const char *str, const char *wc_str)
 {
@@ -131,6 +183,8 @@ int tr_prefix_wildcard_match(const char *str, const char *wc_str)
     return 0;
 }
 
+/* This combines the two constraints in a filter line (TR_FLINE) into a single
+ * set with two constraints. */
 TR_CONSTRAINT_SET *tr_constraint_set_from_fline(TR_FLINE *fline)
 {
   json_t *cset = NULL;
@@ -152,13 +206,16 @@ TR_CONSTRAINT_SET *tr_constraint_set_from_fline(TR_FLINE *fline)
  *
  *     {cset: [{domain: [a.com, b.co.uk]},
  *             {realm: [c.net, d.org]}]}
+ *
+ * This routine takes a TR_CONSTRAINT, converts it to its JSON representation,
+ * and adds that to the TR_CONSTRAINT_SET.
  */
-
 void tr_constraint_add_to_set(TR_CONSTRAINT_SET **cset, TR_CONSTRAINT *cons)
 {
   json_t *jcons = NULL;
   json_t *jmatches = NULL;
-  int i = 0;
+  TR_NAME *this_match = NULL;
+  TR_CONSTRAINT_ITER iter = {0};
 
   if ((!cset) || (!cons))
     return;
@@ -171,8 +228,11 @@ void tr_constraint_add_to_set(TR_CONSTRAINT_SET **cset, TR_CONSTRAINT *cons)
   jmatches = json_array();
   jcons = json_object();
 
-  for (i = 0; ((i < TR_MAX_CONST_MATCHES) && (NULL != cons->matches[i])); i++) {
-    json_array_append_new(jmatches, json_string(cons->matches[i]->buf));
+  for (this_match = tr_constraint_iter_first(&iter, cons);
+       this_match != NULL;
+       this_match = tr_constraint_iter_next(&iter))
+  {
+    json_array_append_new(jmatches, tr_name_to_json_string(this_match));
   }
 
   json_object_set_new(jcons, cons->type->buf, jmatches);
@@ -181,6 +241,9 @@ void tr_constraint_add_to_set(TR_CONSTRAINT_SET **cset, TR_CONSTRAINT *cons)
   json_array_append_new((json_t *) *cset, jcons);
 }
 
+/* Test whether a JSON object has a valid structure
+ * to represent a constraint set.
+ */
 int tr_constraint_set_validate(TR_CONSTRAINT_SET *cset) {
   json_t *json = (json_t *) cset;
   size_t i;
@@ -216,7 +279,11 @@ int tr_constraint_set_validate(TR_CONSTRAINT_SET *cset) {
   return 1;
 }
 
-
+/**
+ * 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_CONSTRAINT_SET *tr_constraint_set_filter(TID_REQ *request,
                                             TR_CONSTRAINT_SET *orig,
                                             const char *constraint_type)
@@ -229,11 +296,13 @@ TR_CONSTRAINT_SET *tr_constraint_set_filter(TID_REQ *request,
     tr_debug ("tr_constraint_set_filter: not a valid constraint set\n");
     return NULL;
   }
-  assert (new_cs = json_array());
+  new_cs = json_array();
+  assert(new_cs);
   json_array_foreach(orig_cset, index, set_member) {
     if (json_object_get(set_member, constraint_type))
       json_array_append(new_cs, set_member);
   }
+  tid_req_cleanup_json(request, new_cs);
   return (TR_CONSTRAINT_SET *) new_cs;
 }
 
@@ -334,18 +403,25 @@ TR_CONSTRAINT_SET *tr_constraint_set_intersect(TID_REQ *request,
     domain = constraint_intersect_internal(input, "domain");
     realm = constraint_intersect_internal(input, "realm");
   }
-  assert(result = json_object());
+  result = json_object();
+  assert(result);
   if (domain)
     json_object_set_new(result, "domain", domain);
   if (realm)
     json_object_set_new(result, "realm", realm);
-  assert(result_array = json_array());
+  result_array = json_array();
+  assert(result_array);
   json_array_append_new(result_array, result);
   tid_req_cleanup_json(request, result_array);
   return (TR_CONSTRAINT_SET *) result_array;
 }
 
-
+/** 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_constraint_set_get_match_strings(TID_REQ *request,
                                         TR_CONSTRAINT_SET *constraints,
                                         const char *constraint_type,