From e71ac4f7f1666dff5b21c9e6a57bf2a01f9ab469 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Tue, 13 Jun 2017 12:32:58 -0400 Subject: [PATCH] Allow inforec filter to have access to realm and community --- common/tests/filt_test.c | 16 ++++++--- common/tr_filter.c | 86 ++++++++++++++++++++++++++++++++++++++---------- include/tr_filter.h | 20 +++++++++-- tr/tr_tid.c | 19 +++++++---- trp/trps.c | 59 ++++++++++++++++++++++++--------- 5 files changed, 154 insertions(+), 46 deletions(-) diff --git a/common/tests/filt_test.c b/common/tests/filt_test.c index 7dc5094..6d246da 100644 --- a/common/tests/filt_test.c +++ b/common/tests/filt_test.c @@ -178,7 +178,7 @@ int test_one_filter(const char *filt_fname, int expected_match, TR_FILTER_ACTION expected_action) { - void *target=NULL; + TR_FILTER_TARGET *target=NULL; TR_FILTER_SET *filts=NULL; TR_FILTER_ACTION action=TR_FILTER_ACTION_UNKNOWN; @@ -188,12 +188,13 @@ int test_one_filter(const char *filt_fname, /* load the target req or inforec */ switch(ftype) { case TR_FILTER_TYPE_TID_INBOUND: - target=load_tid_req(target_fname); + target=tr_filter_target_tid_req(NULL, load_tid_req(target_fname)); break; case TR_FILTER_TYPE_TRP_INBOUND: case TR_FILTER_TYPE_TRP_OUTBOUND: - target=load_inforec(target_fname); + /* TODO: read realm and community */ + target=tr_filter_target_trp_inforec(NULL, load_inforec(target_fname), NULL, NULL); break; default: @@ -208,17 +209,22 @@ int test_one_filter(const char *filt_fname, tr_filter_set_free(filts); switch(ftype) { case TR_FILTER_TYPE_TID_INBOUND: - tid_req_free((TID_REQ *)target); + tid_req_free(target->tid_req); break; case TR_FILTER_TYPE_TRP_INBOUND: case TR_FILTER_TYPE_TRP_OUTBOUND: - trp_inforec_free((TRP_INFOREC *)target); + trp_inforec_free(target->trp_inforec); + if (target->realm!=NULL) + tr_free_name(target->realm); + if (target->comm!=NULL) + tr_free_name(target->comm); break; default: printf("Unknown filter type.\n"); } + tr_filter_target_free(target); return 1; } diff --git a/common/tr_filter.c b/common/tr_filter.c index 39a0fd7..892eb81 100644 --- a/common/tr_filter.c +++ b/common/tr_filter.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -46,14 +45,14 @@ /* Function types for handling filter fields generally. All target values * are represented as strings in a TR_NAME. */ -typedef int (*TR_FILTER_FIELD_CMP)(void *target, TR_NAME *val); /* returns 1 on match, 0 on no match */ -typedef TR_NAME *(*TR_FILTER_FIELD_GET)(void *target); /* returns string form of the field value */ +typedef int (*TR_FILTER_FIELD_CMP)(TR_FILTER_TARGET *target, TR_NAME *val); /* returns 1 on match, 0 on no match */ +typedef TR_NAME *(*TR_FILTER_FIELD_GET)(TR_FILTER_TARGET *target); /* returns string form of the field value */ /* static handler prototypes */ -static int tr_ff_cmp_tid_rp_realm(void *rp_req_arg, TR_NAME *val); -static TR_NAME *tr_ff_get_tid_rp_realm(void *rp_req_arg); -static int tr_ff_cmp_trp_info_type(void *inforec_arg, TR_NAME *val); -static TR_NAME *tr_ff_get_trp_info_type(void *inforec_arg); +static int tr_ff_cmp_tid_rp_realm(TR_FILTER_TARGET *target, TR_NAME *val); +static TR_NAME *tr_ff_get_tid_rp_realm(TR_FILTER_TARGET *target); +static int tr_ff_cmp_trp_info_type(TR_FILTER_TARGET *target, TR_NAME *val); +static TR_NAME *tr_ff_get_trp_info_type(TR_FILTER_TARGET *target); /** * Filter field handler table @@ -84,23 +83,76 @@ static struct tr_filter_field_entry *tr_filter_field_entry(TR_FILTER_TYPE filter return NULL; } -static int tr_ff_cmp_tid_rp_realm(void *rp_req_arg, TR_NAME *val) +static TR_FILTER_TARGET *tr_filter_target_new(TALLOC_CTX *mem_ctx) { - TID_REQ *req=talloc_get_type_abort(rp_req_arg, TID_REQ); + TR_FILTER_TARGET *target=talloc(mem_ctx, TR_FILTER_TARGET); + if (target) { + target->trp_inforec=NULL; + target->comm=NULL; + target->realm=NULL; + target->tid_req=NULL; + } + return target; +} +void tr_filter_target_free(TR_FILTER_TARGET *target) +{ + talloc_free(target); +} + +/** + * Create a filter target for a TID request. Does not change the context of the request, + * so this is only valid until that is freed. + * + * @param mem_ctx talloc context for the object + * @param req TID request object + * @return pointer to a TR_FILTER_TARGET structure, or null on allocation failure + */ +TR_FILTER_TARGET *tr_filter_target_tid_req(TALLOC_CTX *mem_ctx, TID_REQ *req) +{ + TR_FILTER_TARGET *target=tr_filter_target_new(mem_ctx); + if (target) + target->tid_req=req; /* borrowed, not adding to our context */ + return target; +} + +/** + * Create a filter target for a TRP inforec. Does not change the context of the inforec or duplicate TR_NAMEs, + * so this is only valid until those are freed. + * + * @param mem_ctx talloc context for the object + * @param inforec TRP inforec + * @param realm realm name + * @param comm community name + * @return pointer to a TR_FILTER_TARGET structure, or null on allocation failure + */ +TR_FILTER_TARGET *tr_filter_target_trp_inforec(TALLOC_CTX *mem_ctx, TRP_INFOREC *inforec, TR_NAME *realm, TR_NAME *comm) +{ + TR_FILTER_TARGET *target=tr_filter_target_new(mem_ctx); + if (target) { + target->trp_inforec = inforec; /* borrowed, not adding to our context */ + target->realm=realm; + target->comm=comm; + } + return target; +} + +static int tr_ff_cmp_tid_rp_realm(TR_FILTER_TARGET *target, TR_NAME *val) +{ + TID_REQ *req=target->tid_req; assert(req); return 0==tr_name_cmp(val, req->rp_realm); } -static TR_NAME *tr_ff_get_tid_rp_realm(void *rp_req_arg) +static TR_NAME *tr_ff_get_tid_rp_realm(TR_FILTER_TARGET *target) { - TID_REQ *req=talloc_get_type_abort(rp_req_arg, TID_REQ); + TID_REQ *req=target->tid_req; assert(req); return tr_dup_name(req->rp_realm); } -static int tr_ff_cmp_trp_info_type(void *inforec_arg, TR_NAME *val) +static int tr_ff_cmp_trp_info_type(TR_FILTER_TARGET *target, TR_NAME *val) { - TRP_INFOREC *inforec=talloc_get_type_abort(inforec_arg, TRP_INFOREC); + TRP_INFOREC *inforec=target->trp_inforec; char *valstr=NULL; int val_type=0; @@ -118,9 +170,9 @@ static int tr_ff_cmp_trp_info_type(void *inforec_arg, TR_NAME *val) return (val_type==inforec->type); } -static TR_NAME *tr_ff_get_trp_info_type(void *inforec_arg) +static TR_NAME *tr_ff_get_trp_info_type(TR_FILTER_TARGET *target) { - TRP_INFOREC *inforec=talloc_get_type_abort(inforec_arg, TRP_INFOREC); + TRP_INFOREC *inforec=target->trp_inforec; return tr_new_name(trp_inforec_type_to_string(inforec->type)); } @@ -141,7 +193,7 @@ static TR_NAME *tr_ff_get_trp_info_type(void *inforec_arg) * @param out_action Action to be carried out (output) * @return TR_FILTER_MATCH or TR_FILTER_NO_MATCH */ -int tr_filter_apply(void *target, +int tr_filter_apply(TR_FILTER_TARGET *target, TR_FILTER *filt, TR_CONSTRAINT_SET **constraints, TR_FILTER_ACTION *out_action) @@ -243,7 +295,7 @@ void tr_fspec_add_match(TR_FSPEC *fspec, TR_NAME *match) } /* returns 1 if the spec matches */ -int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, void *target) +int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, TR_FILTER_TARGET *target) { struct tr_filter_field_entry *field=NULL; TR_NAME *name=NULL; diff --git a/include/tr_filter.h b/include/tr_filter.h index bbee2dc..0fe8dbd 100644 --- a/include/tr_filter.h +++ b/include/tr_filter.h @@ -91,6 +91,19 @@ struct tr_filter_set { TR_FILTER_SET *next; }; +/** + * Structure to hold information needed to filter different targets. + */ +typedef struct tr_filter_target { + /* An inforec also needs realm and community information */ + TRP_INFOREC *trp_inforec; + TR_NAME *realm; + TR_NAME *comm; + + /* a TID request has all the data it needs to be filtered */ + TID_REQ *tid_req; +} TR_FILTER_TARGET; + 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); @@ -114,13 +127,16 @@ void tr_fspec_free(TR_FSPEC *fspec); void tr_fspec_add_match(TR_FSPEC *fspec, TR_NAME *match); -int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, void *target); +int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, TR_FILTER_TARGET *target); /*In tr_constraint.c and exported, but not really a public symbol; needed by tr_filter.c and by tr_constraint.c*/ int TR_EXPORT tr_prefix_wildcard_match(const char *str, const char *wc_str); -int tr_filter_apply(void *target, TR_FILTER *filt, TR_CONSTRAINT_SET **constraints, TR_FILTER_ACTION *out_action); +int tr_filter_apply(TR_FILTER_TARGET *target, TR_FILTER *filt, TR_CONSTRAINT_SET **constraints, TR_FILTER_ACTION *out_action); +void tr_filter_target_free(TR_FILTER_TARGET *target); +TR_FILTER_TARGET *tr_filter_target_tid_req(TALLOC_CTX *mem_ctx, TID_REQ *req); +TR_FILTER_TARGET *tr_filter_target_trp_inforec(TALLOC_CTX *mem_ctx, TRP_INFOREC *inforec, TR_NAME *realm, TR_NAME *comm); TR_CONSTRAINT_SET *tr_constraint_set_from_fline(TR_FLINE *fline); diff --git a/tr/tr_tid.c b/tr/tr_tid.c index ee3fe1c..6bc002a 100644 --- a/tr/tr_tid.c +++ b/tr/tr_tid.c @@ -261,6 +261,7 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids, unsigned int resp_frac_numer=cfg_mgr->active->internal->tid_resp_numer; unsigned int resp_frac_denom=cfg_mgr->active->internal->tid_resp_denom; TR_RESP_COOKIE *payload=NULL; + TR_FILTER_TARGET *target=NULL; int ii=0; int retval=-1; @@ -306,12 +307,18 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids, * well. Need to verify that this is acceptable behavior, but it's what we've always done. */ fwd_req->cons=orig_req->cons; - if ((TR_FILTER_NO_MATCH == tr_filter_apply(orig_req, - tr_filter_set_get(tids->rp_gss->filters, - TR_FILTER_TYPE_TID_INBOUND), - &(fwd_req->cons), - &oaction)) || - (TR_FILTER_ACTION_ACCEPT != oaction)) { + target=tr_filter_target_tid_req(tmp_ctx, orig_req); + if (target==NULL) { + /* TODO: signal that filtering failed. Until then, just filter everything and give an error message. */ + tr_crit("tid_req_handler: Unable to allocate filter target, cannot apply filter!"); + } + if ((target==NULL) + || (TR_FILTER_NO_MATCH == tr_filter_apply(target, + tr_filter_set_get(tids->rp_gss->filters, + TR_FILTER_TYPE_TID_INBOUND), + &(fwd_req->cons), + &oaction)) + || (TR_FILTER_ACTION_ACCEPT != oaction)) { tr_notice("tr_tids_req_handler: RP realm (%s) does not match RP Realm filter for GSS name", orig_req->rp_realm->buf); tids_send_err_response(tids, orig_req, "RP Realm filter error"); retval=-1; diff --git a/trp/trps.c b/trp/trps.c index aef4b36..61c02e8 100644 --- a/trp/trps.c +++ b/trp/trps.c @@ -1009,12 +1009,16 @@ cleanup: * @param trps Active TRPS instance * @param peer_name Name of peer that sent this inforec * @param rec Inforec to filter + * @param realm Name of realm + * @param comm Name of community * @return 1 if accepted by the filter, 0 otherwise */ -static int trps_filter_inbound_inforec(TRPS_INSTANCE *trps, TR_NAME *peer_name, TRP_INFOREC *rec) +static int trps_filter_inbound_inforec(TRPS_INSTANCE *trps, TR_NAME *peer_name, TRP_INFOREC *rec, TR_NAME *realm, TR_NAME *comm) { TRP_PEER *peer=NULL; TR_FILTER_ACTION action=TR_FILTER_ACTION_REJECT; + TR_FILTER_TARGET *target=NULL; + int retval=0; /* Look up the peer. For inbound messages, the peer is identified by its GSS name */ peer=trps_get_peer_by_gssname(trps, peer_name); @@ -1026,17 +1030,26 @@ static int trps_filter_inbound_inforec(TRPS_INSTANCE *trps, TR_NAME *peer_name, } /* tr_filter_apply() and tr_filter_set_get() handle null filter sets/filters by rejecting */ - if ((TR_FILTER_NO_MATCH==tr_filter_apply(rec, - tr_filter_set_get(peer->filters, TR_FILTER_TYPE_TRP_INBOUND), - NULL, - &action)) + target=tr_filter_target_trp_inforec(NULL, rec, realm, comm); + if (target==NULL) { + /* TODO: signal that filtering failed. Until then, just filter everything and give an error message. */ + tr_crit("trps_filter_inbound_inforec: Unable to allocate filter target, cannot apply filter!"); + } + if ((target==NULL) + || (TR_FILTER_NO_MATCH==tr_filter_apply(target, + tr_filter_set_get(peer->filters, TR_FILTER_TYPE_TRP_INBOUND), + NULL, + &action)) || (action!=TR_FILTER_ACTION_ACCEPT)) { - /* either the filter did not match or it matched a reject rule */ - return 0; - } + /* either the filter did not match or it matched a reject rule or allocating the target failed */ + retval=0; + } else + retval=1; + if (target!=NULL) + tr_filter_target_free(target); /* filter matched an accept rule */ - return 1; + return retval; } @@ -1058,7 +1071,11 @@ static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd) } for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) { - if (!trps_filter_inbound_inforec(trps, trp_upd_get_peer(upd), rec)) { + if (!trps_filter_inbound_inforec(trps, + trp_upd_get_peer(upd), + rec, + trp_upd_get_realm(upd), + trp_upd_get_comm(upd))) { tr_debug("trps_handle_update: inforec rejected by filter."); continue; /* just go on to the next record */ } @@ -1662,14 +1679,24 @@ static void trps_filter_one_outbound_update(TR_FILTER *filt, TRP_UPD *upd) { TRP_INFOREC *this=NULL, *next=NULL; TR_FILTER_ACTION action=TR_FILTER_ACTION_REJECT; + TR_FILTER_TARGET *target=NULL; for(this=trp_upd_get_inforec(upd); this!=NULL; this=next) { next=this->next; - if ((TR_FILTER_NO_MATCH==tr_filter_apply(this, filt, NULL, &action)) + target=tr_filter_target_trp_inforec(NULL, this, trp_upd_get_realm(upd), trp_upd_get_comm(upd)); + if (target==NULL) { + /* TODO: signal that filtering failed. Until then, just filter everything and give an error message. */ + tr_crit("trps_filter_one_outbound_update: Unable to allocate filter target, cannot apply filter!"); + } + if ((target==NULL) + || (TR_FILTER_NO_MATCH==tr_filter_apply(target, filt, NULL, &action)) || (action!=TR_FILTER_ACTION_ACCEPT)) { - /* Either no filter matched or one matched and rejected this record */ + /* Either no filter matched or one matched and rejected this record. + * Also filter out record if we were unable to allocate a target. */ trp_upd_remove_inforec(upd, this); /* "this" is now invalid */ } + if (target!=NULL) + tr_filter_target_free(target); } } @@ -1704,8 +1731,8 @@ static void trps_trp_upd_destroy(gpointer data) static TRP_RC trps_update_one_peer(TRPS_INSTANCE *trps, TRP_PEER *peer, TRP_UPDATE_TYPE update_type, - TR_NAME *comm, - TR_NAME *realm) + TR_NAME *realm, + TR_NAME *comm) { TALLOC_CTX *tmp_ctx=talloc_new(NULL); TR_MSG msg; /* not a pointer! */ @@ -1932,8 +1959,8 @@ static TRP_RC trps_handle_request(TRPS_INSTANCE *trps, TRP_REQ *req) return trps_update_one_peer(trps, trps_get_peer_by_gssname(trps, trp_req_get_peer(req)), TRP_UPDATE_REQUESTED, - comm, - realm); + realm, + comm); } -- 2.1.4