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)
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;
#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);
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;
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;
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);
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;
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;
}