From 12381c5facc9fcb55f8a8cc007811cf2254d87fa Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Mon, 12 Jun 2017 13:17:44 -0400 Subject: [PATCH] Code for testing the filters now works --- common/tests/filt_test.c | 184 +++++++++++++++++++--- common/tests/test-filters/filt-inforec-1-msg.json | 15 ++ common/tests/test-filters/filt-inforec-1.json | 53 +++++++ common/tests/test-filters/filt-tidreq-1-msg.json | 17 ++ common/tests/test-filters/filt-tidreq-1.json | 53 +++++++ common/tests/test-filters/filter-tests.json | 23 +++ common/tr_config.c | 119 +++++++------- common/tr_filter.c | 120 +++++++++++++- common/tr_rp.c | 12 +- include/tr_filter.h | 44 ++++-- include/tr_msg.h | 2 +- include/tr_rp.h | 4 +- include/trp_ptable.h | 6 +- tr/tr_tid.c | 5 +- trp/trp_ptable.c | 18 +-- 15 files changed, 551 insertions(+), 124 deletions(-) create mode 100644 common/tests/test-filters/filt-inforec-1-msg.json create mode 100644 common/tests/test-filters/filt-inforec-1.json create mode 100644 common/tests/test-filters/filt-tidreq-1-msg.json create mode 100644 common/tests/test-filters/filt-tidreq-1.json create mode 100644 common/tests/test-filters/filter-tests.json diff --git a/common/tests/filt_test.c b/common/tests/filt_test.c index c7eb028..7dc5094 100644 --- a/common/tests/filt_test.c +++ b/common/tests/filt_test.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include @@ -50,13 +52,13 @@ * @param filt_out Will point to the loaded filter on success * @return Return value from tr_cfg_parse_one_config_file() */ -int load_filter(const char *fname, TR_FILTER **filt_out) +int load_filter(const char *fname, TR_FILTER_SET **filts_out) { TR_CFG *cfg=tr_cfg_new(NULL); TR_CFG_RC rc=TR_CFG_ERROR; assert(fname); - assert(filt_out); + assert(filts_out); rc=tr_cfg_parse_one_config_file(cfg, fname); if (rc!=TR_CFG_SUCCESS) @@ -65,10 +67,10 @@ int load_filter(const char *fname, TR_FILTER **filt_out) /* Steal the filter from the first rp_client */ assert(cfg); assert(cfg->rp_clients); - assert(cfg->rp_clients->filter); - *filt_out=cfg->rp_clients->filter; - cfg->rp_clients->filter=NULL; /* can't use the _set_filter() because that will free the filter */ - talloc_steal(NULL, *filt_out); + assert(cfg->rp_clients->filters); + *filts_out=cfg->rp_clients->filters; + cfg->rp_clients->filters=NULL; /* can't use the _set_filter() because that will free the filter */ + talloc_steal(NULL, *filts_out); cleanup: tr_cfg_free(cfg); @@ -82,31 +84,174 @@ cleanup: */ int test_load_filter(void) { - TR_FILTER *filt=NULL; + TR_FILTER_SET *filts=NULL; - assert(TR_CFG_SUCCESS==load_filter(FILTER_PATH "valid-filt.json", &filt)); - assert(TR_CFG_NOPARSE==load_filter(FILTER_PATH "invalid-filt-repeated-key.json", &filt)); - assert(TR_CFG_ERROR==load_filter(FILTER_PATH "invalid-filt-unknown-field.json", &filt)); + assert(TR_CFG_SUCCESS==load_filter(FILTER_PATH "valid-filt.json", &filts)); + if (filts) tr_filter_set_free(filts); + filts=NULL; + assert(TR_CFG_NOPARSE==load_filter(FILTER_PATH "invalid-filt-repeated-key.json", &filts)); + if (filts) tr_filter_set_free(filts); + filts=NULL; + assert(TR_CFG_ERROR==load_filter(FILTER_PATH "invalid-filt-unknown-field.json", &filts)); + if (filts) tr_filter_set_free(filts); + filts=NULL; return 1; } -int test_trp_inforec_filter(TRP_INFOREC_TYPE type) +/** + * Read the first inforec from the TR_MSG encoded in JSON file named fname. + * + * @param fname Filename with path for TR_MSG JSON + * @return Pointer to the decoded inforec, or NULL on failure + */ +TRP_INFOREC *load_inforec(const char *fname) { - TRP_INFOREC *inforec=trp_inforec_new(NULL, type); - TR_FILTER *filt=tr_filter_new(NULL); + TR_MSG *msg=NULL; + TRP_UPD *upd=NULL; + TRP_INFOREC *inforec=NULL; + json_t *decoded=json_load_file(fname, JSON_REJECT_DUPLICATES|JSON_DISABLE_EOF_CHECK, NULL); + char *encoded=json_dumps(decoded, 0); /* silly way to read the file without mucking around */ + + assert(decoded); + json_decref(decoded); - assert(inforec); - assert(filt); + assert(encoded); + assert(msg=tr_msg_decode(encoded, strlen(encoded))); + assert(upd=tr_msg_get_trp_upd(msg)); + assert(inforec=trp_upd_get_inforec(upd)); + /* now remove the inforec from the update context */ + talloc_steal(NULL, inforec); + tr_msg_free_decoded(msg); + tr_msg_free_encoded(encoded); + return inforec; +} + +/* make this bigger than your message file */ +#define MAX_FILE_SIZE 20000 +TID_REQ *load_tid_req(const char *fname) +{ + TID_REQ *out=NULL; + TR_MSG *msg=NULL; + FILE *f=NULL; + char *msgbuf=NULL; + size_t msglen=0; + msgbuf=malloc(MAX_FILE_SIZE); + assert(msgbuf); + f=fopen(fname, "r"); + assert(f); + msglen=fread(msgbuf, 1, MAX_FILE_SIZE, f); + assert(msglen); + assert(feof(f)); + msg=tr_msg_decode(msgbuf, msglen); + free(msgbuf); + msgbuf=NULL; - return 1; + assert(msg); + assert(tr_msg_get_msg_type(msg)==TID_REQUEST); + + /* take the tid req out of the msg */ + out=tr_msg_get_req(msg); + tr_msg_set_req(msg, NULL); + assert(out); + + tr_msg_free_decoded(msg); + return out; } +/** + * Read a set of filters from a config JSON in filt_fname and test against the tid_req or inforec in target_fname. + * If expect==1, succeed if the target is accepted by the filter, otherwise succeed if it is rejected. + * Takes filters from the first rp_realm defined in the filter file and the first inforec or tid req from + * the target file. + * + * @param filt_fname Name of JSON file containing filters + * @param ftype Which type of filter to test + * @param target_fname Name of JSON file containing inforec + * @param expected_match 1 if we expect a match, 0 otherwise + * @param expected_action Expected action if the filter matches + * @return 1 if expected result is obtained, 0 or does not return otherwise + */ +int test_one_filter(const char *filt_fname, + TR_FILTER_TYPE ftype, + const char *target_fname, + int expected_match, + TR_FILTER_ACTION expected_action) +{ + void *target=NULL; + TR_FILTER_SET *filts=NULL; + TR_FILTER_ACTION action=TR_FILTER_ACTION_UNKNOWN; + + /* load filter for first test */ + assert(TR_CFG_SUCCESS==load_filter(filt_fname, &filts)); -int test_trp_filter(void) + /* load the target req or inforec */ + switch(ftype) { + case TR_FILTER_TYPE_TID_INBOUND: + target=load_tid_req(target_fname); + break; + + case TR_FILTER_TYPE_TRP_INBOUND: + case TR_FILTER_TYPE_TRP_OUTBOUND: + target=load_inforec(target_fname); + break; + + default: + printf("Unknown filter type.\n"); + } + assert(target); + + assert(expected_match==tr_filter_apply(target, tr_filter_set_get(filts, ftype), NULL, &action)); + if (expected_match==TR_FILTER_MATCH) + assert(action==expected_action); + + tr_filter_set_free(filts); + switch(ftype) { + case TR_FILTER_TYPE_TID_INBOUND: + tid_req_free((TID_REQ *)target); + break; + + case TR_FILTER_TYPE_TRP_INBOUND: + case TR_FILTER_TYPE_TRP_OUTBOUND: + trp_inforec_free((TRP_INFOREC *)target); + break; + + default: + printf("Unknown filter type.\n"); + } + return 1; +} + +int test_filter(void) { - assert(test_trp_inforec_filter(TRP_INFOREC_TYPE_ROUTE)); - assert(test_trp_inforec_filter(TRP_INFOREC_TYPE_COMMUNITY)); + json_t *test_list=json_load_file(FILTER_PATH "filter-tests.json", JSON_DISABLE_EOF_CHECK, NULL); + json_t *this; + size_t ii; + const char *filt_file, *target_file; + TR_FILTER_TYPE ftype; + int expect_match; + TR_FILTER_ACTION action; + + json_array_foreach(test_list, ii, this) { + printf("Running filter test case: %s\n", json_string_value(json_object_get(this, "test label"))); + fflush(stdout); + + filt_file=json_string_value(json_object_get(this, "filter file")); + ftype=tr_filter_type_from_string(json_string_value(json_object_get(this, "filter type"))); + target_file=json_string_value(json_object_get(this, "target file")); + if (0==strcmp("yes", json_string_value(json_object_get(this, "expect match")))) + expect_match=TR_FILTER_MATCH; + else + expect_match=TR_FILTER_NO_MATCH; + + if (0==strcmp("accept", json_string_value(json_object_get(this, "action")))) + action=TR_FILTER_ACTION_ACCEPT; + else + action=TR_FILTER_ACTION_REJECT; + + assert(test_one_filter(filt_file, ftype, target_file, expect_match, action)); + } + return 1; } @@ -115,6 +260,7 @@ int test_trp_filter(void) int main(void) { assert(test_load_filter()); + assert(test_filter()); printf("Success\n"); return 0; } \ No newline at end of file diff --git a/common/tests/test-filters/filt-inforec-1-msg.json b/common/tests/test-filters/filt-inforec-1-msg.json new file mode 100644 index 0000000..94e97fb --- /dev/null +++ b/common/tests/test-filters/filt-inforec-1-msg.json @@ -0,0 +1,15 @@ +{ + "msg_type": "trp_update", + "msg_body": { + "community": "my community", + "realm": "my realm", + "records": [ + { + "record_type": "route", + "trust_router": "tr", + "metric": 27, + "interval": 11 + } + ] + } +} \ No newline at end of file diff --git a/common/tests/test-filters/filt-inforec-1.json b/common/tests/test-filters/filt-inforec-1.json new file mode 100644 index 0000000..df5d1a1 --- /dev/null +++ b/common/tests/test-filters/filt-inforec-1.json @@ -0,0 +1,53 @@ +{ + "local_organizations": [ + { "organization_name": "inforec filter test 1", + "realms": [ + { "realm": "realm", + "gss_names": ["gss"], + "filters": { + "tid_inbound": [ + { "action": "accept", + "specs": [ + { "field": "rp_realm", + "match": [ + "a.realm", + "*.a.realm" + ] + } + ] + } + ], + "trp_inbound": [ + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["route"]} + ] + }, + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["community"]} + ] + } + ], + "trp_outbound": [ + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["invalid value"]} + ] + }, + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["community"]} + ] + } + ] + } + } + ] + } + ] +} diff --git a/common/tests/test-filters/filt-tidreq-1-msg.json b/common/tests/test-filters/filt-tidreq-1-msg.json new file mode 100644 index 0000000..8497e83 --- /dev/null +++ b/common/tests/test-filters/filt-tidreq-1-msg.json @@ -0,0 +1,17 @@ +{ + "msg_type": "tid_request", + "msg_body": { + "rp_realm": "my realm", + "target_realm": "your realm", + "community": "our community", + "orig_coi": "our aliased community", + "dh_info": { + "dh_p": "DEADBEEF", + "dh_g": "FEA57", + "dh_pub_key": "12345678" + }, + "constraints": [{"constraint": ["value"]}], + "path": ["hop", "skip", "jump"], + "expiration_interval": 13 + } +} \ No newline at end of file diff --git a/common/tests/test-filters/filt-tidreq-1.json b/common/tests/test-filters/filt-tidreq-1.json new file mode 100644 index 0000000..7325252 --- /dev/null +++ b/common/tests/test-filters/filt-tidreq-1.json @@ -0,0 +1,53 @@ +{ + "local_organizations": [ + { "organization_name": "tidreq filter test 1", + "realms": [ + { "realm": "realm", + "gss_names": ["gss"], + "filters": { + "tid_inbound": [ + { "action": "accept", + "specs": [ + { "field": "rp_realm", + "match": [ + "my realm", + "*.my realm" + ] + } + ] + } + ], + "trp_inbound": [ + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["route"]} + ] + }, + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["community"]} + ] + } + ], + "trp_outbound": [ + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["invalid value"]} + ] + }, + { "action": "accept", + "specs": [ + { "field": "info_type", + "match": ["community"]} + ] + } + ] + } + } + ] + } + ] +} diff --git a/common/tests/test-filters/filter-tests.json b/common/tests/test-filters/filter-tests.json new file mode 100644 index 0000000..cca4a7d --- /dev/null +++ b/common/tests/test-filters/filter-tests.json @@ -0,0 +1,23 @@ +[ + { "test label": "first TRP test", + "filter file": "test-filters/filt-inforec-1.json", + "filter type": "trp_inbound", + "target file": "test-filters/filt-inforec-1-msg.json", + "expect match": "yes", + "action": "accept" + }, + { "test label": "second TRP test", + "filter file": "test-filters/filt-inforec-1.json", + "filter type": "trp_outbound", + "target file": "test-filters/filt-inforec-1-msg.json", + "expect match": "no", + "action": "" + }, + { "test label": "first TID test", + "filter file": "test-filters/filt-tidreq-1.json", + "filter type": "tid_inbound", + "target file": "test-filters/filt-tidreq-1-msg.json", + "expect match": "yes", + "action": "accept" + } +] diff --git a/common/tr_config.c b/common/tr_config.c index 917a465..e98061f 100644 --- a/common/tr_config.c +++ b/common/tr_config.c @@ -410,41 +410,12 @@ static TR_CONSTRAINT *tr_cfg_parse_one_constraint(TALLOC_CTX *mem_ctx, char *cty return cons; } -TR_FILTER_TYPE filter_type[]={TR_FILTER_TYPE_TID_INBOUND, - TR_FILTER_TYPE_TRP_INBOUND, - TR_FILTER_TYPE_TRP_OUTBOUND}; -const char *filter_label[]={"tid_inbound", - "trp_inbound", - "trp_outbound"}; -size_t num_filter_types=sizeof(filter_type)/sizeof(filter_type[0]); - -static const char *filter_type_to_string(TR_FILTER_TYPE ftype) -{ - size_t ii=0; - - for (ii=0; iilines[i]->specs[j]->field->len, filt->lines[i]->specs[j]->field->buf, - filter_type_to_string(filt->type), + tr_filter_type_to_string(filt->type), i, j); *rc = TR_CFG_ERROR; goto cleanup; @@ -643,12 +614,13 @@ 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) +static TR_FILTER_SET *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; const char *filt_label=NULL; TR_FILTER *filt=NULL; + TR_FILTER_SET *filt_set=NULL; TR_FILTER_TYPE filt_type=TR_FILTER_TYPE_UNKNOWN; *rc=TR_CFG_ERROR; @@ -659,6 +631,13 @@ static TR_FILTER *tr_cfg_parse_filters(TALLOC_CTX *mem_ctx, json_t *jfilts, TR_C goto cleanup; } + filt_set=tr_filter_set_new(tmp_ctx); + if (filt_set==NULL) { + tr_debug("tr_cfg_parse_filters: Unable to allocate filter set."); + *rc = TR_CFG_NOMEM; + goto cleanup; + } + json_object_foreach(jfilts, filt_label, jfilt) { /* check that we got a filter */ if (jfilt == NULL) { @@ -668,7 +647,7 @@ static TR_FILTER *tr_cfg_parse_filters(TALLOC_CTX *mem_ctx, json_t *jfilts, TR_C } /* check that we recognize the filter type */ - filt_type=filter_type_from_string(filt_label); + filt_type=tr_filter_type_from_string(filt_label); if (filt_type==TR_FILTER_TYPE_UNKNOWN) { tr_debug("tr_cfg_parse_filters: Unrecognized filter (%s) defined.", filt_label); *rc = TR_CFG_NOPARSE; @@ -678,6 +657,7 @@ static TR_FILTER *tr_cfg_parse_filters(TALLOC_CTX *mem_ctx, json_t *jfilts, TR_C /* finally, parse the filter */ tr_debug("tr_cfg_parse_filters: Found %s filter.", filt_label); filt = tr_cfg_parse_one_filter(tmp_ctx, jfilt, filt_type, rc); + tr_filter_set_add(filt_set, filt); if (*rc != TR_CFG_SUCCESS) { tr_debug("tr_cfg_parse_filters: Error parsing %s filter.", filt_label); *rc = TR_CFG_NOPARSE; @@ -689,14 +669,14 @@ static TR_FILTER *tr_cfg_parse_filters(TALLOC_CTX *mem_ctx, json_t *jfilts, TR_C cleanup: if (*rc==TR_CFG_SUCCESS) - talloc_steal(mem_ctx, filt); - else if (filt!=NULL) { - talloc_free(filt); - filt=NULL; + talloc_steal(mem_ctx, filt_set); + else if (filt_set!=NULL) { + talloc_free(filt_set); + filt_set=NULL; } talloc_free(tmp_ctx); - return filt; + return filt_set; } static TR_AAA_SERVER *tr_cfg_parse_one_aaa_server(TALLOC_CTX *mem_ctx, json_t *jaddr, TR_CFG_RC *rc) @@ -1167,10 +1147,11 @@ static TR_GSS_NAMES *tr_cfg_parse_gss_names(TALLOC_CTX *mem_ctx, json_t *jgss_na } /* default filter accepts realm and *.realm */ -static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_CFG_RC *rc) +static TR_FILTER_SET *tr_cfg_default_filters(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_CFG_RC *rc) { TALLOC_CTX *tmp_ctx=talloc_new(NULL); TR_FILTER *filt=NULL; + TR_FILTER_SET *filt_set=NULL; TR_CONSTRAINT *cons=NULL; TR_NAME *name=NULL; TR_NAME *n_prefix=tr_new_name("*."); @@ -1181,7 +1162,7 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ if ((realm==NULL) || (rc==NULL)) { - tr_debug("tr_cfg_default_filter: invalid arguments."); + tr_debug("tr_cfg_default_filters: invalid arguments."); if (rc!=NULL) *rc=TR_CFG_BAD_PARAMS; goto cleanup; @@ -1192,21 +1173,21 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ (n_rp_realm_2==NULL) || (n_domain==NULL) || (n_realm==NULL)) { - tr_debug("tr_cfg_default_filter: unable to allocate names."); + tr_debug("tr_cfg_default_filters: unable to allocate names."); *rc=TR_CFG_NOMEM; goto cleanup; } filt=tr_filter_new(tmp_ctx); if (filt==NULL) { - tr_debug("tr_cfg_default_filter: could not allocate filter."); + tr_debug("tr_cfg_default_filters: could not allocate filter."); *rc=TR_CFG_NOMEM; goto cleanup; } tr_filter_set_type(filt, TR_FILTER_TYPE_TID_INBOUND); filt->lines[0]=tr_fline_new(filt); if (filt->lines[0]==NULL) { - tr_debug("tr_cfg_default_filter: could not allocate filter line."); + tr_debug("tr_cfg_default_filters: could not allocate filter line."); *rc=TR_CFG_NOMEM; goto cleanup; } @@ -1218,7 +1199,7 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ name=tr_dup_name(realm); if (name==NULL) { - tr_debug("tr_cfg_default_filter: could not allocate realm name."); + tr_debug("tr_cfg_default_filters: could not allocate realm name."); *rc=TR_CFG_NOMEM; goto cleanup; } @@ -1231,7 +1212,7 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ n_rp_realm_2=NULL; /* we don't own this name any more */ if (NULL==(name=tr_name_cat(n_prefix, realm))) { - tr_debug("tr_cfg_default_filter: could not allocate wildcard realm name."); + tr_debug("tr_cfg_default_filters: could not allocate wildcard realm name."); *rc=TR_CFG_NOMEM; goto cleanup; } @@ -1241,7 +1222,7 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ /* domain constraint */ if (NULL==(cons=tr_constraint_new(filt->lines[0]))) { - tr_debug("tr_cfg_default_filter: could not allocate domain constraint."); + tr_debug("tr_cfg_default_filters: could not allocate domain constraint."); *rc=TR_CFG_NOMEM; goto cleanup; } @@ -1250,14 +1231,14 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ n_domain=NULL; /* belongs to the constraint now */ name=tr_dup_name(realm); if (name==NULL) { - tr_debug("tr_cfg_default_filter: could not allocate realm name for domain constraint."); + tr_debug("tr_cfg_default_filters: could not allocate realm name for domain constraint."); *rc=TR_CFG_NOMEM; goto cleanup; } cons->matches[0]=name; name=tr_name_cat(n_prefix, realm); if (name==NULL) { - tr_debug("tr_cfg_default_filter: could not allocate wildcard realm name for domain constraint."); + tr_debug("tr_cfg_default_filters: could not allocate wildcard realm name for domain constraint."); *rc=TR_CFG_NOMEM; goto cleanup; } @@ -1268,7 +1249,7 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ /* realm constraint */ if (NULL==(cons=tr_constraint_new(filt->lines[0]))) { - tr_debug("tr_cfg_default_filter: could not allocate realm constraint."); + tr_debug("tr_cfg_default_filters: could not allocate realm constraint."); *rc=TR_CFG_NOMEM; goto cleanup; } @@ -1277,14 +1258,14 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ n_realm=NULL; /* belongs to the constraint now */ name=tr_dup_name(realm); if (name==NULL) { - tr_debug("tr_cfg_default_filter: could not allocate realm name for realm constraint."); + tr_debug("tr_cfg_default_filters: could not allocate realm name for realm constraint."); *rc=TR_CFG_NOMEM; goto cleanup; } cons->matches[0]=name; name=tr_name_cat(n_prefix, realm); if (name==NULL) { - tr_debug("tr_cfg_default_filter: could not allocate wildcard realm name for realm constraint."); + tr_debug("tr_cfg_default_filters: could not allocate wildcard realm name for realm constraint."); *rc=TR_CFG_NOMEM; goto cleanup; } @@ -1292,7 +1273,15 @@ static TR_FILTER *tr_cfg_default_filter(TALLOC_CTX *mem_ctx, TR_NAME *realm, TR_ name=NULL; filt->lines[0]->realm_cons=cons; - talloc_steal(mem_ctx, filt); + /* put the filter in a set */ + filt_set=tr_filter_set_new(tmp_ctx); + if ((filt_set==NULL)||(0!=tr_filter_set_add(filt_set, filt))) { + tr_debug("tr_cfg_default_filters: could not allocate filter set."); + *rc=TR_CFG_NOMEM; + goto cleanup; + } + talloc_steal(mem_ctx, filt_set); + cleanup: talloc_free(tmp_ctx); @@ -1312,7 +1301,7 @@ cleanup: if (name!=NULL) tr_free_name(name); - return filt; + return filt_set; } /* parses rp client */ @@ -1321,7 +1310,7 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client(TALLOC_CTX *mem_ctx, json_t *jre 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; + TR_FILTER_SET *new_filts=NULL; TR_NAME *realm=NULL; json_t *jfilt=NULL; json_t *jrealm_id=NULL; @@ -1366,7 +1355,7 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client(TALLOC_CTX *mem_ctx, json_t *jre /* parse filters */ jfilt=json_object_get(jrealm, "filters"); if (jfilt!=NULL) { - new_filt=tr_cfg_parse_filters(tmp_ctx, jfilt, &call_rc); + new_filts=tr_cfg_parse_filters(tmp_ctx, jfilt, &call_rc); if (call_rc!=TR_CFG_SUCCESS) { tr_err("tr_cfg_parse_one_rp_client: could not parse filters."); *rc=TR_CFG_NOPARSE; @@ -1374,7 +1363,7 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client(TALLOC_CTX *mem_ctx, json_t *jre } } else { tr_debug("tr_cfg_parse_one_rp_client: no filters specified, using default filters."); - new_filt=tr_cfg_default_filter(tmp_ctx, realm, &call_rc); + new_filts= tr_cfg_default_filters(tmp_ctx, realm, &call_rc); if (call_rc!=TR_CFG_SUCCESS) { tr_err("tr_cfg_parse_one_rp_client: could not set default filters."); *rc=TR_CFG_NOPARSE; @@ -1382,7 +1371,7 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client(TALLOC_CTX *mem_ctx, json_t *jre } } - tr_rp_client_set_filter(client, new_filt); + tr_rp_client_set_filters(client, new_filts); *rc=TR_CFG_SUCCESS; cleanup: @@ -1617,7 +1606,7 @@ static TR_CFG_RC tr_cfg_parse_one_peer_org(TR_CFG *trc, json_t *jporg) json_t *jfilt=NULL; TRP_PEER *new_peer=NULL; TR_GSS_NAMES *names=NULL; - TR_FILTER *filt=NULL; + TR_FILTER_SET *filt_set=NULL; TR_CFG_RC rc=TR_CFG_ERROR; jhost=json_object_get(jporg, "hostname"); @@ -1672,13 +1661,13 @@ static TR_CFG_RC tr_cfg_parse_one_peer_org(TR_CFG *trc, json_t *jporg) trp_peer_set_gss_names(new_peer, names); if (jfilt) { - filt=tr_cfg_parse_filters(tmp_ctx, jfilt, &rc); + filt_set=tr_cfg_parse_filters(tmp_ctx, jfilt, &rc); if (rc!=TR_CFG_SUCCESS) { tr_err("tr_cfg_parse_one_peer_org: unable to parse filters."); rc=TR_CFG_NOPARSE; goto cleanup; } - trp_peer_set_filter(new_peer, filt); + trp_peer_set_filters(new_peer, filt_set); } /* success! */ diff --git a/common/tr_filter.c b/common/tr_filter.c index c13be74..d30ce7a 100644 --- a/common/tr_filter.c +++ b/common/tr_filter.c @@ -159,7 +159,7 @@ int tr_filter_apply(void *target, /* Step through filter lines looking for a match. If a line matches, retval * will be set to TR_FILTER_MATCH, so stop then. */ for (ii=0, retval=TR_FILTER_NO_MATCH; - (iilines[ii]==NULL) @@ -178,6 +178,9 @@ int tr_filter_apply(void *target, break; /* give up on this filter line */ } } + + if (retval==TR_FILTER_MATCH) + break; } if (retval==TR_FILTER_MATCH) { @@ -418,4 +421,117 @@ int tr_filter_validate_spec_field(TR_FILTER_TYPE ftype, TR_FSPEC *fspec) return 0; /* unknown field */ return 1; -} \ No newline at end of file +} + +/** + * Allocate a new filter set. + * + * @param mem_ctx Talloc context for the new set + * @return Pointer to new set, or null on error + */ +TR_FILTER_SET *tr_filter_set_new(TALLOC_CTX *mem_ctx) +{ + TR_FILTER_SET *set=talloc(mem_ctx, TR_FILTER_SET); + if (set!=NULL) { + set->next=NULL; + set->this=NULL; + } + return set; +} + +/** + * Free a filter set + * + * @param fs Filter set to free + */ +void tr_filter_set_free(TR_FILTER_SET *fs) +{ + talloc_free(fs); +} + +/** + * Find the tail of the filter set linked list. + * + * @param set Set to find tail of + * @return Last element in the list + */ +static TR_FILTER_SET *tr_filter_set_tail(TR_FILTER_SET *set) +{ + while (set->next) + set=set->next; + return set; +} + +/** + * Add new filter to filter set. + * + * @param set Filter set + * @param new New filter to add + * @return 0 on success, nonzero on error + */ +int tr_filter_set_add(TR_FILTER_SET *set, TR_FILTER *new) +{ + TR_FILTER_SET *tail=NULL; + + if (set->this==NULL) + tail=set; + else { + tail=tr_filter_set_tail(set); + tail->next=tr_filter_set_new(set); + if (tail->next==NULL) + return 1; + tail=tail->next; + } + tail->this=new; + talloc_steal(tail, new); + return 0; +} + +/** + * Find a filter of a given type in the filter set. If there are multiple, returns the first one. + * + * @param set Filter set to search + * @param type Type of filter to find + * @return Borrowed pointer to the filter, or null if no filter of that type is found + */ +TR_FILTER *tr_filter_set_get(TR_FILTER_SET *set, TR_FILTER_TYPE type) +{ + TR_FILTER_SET *cur=set; + while(cur!=NULL) { + if ((cur->this != NULL) && (cur->this->type == type)) + return cur->this; + cur=cur->next; + } + return NULL; +} + +TR_FILTER_TYPE filter_type[]={TR_FILTER_TYPE_TID_INBOUND, + TR_FILTER_TYPE_TRP_INBOUND, + TR_FILTER_TYPE_TRP_OUTBOUND}; +const char *filter_label[]={"tid_inbound", + "trp_inbound", + "trp_outbound"}; +size_t num_filter_types=sizeof(filter_type)/sizeof(filter_type[0]); + +const char *tr_filter_type_to_string(TR_FILTER_TYPE ftype) +{ + size_t ii=0; + + for (ii=0; iinext=NULL; client->comm_next=NULL; client->gss_names=NULL; - client->filter=NULL; + client->filters=NULL; talloc_set_destructor((void *)client, tr_rp_client_destructor); } return client; @@ -96,12 +96,12 @@ int tr_rp_client_add_gss_name(TR_RP_CLIENT *rp_client, TR_NAME *gss_name) return tr_gss_names_add(rp_client->gss_names, gss_name); } -int tr_rp_client_set_filter(TR_RP_CLIENT *client, TR_FILTER *filt) +int tr_rp_client_set_filters(TR_RP_CLIENT *client, TR_FILTER_SET *filts) { - if (client->filter!=NULL) - tr_filter_free(client->filter); - client->filter=filt; - talloc_steal(client, filt); + if (client->filters!=NULL) + tr_filter_set_free(client->filters); + client->filters=filts; + talloc_steal(client, filts); return 0; /* success */ } diff --git a/include/tr_filter.h b/include/tr_filter.h index 38082de..a6f8651 100644 --- a/include/tr_filter.h +++ b/include/tr_filter.h @@ -50,9 +50,9 @@ /* Filter actions */ typedef enum { - TR_FILTER_ACTION_REJECT = 0, - TR_FILTER_ACTION_ACCEPT, - TR_FILTER_ACTION_UNKNOWN + TR_FILTER_ACTION_REJECT = 0, + TR_FILTER_ACTION_ACCEPT, + TR_FILTER_ACTION_UNKNOWN } TR_FILTER_ACTION; /* Match codes */ @@ -61,29 +61,41 @@ typedef enum { /* Filter types */ typedef enum { - TR_FILTER_TYPE_TID_INBOUND = 0, - TR_FILTER_TYPE_TRP_INBOUND, - TR_FILTER_TYPE_TRP_OUTBOUND, - TR_FILTER_TYPE_UNKNOWN + TR_FILTER_TYPE_TID_INBOUND = 0, + TR_FILTER_TYPE_TRP_INBOUND, + TR_FILTER_TYPE_TRP_OUTBOUND, + TR_FILTER_TYPE_UNKNOWN } TR_FILTER_TYPE; typedef struct tr_fspec { - TR_NAME *field; - TR_NAME *match[TR_MAX_FILTER_SPEC_MATCHES]; + TR_NAME *field; + TR_NAME *match[TR_MAX_FILTER_SPEC_MATCHES]; } TR_FSPEC; typedef struct tr_fline { - TR_FILTER_ACTION action; - TR_FSPEC *specs[TR_MAX_FILTER_SPECS]; - TR_CONSTRAINT *realm_cons; - TR_CONSTRAINT *domain_cons; + TR_FILTER_ACTION action; + TR_FSPEC *specs[TR_MAX_FILTER_SPECS]; + TR_CONSTRAINT *realm_cons; + TR_CONSTRAINT *domain_cons; } TR_FLINE; typedef struct tr_filter { - TR_FILTER_TYPE type; - TR_FLINE *lines[TR_MAX_FILTER_LINES]; + TR_FILTER_TYPE type; + TR_FLINE *lines[TR_MAX_FILTER_LINES]; } TR_FILTER; + +typedef struct tr_filter_set TR_FILTER_SET; +struct tr_filter_set { + TR_FILTER *this; + TR_FILTER_SET *next; +}; + +TR_FILTER_SET *tr_filter_set_new(TALLOC_CTX *mem_ctx); +void tr_filter_set_free(TR_FILTER_SET *fs); +int tr_filter_set_add(TR_FILTER_SET *set, TR_FILTER *new); +TR_FILTER *tr_filter_set_get(TR_FILTER_SET *set, TR_FILTER_TYPE type); + TR_FILTER *tr_filter_new(TALLOC_CTX *mem_ctx); void tr_filter_free(TR_FILTER *filt); @@ -116,5 +128,7 @@ TR_CONSTRAINT_SET *tr_constraint_set_from_fline(TR_FLINE *fline); int tr_filter_validate(TR_FILTER *filt); int tr_filter_validate_spec_field(TR_FILTER_TYPE ftype, TR_FSPEC *fspec); +const char *tr_filter_type_to_string(TR_FILTER_TYPE ftype); +TR_FILTER_TYPE tr_filter_type_from_string(const char *s); #endif diff --git a/include/tr_msg.h b/include/tr_msg.h index 0a9096f..e10fd1a 100644 --- a/include/tr_msg.h +++ b/include/tr_msg.h @@ -69,7 +69,7 @@ void tr_msg_set_trp_req(TR_MSG *msg, TRP_REQ *req); /* Encoders/Decoders */ char *tr_msg_encode(TR_MSG *msg); -TR_MSG *tr_msg_decode(char *jmsg, size_t len); +TR_MSG *tr_msg_decode(const char *jmsg, size_t len); void tr_msg_free_encoded(char *jmsg); void tr_msg_free_decoded(TR_MSG *msg); diff --git a/include/tr_rp.h b/include/tr_rp.h index 7e8f8f0..e150f9a 100644 --- a/include/tr_rp.h +++ b/include/tr_rp.h @@ -44,7 +44,7 @@ typedef struct tr_rp_client { struct tr_rp_client *next; struct tr_rp_client *comm_next; TR_GSS_NAMES *gss_names; - TR_FILTER *filter; + TR_FILTER_SET *filters; } TR_RP_CLIENT; /* Structure to make a linked list of RP realms by name for community config */ @@ -60,7 +60,7 @@ void tr_rp_client_free(TR_RP_CLIENT *client); TR_RP_CLIENT *tr_rp_client_add_func(TR_RP_CLIENT *clients, TR_RP_CLIENT *new); #define tr_rp_client_add(clients,new) ((clients)=tr_rp_client_add_func((clients),(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); +int tr_rp_client_set_filters(TR_RP_CLIENT *client, TR_FILTER_SET *filts); TR_RP_CLIENT *tr_rp_client_lookup(TR_RP_CLIENT *rp_clients, TR_NAME *gss_name); TR_RP_REALM *tr_rp_realm_new(TALLOC_CTX *mem_ctx); diff --git a/include/trp_ptable.h b/include/trp_ptable.h index 303bbc3..7171952 100644 --- a/include/trp_ptable.h +++ b/include/trp_ptable.h @@ -62,7 +62,7 @@ struct trp_peer { TRP_PEER_CONN_STATUS incoming_status; void (*conn_status_cb)(TRP_PEER *, void *); /* callback for connected status change */ void *conn_status_cookie; - TR_FILTER *filter; + TR_FILTER_SET *filters; }; typedef struct trp_ptable { @@ -108,8 +108,8 @@ void trp_peer_set_incoming_status(TRP_PEER *peer, TRP_PEER_CONN_STATUS status); int trp_peer_is_connected(TRP_PEER *peer); void trp_peer_set_linkcost(TRP_PEER *peer, unsigned int linkcost); void trp_peer_set_conn_status_cb(TRP_PEER *peer, void (*cb)(TRP_PEER *, void *), void *cookie); -void trp_peer_set_filter(TRP_PEER *peer, TR_FILTER *filt); -TR_FILTER *trp_peer_get_filter(TRP_PEER *peer); +void trp_peer_set_filters(TRP_PEER *peer, TR_FILTER_SET *filts); +TR_FILTER *trp_peer_get_filter(TRP_PEER *peer, TR_FILTER_TYPE ftype); char *trp_peer_to_str(TALLOC_CTX *memctx, TRP_PEER *peer, const char *sep); #endif /* _TRP_PTABLE_H_ */ diff --git a/tr/tr_tid.c b/tr/tr_tid.c index fb76dd7..7a09dda 100644 --- a/tr/tr_tid.c +++ b/tr/tr_tid.c @@ -295,7 +295,7 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids, * the TIDS handler subprocess. */ if ((!tids->rp_gss) || - (!tids->rp_gss->filter)) { + (!tids->rp_gss->filters)) { tr_notice("tr_tids_req_handler: No GSS name for incoming request."); tids_send_err_response(tids, orig_req, "No GSS name for request"); retval=-1; @@ -303,7 +303,8 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids, } if ((TR_FILTER_NO_MATCH == tr_filter_process_rp_permitted(orig_req->rp_realm, - tids->rp_gss->filter, + tr_filter_set_get(tids->rp_gss->filters, + TR_FILTER_TYPE_TID_INBOUND), orig_req->cons, &fwd_req->cons, &oaction)) || diff --git a/trp/trp_ptable.c b/trp/trp_ptable.c index 4cb0705..b954584 100644 --- a/trp/trp_ptable.c +++ b/trp/trp_ptable.c @@ -66,7 +66,7 @@ TRP_PEER *trp_peer_new(TALLOC_CTX *memctx) peer->incoming_status=PEER_DISCONNECTED; peer->conn_status_cb=NULL; peer->conn_status_cookie=NULL; - peer->filter=NULL; + peer->filters=NULL; talloc_set_destructor((void *)peer, trp_peer_destructor); } return peer; @@ -212,20 +212,20 @@ void trp_peer_set_conn_status_cb(TRP_PEER *peer, void (*cb)(TRP_PEER *, void *), * freeing the new filter. * * @param peer Peer to modify - * @param filt New filter to attach to the peer + * @param filts New filter to attach to the peer */ -void trp_peer_set_filter(TRP_PEER *peer, TR_FILTER *filt) +void trp_peer_set_filters(TRP_PEER *peer, TR_FILTER_SET *filts) { - if (peer->filter!=NULL) - tr_filter_free(peer->filter); + if (peer->filters!=NULL) + tr_filter_set_free(peer->filters); - peer->filter=filt; - talloc_steal(peer, filt); + peer->filters=filts; + talloc_steal(peer, filts); } -TR_FILTER *trp_peer_get_filter(TRP_PEER *peer) +TR_FILTER *trp_peer_get_filter(TRP_PEER *peer, TR_FILTER_TYPE ftype) { - return peer->filter; + return tr_filter_set_get(peer->filters, ftype); } struct timespec *trp_peer_get_last_conn_attempt(TRP_PEER *peer) -- 2.1.4