From fa5f69b296b9fa27f374a51b66d84ff4de3f3559 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Thu, 13 Jul 2017 22:41:31 -0400 Subject: [PATCH 1/1] Apply all filters applicable to a GSS name to a TID req --- common/tr_rp.c | 53 +++++++++++++++++++++++++++++++++------- include/tid_internal.h | 2 +- include/tr_filter.h | 2 +- include/tr_rp.h | 6 +++++ tr/tr_tid.c | 66 +++++++++++++++++++++++++++++++++----------------- 5 files changed, 96 insertions(+), 33 deletions(-) diff --git a/common/tr_rp.c b/common/tr_rp.c index 35c2714..f54a5a5 100644 --- a/common/tr_rp.c +++ b/common/tr_rp.c @@ -105,20 +105,55 @@ int tr_rp_client_set_filters(TR_RP_CLIENT *client, TR_FILTER_SET *filts) return 0; /* success */ } -TR_RP_CLIENT *tr_rp_client_lookup(TR_RP_CLIENT *rp_clients, TR_NAME *gss_name) +TR_RP_CLIENT_ITER *tr_rp_client_iter_new(TALLOC_CTX *memctx) +{ + return talloc(memctx, TR_RP_CLIENT_ITER); +} + +void tr_rp_client_iter_free(TR_RP_CLIENT_ITER *iter) { - TR_RP_CLIENT *rp = NULL; + talloc_free(iter); +} - if ((!rp_clients) || (!gss_name)) { - tr_debug("tr_rp_client_lookup: Bad parameters."); +TR_RP_CLIENT *tr_rp_client_iter_first(TR_RP_CLIENT_ITER *iter, TR_RP_CLIENT *rp_clients) +{ + if (!iter) { + tr_err("tr_rp_client_iter_first: Iterator is null, failing."); return NULL; } + *iter=rp_clients; + return *iter; +} - for (rp = rp_clients; NULL != rp; rp = rp->next) { - if (tr_gss_names_matches(rp->gss_names, gss_name)) - return rp; - } - return NULL; +TR_RP_CLIENT *tr_rp_client_iter_next(TR_RP_CLIENT_ITER *iter) +{ + if (*iter) + *iter=(*iter)->next; + return *iter; +} + +/** + * Find a client associated with a GSS name. It's possible there are other clients that match as well. + * + * @param rp_clients List of RP clients to search + * @param gss_name GSS name to search for + * @return Borrowed reference to an RP client linked to the GSS name + */ +TR_RP_CLIENT *tr_rp_client_lookup(TR_RP_CLIENT *rp_clients, TR_NAME *gss_name) +{ + TR_RP_CLIENT_ITER *iter=tr_rp_client_iter_new(NULL); + TR_RP_CLIENT *client=NULL; + + if (iter==NULL) { + tr_err("tr_rp_client_lookup: Unable to allocate iterator"); + return NULL; + } + for (client=tr_rp_client_iter_first(iter, rp_clients); client != NULL; client=tr_rp_client_iter_next(iter)) { + if (tr_gss_names_matches(client->gss_names, gss_name)) + break; + } + tr_rp_client_iter_free(iter); + return client; } TR_RP_REALM *tr_rp_realm_lookup(TR_RP_REALM *rp_realms, TR_NAME *rp_name) diff --git a/include/tid_internal.h b/include/tid_internal.h index 10c6eac..f02c4d1 100644 --- a/include/tid_internal.h +++ b/include/tid_internal.h @@ -98,7 +98,7 @@ struct tids_instance { tids_auth_func *auth_handler; void *cookie; uint16_t tids_port; - struct tr_rp_client *rp_gss; /* Client matching GSS name */ + TR_NAME *gss_name; /* GSS name client used for authentication */ }; /** Decrement a reference to #json when this tid_req is cleaned up. A diff --git a/include/tr_filter.h b/include/tr_filter.h index 45b8fdc..63b23dd 100644 --- a/include/tr_filter.h +++ b/include/tr_filter.h @@ -49,7 +49,7 @@ #define TR_MAX_FILTER_SPEC_MATCHES 64 /* Filter actions */ -typedef enum { +typedef enum tr_filter_action { TR_FILTER_ACTION_REJECT = 0, TR_FILTER_ACTION_ACCEPT, TR_FILTER_ACTION_UNKNOWN diff --git a/include/tr_rp.h b/include/tr_rp.h index e150f9a..fa6b84e 100644 --- a/include/tr_rp.h +++ b/include/tr_rp.h @@ -47,6 +47,8 @@ typedef struct tr_rp_client { TR_FILTER_SET *filters; } TR_RP_CLIENT; +typedef struct tr_rp_client *TR_RP_CLIENT_ITER; + /* Structure to make a linked list of RP realms by name for community config */ typedef struct tr_rp_realm { struct tr_rp_realm *next; @@ -61,6 +63,10 @@ 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_filters(TR_RP_CLIENT *client, TR_FILTER_SET *filts); +TR_RP_CLIENT_ITER *tr_rp_client_iter_new(TALLOC_CTX *memctx); +void tr_rp_client_iter_free(TR_RP_CLIENT_ITER *iter); +TR_RP_CLIENT *tr_rp_client_iter_first(TR_RP_CLIENT_ITER *iter, TR_RP_CLIENT *rp_clients); +TR_RP_CLIENT *tr_rp_client_iter_next(TR_RP_CLIENT_ITER *iter); 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/tr/tr_tid.c b/tr/tr_tid.c index 37ee89f..dffa46b 100644 --- a/tr/tr_tid.c +++ b/tr/tr_tid.c @@ -243,6 +243,8 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids, pthread_t aaa_thread[TR_TID_MAX_AAA_SERVERS]; struct tr_tids_fwd_cookie *aaa_cookie[TR_TID_MAX_AAA_SERVERS]={NULL}; TID_RESP *aaa_resp[TR_TID_MAX_AAA_SERVERS]={NULL}; + TR_RP_CLIENT *rp_client=NULL; + TR_RP_CLIENT_ITER *rpc_iter=NULL; TR_NAME *apc = NULL; TID_REQ *fwd_req = NULL; TR_COMM *cfg_comm = NULL; @@ -290,13 +292,13 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids, goto cleanup; } - /* Check that the rp_realm matches the filter for the GSS name that - * was received. N.B. that tids->rp_gss was pointed at the correct - * rp_client when we received its GSS name. It is only set within - * the TIDS handler subprocess. */ + /* We now need to apply the filters associated with the RP client handing us the request. + * It is possible (or even likely) that more than one client is associated with the GSS + * name we got from the authentication. We will apply all of them in an arbitrary order. + * For this to result in well-defined behavior, either only accept or only reject filter + * lines should be used, or a unique GSS name must be given for each RP realm. */ - if ((!tids->rp_gss) || - (!tids->rp_gss->filters)) { + if (!tids->gss_name) { 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; @@ -309,21 +311,42 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids, 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!"); + tids_send_err_response(tids, orig_req, "Incoming TID request filter error"); + retval=-1; + goto cleanup; } - 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)) { + + rpc_iter=tr_rp_client_iter_new(tmp_ctx); + if (rpc_iter==NULL) { + tr_err("tid_req_handler: Unable to allocate RP client iterator."); + retval=-1; + goto cleanup; + } + for (rp_client=tr_rp_client_iter_first(rpc_iter, cfg_mgr->active->rp_clients); + rp_client != NULL; + rp_client=tr_rp_client_iter_next(rpc_iter)) { + + if (!tr_gss_names_matches(rp_client->gss_names, tids->gss_name)) + continue; /* skip any that don't match the GSS name */ + + if (TR_FILTER_MATCH == tr_filter_apply(target, + tr_filter_set_get(rp_client->filters, + TR_FILTER_TYPE_TID_INBOUND), + &(fwd_req->cons), + &oaction)) + break; /* Stop looking, oaction is set */ + } + + /* We get here whether or not a filter matched. If tr_filter_apply() doesn't match, it returns + * a default action of reject, so we don't have to check why we exited the loop. */ + if (oaction != TR_FILTER_ACTION_ACCEPT) { tr_notice("tr_tids_req_handler: Incoming TID request rejected by filter for GSS name", orig_req->rp_realm->buf); tids_send_err_response(tids, orig_req, "Incoming TID request filter error"); - retval=-1; + retval = -1; goto cleanup; } + /* Check that the rp_realm is a member of the community in the request */ if (NULL == tr_comm_find_rp(cfg_mgr->active->ctable, cfg_comm, orig_req->rp_realm)) { tr_notice("tr_tids_req_handler: RP Realm (%s) not member of community (%s).", orig_req->rp_realm->buf, orig_req->comm->buf); @@ -602,7 +625,6 @@ cleanup: static int tr_tids_gss_handler(gss_name_t client_name, TR_NAME *gss_name, void *data) { - TR_RP_CLIENT *rp; struct tr_tids_event_cookie *cookie=talloc_get_type_abort(data, struct tr_tids_event_cookie); TIDS_INSTANCE *tids = cookie->tids; TR_CFG_MGR *cfg_mgr = cookie->cfg_mgr; @@ -612,15 +634,15 @@ static int tr_tids_gss_handler(gss_name_t client_name, TR_NAME *gss_name, return -1; } - /* look up the RP client matching the GSS name */ - if ((NULL == (rp = tr_rp_client_lookup(cfg_mgr->active->rp_clients, gss_name)))) { - tr_debug("tr_tids_gss_handler: Unknown GSS name %s", gss_name->buf); + /* Ensure at least one client exists using this GSS name */ + if (NULL == tr_rp_client_lookup(cfg_mgr->active->rp_clients, gss_name)) { + tr_debug("tr_tids_gss_handler: Unknown GSS name %.*s", gss_name->len, gss_name->buf); return -1; } - /* Store the rp client */ - tids->rp_gss = rp; - tr_debug("Client's GSS Name: %s", gss_name->buf); + /* Store the GSS name */ + tids->gss_name = tr_dup_name(gss_name); + tr_debug("Client's GSS Name: %.*s", gss_name->len, gss_name->buf); return 0; } -- 2.1.4