DONE - Read TR portal/manual config from files at start-up (non-dynamic)
DONE - Look-up code to find correct AAA Server for a Comm/Realm
DONE - TR TID request & response handlers
-- Check gss_name on incoming TID request in TR (in TIDS, too?)
+DONE - TIDS integration with freeradius server
+DONE - TIDC integration with freeradius proxy
+DONE - Map a COI to an APC in TR (incl config & lookup code)
- Check rp_realm COI membership in TR
- Check idp_realm APC membership in TR
-- Map a COI to an APC in TR (incl config & lookup code)
-IN PROGRESS - TIDS integration with freeradius server (Sam)
-IN PROGRESS - TIDC integration with freeradius proxy (w/default comm config)
-- Handle per-request community configuration in AAA proxy
-- Resolve TBDs for error handling and memory deallocation
+DONE - Resolve TBDs for error handling and deallocation
TO-DO FOR FULL PILOT VERSION (~2 months after beta release)
============================
-- Move to better tasking model for TR (needed for dyn cfg and TR protocol)
-- Dynamically re-read TR configuration file at runtime
+- Add key confirmation to TID protocol
+- Check gss_name on incoming TID request in TR (in TIDS, too?)
- Keep single connection open between AAA proxy & TR for TID requests
-- Handle multiple simultaneous TID requests in AAA proxy (reqs req ID in the protocol)
+- Add Request ID to TID messages (req'd for mult simultaneous reqs)
+- Handle multiple simultaneous TID requests in AAA proxy
+- Fix issue with how DH params are handled in the TR (API clean-up)
+- Handle per-request community configuration in AAA proxy
- Add TR support for multiple AAA servers in an IDP
-- Normalize/configure logging for info msgs, warnings and errors (log4c)
+- Move to better tasking model for TR (for dyn cfg and TR protocol)
+- Dynamically re-read TR configuration file at runtime
+- Normalize/configure logging for info, warnings and errors (log4c)
- Clean-up gsscon API and messages
+- Add accessors for all externally accessible data structures, etc.
+- Formalize API for integration with RADIUS servers
+- More fully integrate TIDS with AAA Server? (Tradeoffs?)
- Figure out what to do about commented-out checks in gsscon_passive.c
- Handle IPv6 addresses in TID req/resp (use getaddrinfo())
- Implement rp_permitted filters (incl. general filtering mechanism)
+- Add
- Add constraints to TID req in TR, store and use them in AAA Server
- Use valgrind to check for memory leaks, other issues
+- Resolve remaining TBDs
- Full functional testing
TO-DO FOR PRODUCTION VERSION (August 2013)
- Multiple Trust Router support including implementation of TR protocol
- Consider standard encoding of DH info (from jose WG)
- Algorithm agility in TID protocol?
+- Handle more than one APC per COI? (How would this work?)
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2012, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <trust_router/tr_name.h>
+#include <tr.h>
+#include <tr_comm.h>
+
+TR_COMM *tr_comm_lookup(TR_INSTANCE *tr, TR_NAME *comm)
+{
+ return NULL;
+}
TR_RP_REALM *rp_realms;
} TR_COMM;
+TR_COMM *tr_comm_lookup(TR_INSTANCE *tr, TR_NAME *comm);
+
#endif
void *cookie;
};
+TR_EXPORT TID_REQ *tid_dup_req (TID_REQ *orig_req);
+
TR_EXPORT TIDC_INSTANCE *tidc_create (void);
TR_EXPORT int tidc_open_connection (TIDC_INSTANCE *tidc, char *server, gss_ctx_id_t *gssctx);
TR_EXPORT int tidc_send_request (TIDC_INSTANCE *tidc, int conn, gss_ctx_id_t gssctx, char *rp_realm, char *realm, char *coi, TIDC_RESP_FUNC *resp_handler, void *cookie);
+TR_EXPORT int tidc_fwd_request (TIDC_INSTANCE *tidc, TID_REQ *req, TIDC_RESP_FUNC *resp_handler, void *cookie);
TR_EXPORT int tids_send_response (TIDS_INSTANCE *tids, int conn, gss_ctx_id_t *gssctx, TID_RESP *resp);
TR_EXPORT void tidc_destroy (TIDC_INSTANCE *tidc);
free(tidc);
}
+TID_REQ *tid_dup_req (TID_REQ *orig_req)
+{
+ TID_REQ *new_req;
+
+ if (NULL == (new_req = malloc(sizeof(TID_REQ))))
+ return NULL;
+
+ /* Memcpy for flat fields, not valid until names are duped. */
+ memcpy(new_req, orig_req, sizeof(TID_REQ));
+
+ new_req->rp_realm = tr_dup_name(orig_req->rp_realm);
+ new_req->realm = tr_dup_name(orig_req->realm);
+ new_req->comm = tr_dup_name(orig_req->comm);
+ new_req->orig_coi = tr_dup_name(orig_req->orig_coi);
+
+ return new_req;
+}
+
int tidc_open_connection (TIDC_INSTANCE *tidc,
char *server,
gss_ctx_id_t *gssctx)
void *cookie)
{
- int err = 0;
- char *req_buf = NULL;
- char *resp_buf = NULL;
- size_t resp_buflen = 0;
- TR_MSG *msg = NULL;
TID_REQ *tid_req = NULL;
- TR_MSG *resp_msg = NULL;
- /* Create and populate a TID msg structure */
- if ((!(msg = malloc(sizeof(TR_MSG)))) ||
- (!(tid_req = malloc(sizeof(TID_REQ)))))
+ /* Create and populate a TID req structure */
+ if (!(tid_req = malloc(sizeof(TID_REQ))))
return -1;
memset(tid_req, 0, sizeof(tid_req));
- msg->msg_type = TID_REQUEST;
-
- msg->tid_req = tid_req;
-
tid_req->conn = conn;
tid_req->gssctx = gssctx;
- /* TBD -- error handling */
- tid_req->rp_realm = tr_new_name(rp_realm);
- tid_req->realm = tr_new_name(realm);
- tid_req->comm = tr_new_name(comm);
+ if ((NULL == (tid_req->rp_realm = tr_new_name(rp_realm))) ||
+ (NULL == (tid_req->realm = tr_new_name(realm))) ||
+ (NULL == (tid_req->comm = tr_new_name(comm)))) {
+ fprintf (stderr, "tidc_send_request: Error duplicating names.\n");
+ return -1;
+ }
tid_req->tidc_dh = tidc->client_dh;
-
tid_req->resp_func = resp_handler;
tid_req->cookie = cookie;
+
+ return (tidc_fwd_request(tidc, tid_req, resp_handler, cookie));
+}
+
+int tidc_fwd_request (TIDC_INSTANCE *tidc,
+ TID_REQ *tid_req,
+ TIDC_RESP_FUNC *resp_handler,
+ void *cookie)
+
+{
+ char *req_buf = NULL;
+ char *resp_buf = NULL;
+ size_t resp_buflen = 0;
+ TR_MSG *msg = NULL;
+ TR_MSG *resp_msg = NULL;
+ int err;
+
+ /* Create and populate a TID msg structure */
+ if (!(msg = malloc(sizeof(TR_MSG))))
+ return -1;
+
+ msg->msg_type = TID_REQUEST;
+ msg->tid_req = tid_req;
/* Encode the request into a json string */
if (!(req_buf = tr_msg_encode(msg))) {
printf ("%s\n", req_buf);
/* Send the request over the connection */
- if (err = gsscon_write_encrypted_token (conn, gssctx, req_buf,
+ if (err = gsscon_write_encrypted_token (tid_req->conn, tid_req->gssctx, req_buf,
strlen(req_buf))) {
fprintf(stderr, "Error sending request over connection.\n");
return -1;
}
- /* TBD -- should queue request on instance, resps read in separate thread */
- /* Read the response from the connection */
+ /* TBD -- queue request on instance, read resps in separate thread */
- if (err = gsscon_read_encrypted_token(conn, gssctx, &resp_buf, &resp_buflen)) {
+ /* Read the response from the connection */
+ /* TBD -- timeout? */
+ if (err = gsscon_read_encrypted_token(tid_req->conn, tid_req->gssctx, &resp_buf, &resp_buflen)) {
if (resp_buf)
free(resp_buf);
return -1;
--- /dev/null
+{"tr_internal":{"max_tree_depth": 4}}
\ No newline at end of file
--- /dev/null
+{
+ "communities": [
+ {
+ "apcs": [],
+ "community_id": "pci-community.ja.net",
+ "idp_realms": [],
+ "rp_realms": [],
+ "type": "apc"
+ },
+ {
+ "apcs": [],
+ "community_id": "community.ja.net",
+ "idp_realms": [],
+ "rp_realms": [],
+ "type": "apc"
+ },
+ {
+ "apcs": [
+ "pci-community.ja.net"
+ ],
+ "community_id": "comm.offcenter.org",
+ "idp_realms": [
+ "idr2.offcenter.org"
+ ],
+ "rp_realms": [
+ "sr3.offcenter.org"
+ ],
+ "type": "coi"
+ }
+ ],
+ "idp_realms": [
+ {
+ "aaa_servers": ["10.1.10.90"],
+ "apcs": ["community.ja.net"],
+ "realm_id": "ja.net",
+ "shared_config": "no"
+ },
+ {
+ "aaa_servers": ["127.0.0.1"],
+ "apcs": ["community.ja.net"],
+ "realm_id": "idr2.offcenter.org",
+ "shared_config": "no"
+ },
+ {
+ "aaa_servers": ["127.0.0.1"],
+ "apcs": ["community.ja.net"],
+ "realm_id": "idr1.offcenter.org",
+ "shared_config": "yes"
+ },
+ {
+ "aaa_servers": ["127.0.0.1"],
+ "apcs": ["community.ja.net"],
+ "realm_id": "no-longer-untitled.offcenter.org",
+ "shared_config": "yes"
+ }
+ ],
+ "rp_clients": [
+ {
+ "filter": {
+ "filter_lines": [
+ {
+ "action": "accept",
+ "domain_constraints": [],
+ "filter_specs": [
+ {
+ "field": "rp_realm",
+ "rp_realm": "*.exchange.ja.net"
+ }
+ ],
+ "realm_constraints": []
+ }
+ ],
+ "type": "rp_permitted"
+ },
+ "gss_names": [
+ "this.is.a.dandy.gss.name@creds.portal.ja.net"
+ ]
+ },
+ {
+ "filter": {
+ "filter_lines": [
+ {
+ "action": "accept",
+ "domain_constraints": [],
+ "filter_specs": [
+ {
+ "field": "rp_realm",
+ "rp_realm": "*.sr3.offcenter.org"
+ }
+ ],
+ "realm_constraints": []
+ }
+ ],
+ "type": "rp_permitted"
+ },
+ "gss_names": [
+ "this.is.a.dandy.gss.name@creds.portal.ja.net"
+ ]
+ },
+ {
+ "filter": {
+ "filter_lines": [
+ {
+ "action": "accept",
+ "domain_constraints": [],
+ "filter_specs": [
+ {
+ "field": "rp_realm",
+ "rp_realm": "*.shell.ja.net"
+ }
+ ],
+ "realm_constraints": []
+ }
+ ],
+ "type": "rp_permitted"
+ },
+ "gss_names": [
+ "this.is.a.dandy.gss.name@creds.portal.ja.net"
+ ]
+ },
+ {
+ "filter": {
+ "filter_lines": [
+ {
+ "action": "accept",
+ "domain_constraints": [],
+ "filter_specs": [
+ {
+ "field": "rp_realm",
+ "rp_realm": "*.sr2.offcenter.org"
+ }
+ ],
+ "realm_constraints": []
+ }
+ ],
+ "type": "rp_permitted"
+ },
+ "gss_names": [
+ "this.is.a.dandy.gss.name@creds.portal.ja.net"
+ ]
+ },
+ {
+ "filter": {
+ "filter_lines": [
+ {
+ "action": "accept",
+ "domain_constraints": [],
+ "filter_specs": [
+ {
+ "field": "rp_realm",
+ "rp_realm": "*.sr1.offcenter.org"
+ }
+ ],
+ "realm_constraints": []
+ }
+ ],
+ "type": "rp_permitted"
+ },
+ "gss_names": [
+ "this.is.a.dandy.gss.name@creds.portal.ja.net"
+ ]
+ },
+ {
+ "filter": {
+ "filter_lines": [
+ {
+ "action": "accept",
+ "domain_constraints": [],
+ "filter_specs": [
+ {
+ "field": "rp_realm",
+ "rp_realm": "*.sr4.offcenter.org"
+ }
+ ],
+ "realm_constraints": []
+ }
+ ],
+ "type": "rp_permitted"
+ },
+ "gss_names": [
+ "this.is.a.dandy.gss.name@creds.portal.ja.net"
+ ]
+ },
+ {
+ "filter": {
+ "filter_lines": [
+ {
+ "action": "accept",
+ "domain_constraints": [],
+ "filter_specs": [
+ {
+ "field": "rp_realm",
+ "rp_realm": "*.billing.ja.net"
+ }
+ ],
+ "realm_constraints": []
+ }
+ ],
+ "type": "rp_permitted"
+ },
+ "gss_names": [
+ "this.is.a.dandy.gss.name@creds.portal.ja.net"
+ ]
+ }
+ ]
+}
+
#include <tr.h>
#include <trust_router/tid.h>
#include <tr_config.h>
+#include <tr_comm.h>
#include <tr_idp.h>
/* Structure to hold TR instance and original request in one cookie */
}
static int tr_tids_req_handler (TIDS_INSTANCE * tids,
- TID_REQ *req,
+ TID_REQ *orig_req,
TID_RESP **resp,
void *tr)
{
- gss_ctx_id_t gssctx;
TIDC_INSTANCE *tidc = NULL;
TR_RESP_COOKIE resp_cookie;
TR_AAA_SERVER *aaa_servers = NULL;
- int conn = 0;
+ TR_NAME *apc = NULL;
+ TID_REQ *req = NULL;
+ TR_COMM *cfg_comm = NULL;
int rc;
- if ((!tids) || (!req) || (!resp) || (!(*resp))) {
+ if ((!tids) || (!orig_req) || (!resp) || (!(*resp))) {
printf("tids_req_handler: Bad parameters\n");
return -1;
}
- printf("Request received! Realm = %s, Comm = %s\n", req->realm->buf, req->comm->buf);
+ printf("Request received! Realm = %s, Comm = %s\n", orig_req->realm->buf, orig_req->comm->buf);
if (tids)
tids->req_count++;
- /* find the AAA server(s) for this request */
- aaa_servers = tr_idp_aaa_server_lookup((TR_INSTANCE *)tids->cookie, req->realm, req->comm);
+ /* Save tr and request info for the response */
+ resp_cookie.tr = tr;
+ resp_cookie.orig_req = req;
+
+ /* Duplicate the request, so we can modify and forward it */
+ if (NULL == (req = tid_dup_req(orig_req))) {
+ fprintf(stderr, "tr_tids_req_handler: Unable to duplicate request.\n");
+ return -1;
+ }
+
+ /* Map the comm in the request from a COI to an APC, if needed */
+ if (NULL == (cfg_comm = tr_comm_lookup((TR_INSTANCE *)tids->cookie, req->comm))) {
+ fprintf(stderr, "tr_tids_req_hander: Request for unknown comm: %s.\n", req->comm->buf);
+ }
+
+ /* TBD -- check that the rp_realm is a member of the original community */
+
+ if (TR_COMM_COI == cfg_comm->type) {
+ /* TBD -- In theory there can be more than one? How would that work? */
+ apc = tr_dup_name(cfg_comm->apcs->id);
+ req->orig_coi = req->comm;
+ req->comm = apc;
+ }
+
+ /* Find the AAA server(s) for this request */
+ aaa_servers = tr_idp_aaa_server_lookup((TR_INSTANCE *)tids->cookie, req->realm, apc);
/* send a TID request to the AAA server(s), and get the answer(s) */
/* TBD -- Handle multiple servers */
}
/* Use the DH parameters from the original request */
+ /* TBD -- this needs to be fixed when we handle more than one req per conn */
tidc->client_dh = req->tidc_dh;
+ /* Save information about this request for the response */
+ resp_cookie.tr = tr;
+ resp_cookie.orig_req = req;
+
/* Set-up TID connection */
- /* TBD -- version of open_connection that takes an inaddr */
- if (-1 == (conn = tidc_open_connection(tidc, inet_ntoa(aaa_servers->aaa_server_addr), &gssctx))) {
+ /* TBD -- handle IPv6 Addresses */
+ if (-1 == (req->conn = tidc_open_connection(tidc, inet_ntoa(aaa_servers->aaa_server_addr), &(req->gssctx)))) {
printf("tr_tids_req_handler: Error in tidc_open_connection.\n");
return -1;
};
/* Send a TID request */
- resp_cookie.tr = tr;
- resp_cookie.orig_req = req;
- /* TBD -- version of send request that takes TR_NAMES? */
- if (0 > (rc = tidc_send_request(tidc, conn, gssctx, req->rp_realm->buf, req->realm->buf, req->comm->buf, &tr_tidc_resp_handler, (void *)&resp_cookie))) {
- printf("Error in tidc_send_request, rc = %d.\n", rc);
+ if (0 > (rc = tidc_fwd_request(tidc, req, &tr_tidc_resp_handler, (void *)&resp_cookie))) {
+ printf("Error from tidc_fwd_request, rc = %d.\n", rc);
return -1;
}