X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=common%2Ftr_constraint.c;h=f9fcf6161dcd349aa6d89b22981a4d091fc3d216;hb=fc7fb82d2661d977e7bacb4ffe469f3857a06b63;hp=a15556667d041b340824d69090da9a27308aad0e;hpb=e9332953189a29c0c52f703e4a3717b6141306d9;p=trust_router.git diff --git a/common/tr_constraint.c b/common/tr_constraint.c index a155566..f9fcf61 100644 --- a/common/tr_constraint.c +++ b/common/tr_constraint.c @@ -32,41 +32,53 @@ * */ #include +#if JANSSON_VERSION_HEX < 0x020500 #include "jansson_iterators.h" +#endif #include #include #include -#include - -#include #include +#include +#include - +/** + * 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; + TR_CONSTRAINT *cons = talloc_get_type_abort(obj, TR_CONSTRAINT); - if (cons->type!=NULL) + if (cons->type) tr_free_name(cons->type); - for (ii=0; iimatches[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; iimatches[ii]=NULL; - talloc_set_destructor((void *)cons, tr_constraint_destructor); + TR_CONSTRAINT *cons = talloc(mem_ctx, TR_CONSTRAINT); + + if (cons != NULL) { + cons->type = 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,32 +88,73 @@ 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; - TR_CONSTRAINT *new=NULL; - int ii=0; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + TR_CONSTRAINT *new = NULL; - if (cons==NULL) - return NULL; + if (cons == NULL) + goto cleanup; - tmp_ctx=talloc_new(NULL); - new=tr_constraint_new(tmp_ctx); + new = tr_constraint_new(tmp_ctx); + if (new == NULL) + goto cleanup; - if (new!=NULL) { - new->type=tr_dup_name(cons->type); - for (ii=0; iimatches[ii]=tr_dup_name(cons->matches[ii]); - talloc_steal(mem_ctx, new); + new->type = tr_dup_name(cons->type); + if (new->type == NULL) { + new = NULL; + goto cleanup; } + 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) { +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; @@ -117,21 +170,22 @@ int tr_prefix_wildcard_match (const char *str, const char *wc_str) { if ('*' == wc_str[0]) { wc_post = &(wc_str[1]); wc_len--; - }else if (len != wc_len) + } else if (len != wc_len) return 0; if (wc_len > len) return 0; - - if (0 == strcmp(&(str[len-wc_len]), wc_post)) { + + if (0 == strcmp(&(str[len - wc_len]), wc_post)) { return 1; - } - else + } else return 0; - } +} -TR_CONSTRAINT_SET *tr_constraint_set_from_fline (TR_FLINE *fline) +/* 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; @@ -139,10 +193,10 @@ TR_CONSTRAINT_SET *tr_constraint_set_from_fline (TR_FLINE *fline) return NULL; if (fline->realm_cons) - tr_constraint_add_to_set((TR_CONSTRAINT_SET **)&cset, fline->realm_cons); + tr_constraint_add_to_set((TR_CONSTRAINT_SET **) &cset, fline->realm_cons); if (fline->domain_cons) - tr_constraint_add_to_set((TR_CONSTRAINT_SET **)&cset, fline->domain_cons); - + tr_constraint_add_to_set((TR_CONSTRAINT_SET **) &cset, fline->domain_cons); + return (TR_CONSTRAINT_SET *) cset; } @@ -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) +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,22 +228,27 @@ 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); - + /* Add the created object to the cset object */ json_array_append_new((json_t *) *cset, jcons); -} +} - int tr_constraint_set_validate(TR_CONSTRAINT_SET *cset) -{ +/* 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; json_t *set_member; - if (!json_is_array(json)){ + if (!json_is_array(json)) { tr_debug("Constraint_set is not an array"); return 0; } @@ -197,44 +259,50 @@ void tr_constraint_add_to_set (TR_CONSTRAINT_SET **cset, TR_CONSTRAINT *cons) tr_debug("Constraint member at %zu is not an object\n", i); return 0; } - json_object_foreach( set_member, key, value) { + 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; + 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; - } + 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) +/** + * 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) { - json_t *orig_cset = (json_t*) orig; - json_t *new_cs = NULL; + 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)) { + 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()); + new_cs = json_array(); + assert(new_cs); json_array_foreach(orig_cset, index, set_member) { - if (json_object_get( set_member, constraint_type)) + 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; } @@ -255,40 +323,39 @@ static void merge_constraints(json_t *constraint, const char *key) */ 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--; + 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) +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); + 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 { + 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); @@ -298,24 +365,25 @@ static json_t *constraint_intersect_internal( TR_CONSTRAINT_SET *constraints, * constraint type we return empty (no access) rather than universal * access.*/ if (!intersect) - continue; - result_loop: + 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; + 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; } } } @@ -326,33 +394,39 @@ static json_t *constraint_intersect_internal( TR_CONSTRAINT_SET *constraints, * 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) +TR_CONSTRAINT_SET *tr_constraint_set_intersect(TID_REQ *request, + TR_CONSTRAINT_SET *input) { - json_t *domain=NULL, *realm=NULL; + 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()); + 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); + 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) +/** 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, + tr_const_string **output, + size_t *output_len) { json_t *cset = (json_t *) constraints; json_t *member, *matches, *value;; @@ -372,8 +446,7 @@ int tr_constraint_set_get_match_strings( 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); + json_array_foreach(matches, index, value)(*output)[index] = json_string_value(value); *output_len = array_size; return 0; }