Add TRP handling events, plus change to cfg layout.
authorJennifer Richards <jennifer@painless-security.com>
Thu, 26 May 2016 02:42:13 +0000 (22:42 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Thu, 26 May 2016 18:24:28 +0000 (14:24 -0400)
The main purpose of this commit is to add a stub for TRP event handling.
This currently amounts to listning to a TCP port and replying with a
brief message. Additionally, moved the active and new configurations
in the TR_INSTANCE struct into a container called TR_CFG_MGR. Other
instance types (TIDS, TRPS [new with this commit], and CFGWATCH)
instances now refer to the TR_CFG_MGR rather than to the TR_INSTANCE.
This resolves circular include dependencies and makes for a cycle-free
object hierarchy. Finally, introduced more complete use of talloc
for memory management, though this is probably not complete yet.

17 files changed:
Makefile.am
common/tr_comm.c
common/tr_config.c
include/tid_internal.h
include/tr.h
include/tr_cfgwatch.h
include/tr_config.h
include/tr_tid.h
include/tr_trp.h [new file with mode: 0644]
include/trust_router/tid.h
tid/example/tids_main.c
tid/tids.c
tr/tr.c
tr/tr_cfgwatch.c
tr/tr_main.c
tr/tr_tid.c
tr/tr_trp.c [new file with mode: 0644]

index 5dbd8cb..83a3478 100644 (file)
@@ -30,7 +30,8 @@ common/tr_rp.c \
 tr/tr.c \
 tr/tr_event.c \
 tr/tr_cfgwatch.c \
-tr/tr_tid.c
+tr/tr_tid.c \
+tr/tr_trp.c
 
 tr_trust_router_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
 
@@ -63,6 +64,7 @@ noinst_HEADERS = include/gsscon.h include/tr_config.h \
        include/tr_msg.h include/tr.h \
        include/tr_idp.h include/tr_rp.h \
        include/tr_comm.h include/tr_apc.h \
+       include/tr_tid.h include/tr_trp.h \
        include/tr_filter.h \
        include/tid_internal.h
 
index a471cf4..92bd2e0 100644 (file)
  *
  */
 
-#include <tr.h>
 #include <tr_rp.h>
 #include <trust_router/tr_name.h>
-#include <tr_config.h>
 #include <tr_comm.h>
 #include <tr_debug.h>
 
index f7fdf39..0625790 100644 (file)
@@ -56,23 +56,31 @@ TR_CFG *tr_cfg_new(TALLOC_CTX *mem_ctx)
 
 void tr_cfg_free (TR_CFG *cfg) {
   talloc_free(cfg);
-  return;
 }
 
-TR_CFG_RC tr_apply_new_config (TR_CFG **active_cfg,
-                               TR_CFG **new_cfg)
+TR_CFG_MGR *tr_cfg_mgr_new(TALLOC_CTX *mem_ctx)
 {
-  if ((active_cfg==NULL) || (new_cfg==NULL))
+  return talloc_zero(mem_ctx, TR_CFG_MGR);
+}
+
+void tr_cfg_mgr_free (TR_CFG_MGR *cfg_mgr) {
+  talloc_free(cfg_mgr);
+}
+
+TR_CFG_RC tr_apply_new_config (TR_CFG_MGR *cfg_mgr)
+{
+  /* cfg_mgr->active is allowed to be null, but new cannot be */
+  if ((cfg_mgr==NULL) || (cfg_mgr->new==NULL))
     return TR_CFG_BAD_PARAMS;
 
-  if (*active_cfg != NULL)
-    tr_cfg_free(*active_cfg);
+  if (cfg_mgr->active != NULL)
+    tr_cfg_free(cfg_mgr->active);
 
-  *active_cfg = *new_cfg;
-  *new_cfg=NULL; /* only keep a single handle on the new configuration */
+  cfg_mgr->active = cfg_mgr->new;
+  cfg_mgr->new=NULL; /* only keep a single handle on the new configuration */
 
-  tr_log_threshold((*active_cfg)->internal->log_threshold);
-  tr_console_threshold((*active_cfg)->internal->console_threshold);
+  tr_log_threshold(cfg_mgr->active->internal->log_threshold);
+  tr_console_threshold(cfg_mgr->active->internal->console_threshold);
 
   return TR_CFG_SUCCESS;
 }
@@ -80,7 +88,8 @@ TR_CFG_RC tr_apply_new_config (TR_CFG **active_cfg,
 static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
   json_t *jint = NULL;
   json_t *jmtd = NULL;
-  json_t *jtp = NULL;
+  json_t *jtidsp = NULL;
+  json_t *jtrpsp = NULL;
   json_t *jhname = NULL;
   json_t *jlog = NULL;
   json_t *jconthres = NULL;
@@ -108,17 +117,28 @@ static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
       /* If not configured, use the default */
       trc->internal->max_tree_depth = TR_DEFAULT_MAX_TREE_DEPTH;
     }
-    if (NULL != (jtp = json_object_get(jint, "tids_port"))) {
-      if (json_is_number(jtp)) {
-       trc->internal->tids_port = json_integer_value(jtp);
+    if (NULL != (jtidsp = json_object_get(jint, "tids_port"))) {
+      if (json_is_number(jtidsp)) {
+       trc->internal->tids_port = json_integer_value(jtidsp);
       } else {
-       tr_debug("tr_cfg_parse_internal: Parsing error, port is not a number.");
+       tr_debug("tr_cfg_parse_internal: Parsing error, tids_port is not a number.");
        return TR_CFG_NOPARSE;
       }
     } else {
       /* If not configured, use the default */
       trc->internal->tids_port = TR_DEFAULT_TIDS_PORT;
     }
+    if (NULL != (jtrpsp = json_object_get(jint, "trps_port"))) {
+      if (json_is_number(jtrpsp)) {
+       trc->internal->trps_port = json_integer_value(jtrpsp);
+      } else {
+       tr_debug("tr_cfg_parse_internal: Parsing error, trps_port is not a number.");
+       return TR_CFG_NOPARSE;
+      }
+    } else {
+      /* If not configured, use the default */
+      trc->internal->trps_port = TR_DEFAULT_TRPS_PORT;
+    }
     if (NULL != (jhname = json_object_get(jint, "hostname"))) {
       if (json_is_string(jhname)) {
        trc->internal->hostname = json_string_value(jhname);
@@ -675,8 +695,8 @@ static TR_IDP_REALM *tr_cfg_parse_comm_idps (TR_CFG *trc, json_t *jidps, TR_CFG_
 
   for (i = 0; i < json_array_size(jidps); i++) {
     if (NULL == (temp_idp = (tr_cfg_find_idp(trc, 
-                                            tr_new_name((char *)json_string_value(json_array_get(jidps, i))), 
-                                            rc)))) {
+                                             tr_new_name((char *)json_string_value(json_array_get(jidps, i))), 
+                                             rc)))) {
       tr_debug("tr_cfg_parse_comm_idps: Unknown IDP %s.", 
              (char *)json_string_value(json_array_get(jidps, i)));
       return NULL;
@@ -881,53 +901,74 @@ TR_CFG_RC tr_cfg_validate (TR_CFG *trc) {
 
 /* Join two paths and return a pointer to the result. This should be freed
  * via talloc_free. Returns NULL on failure. */
-static char *join_paths(const char *p1, const char *p2) {
-  return talloc_asprintf(NULL, "%s/%s", p1, p2); /* returns NULL on a failure */
+static char *join_paths(TALLOC_CTX *mem_ctx, const char *p1, const char *p2) {
+  return talloc_asprintf(mem_ctx, "%s/%s", p1, p2); /* returns NULL on a failure */
 }
 
 /* Reads configuration files in config_dir ("" or "./" will use the current directory). */
-TR_CFG_RC tr_parse_config (TR_CFG *new_cfg, const char *config_dir, int n, struct dirent **cfg_files) {
+TR_CFG_RC tr_parse_config (TR_CFG_MGR *cfg_mgr, const char *config_dir, int n, struct dirent **cfg_files)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   json_t *jcfg;
   json_error_t rc;
   char *file_with_path;
   int ii;
+  TR_CFG_RC cfg_rc=TR_CFG_ERROR;
 
-  if ((!new_cfg) || (!cfg_files) || (n<=0))
-    return TR_CFG_BAD_PARAMS;
+  if ((!cfg_mgr) || (!cfg_files) || (n<=0)) {
+    cfg_rc=TR_CFG_BAD_PARAMS;
+    goto cleanup;
+  }
+
+  if (cfg_mgr->new != NULL)
+    tr_cfg_free(cfg_mgr->new);
+  cfg_mgr->new=tr_cfg_new(tmp_ctx); /* belongs to the temporary context for now */
+  if (cfg_mgr->new == NULL) {
+    cfg_rc=TR_CFG_NOMEM;
+    goto cleanup;
+  }
 
   /* Parse configuration information from each config file */
   for (ii=0; ii<n; ii++) {
-    file_with_path=join_paths(config_dir, cfg_files[ii]->d_name); /* must free result with talloc_free */
+    file_with_path=join_paths(tmp_ctx, config_dir, cfg_files[ii]->d_name); /* must free result with talloc_free */
     if(file_with_path == NULL) {
       tr_crit("tr_parse_config: error joining path.");
-      return TR_CFG_NOMEM;
+      cfg_rc=TR_CFG_NOMEM;
+      goto cleanup;
     }
     tr_debug("tr_parse_config: Parsing %s.", cfg_files[ii]->d_name); /* print the filename without the path */
     if (NULL == (jcfg = json_load_file(file_with_path, 
                                        JSON_DISABLE_EOF_CHECK, &rc))) {
       tr_debug("tr_parse_config: Error parsing config file %s.", 
                cfg_files[ii]->d_name);
-      talloc_free(file_with_path);
-      return TR_CFG_NOPARSE;
+      cfg_rc=TR_CFG_NOPARSE;
+      goto cleanup;
     }
-    talloc_free(file_with_path); /* done with filename */
-
-    if ((TR_CFG_SUCCESS != tr_cfg_parse_internal(new_cfg, jcfg)) ||
-        (TR_CFG_SUCCESS != tr_cfg_parse_rp_clients(new_cfg, jcfg)) ||
-        (TR_CFG_SUCCESS != tr_cfg_parse_idp_realms(new_cfg, jcfg)) ||
-        (TR_CFG_SUCCESS != tr_cfg_parse_default_servers(new_cfg, jcfg)) ||
-        (TR_CFG_SUCCESS != tr_cfg_parse_comms(new_cfg, jcfg))) {
-      return TR_CFG_ERROR;
+
+    if ((TR_CFG_SUCCESS != tr_cfg_parse_internal(cfg_mgr->new, jcfg)) ||
+        (TR_CFG_SUCCESS != tr_cfg_parse_rp_clients(cfg_mgr->new, jcfg)) ||
+        (TR_CFG_SUCCESS != tr_cfg_parse_idp_realms(cfg_mgr->new, jcfg)) ||
+        (TR_CFG_SUCCESS != tr_cfg_parse_default_servers(cfg_mgr->new, jcfg)) ||
+        (TR_CFG_SUCCESS != tr_cfg_parse_comms(cfg_mgr->new, jcfg))) {
+      cfg_rc=TR_CFG_ERROR;
+      goto cleanup;
     }
   }
 
   /* make sure we got a complete, consistent configuration */
-  if (TR_CFG_SUCCESS != tr_cfg_validate(new_cfg)) {
+  if (TR_CFG_SUCCESS != tr_cfg_validate(cfg_mgr->new)) {
     tr_err("tr_parse_config: Error: INVALID CONFIGURATION");
-    return TR_CFG_ERROR;
+    cfg_rc=TR_CFG_ERROR;
+    goto cleanup;
   }
 
-  return TR_CFG_SUCCESS;
+  /* success! */
+  talloc_steal(cfg_mgr, cfg_mgr->new); /* hand this over to the cfg_mgr context */
+  cfg_rc=TR_CFG_SUCCESS;
+
+cleanup:
+  talloc_free(tmp_ctx);
+  return cfg_rc;
 }
 
 TR_IDP_REALM *tr_cfg_find_idp (TR_CFG *tr_cfg, TR_NAME *idp_id, TR_CFG_RC *rc)
@@ -1008,20 +1049,14 @@ static int is_cfg_file(const struct dirent *dent) {
  * by scandir(). These can be freed with tr_free_config_file_list().
  */
 int tr_find_config_files (const char *config_dir, struct dirent ***cfg_files) {
-  int n = 0, ii = 0;
+  int n = 0;
   
   n = scandir(config_dir, cfg_files, is_cfg_file, alphasort);
 
   if (n < 0) {
     perror("scandir");
     tr_debug("tr_find_config: scandir error trying to scan %s.", config_dir);
-  } else if (n == 0) {
-    tr_debug("tr_find_config: No config files found.");
-  } else {
-    for (ii=0; ii<n; ii++) {
-      tr_debug("tr_find_config: Config file found (%s).", (*cfg_files)[ii]->d_name);
-    }
-  }
+  } 
 
   return n;
 }
index 8502185..6fa8e38 100644 (file)
@@ -35,8 +35,9 @@
 #ifndef TID_INTERNAL_H
 #define TID_INTERNAL_H
 #include <glib.h>
-#include <trust_router/tid.h>
 
+#include <tr_rp.h>
+#include <trust_router/tid.h>
 #include <jansson.h>
 
 struct tid_srvr_blk {
@@ -97,6 +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 */
 };
 
 
index 9d75fa5..8878161 100644 (file)
 #ifndef TR_H
 #define TR_H
 
+#include <talloc.h>
+
 #include <tid_internal.h>
 #include <trust_router/tr_name.h>
 #include <tr_msg.h>
 #include <tr_rp.h>
+#include <tr_trp.h>
+#include <tr_cfgwatch.h>
 #include <tr_config.h>
 
 typedef struct tr_instance {
-  struct tr_cfg *new_cfg;      /* unapplied configuration */
-  struct tr_cfg *active_cfg;
+  TR_CFG_MGR *cfg_mgr;
   TIDS_INSTANCE *tids;
-  struct tr_rp_client *rp_gss;         /* Client matching GSS name, TBD -- FIX ME */
+  TRPS_INSTANCE *trps;
+  TR_CFGWATCH *cfgwatch;
 } TR_INSTANCE;
 
-TR_INSTANCE *tr_create(void);
+TR_INSTANCE *tr_create(TALLOC_CTX *mem_ctx);
 void tr_destroy(TR_INSTANCE *tr);
 
 #endif
index 92ad9cb..434202f 100644 (file)
@@ -5,8 +5,6 @@
 #include <time.h>
 #include <sys/time.h>
 
-#include <tr.h>
-
 
 struct tr_fstat {
   char *name;
@@ -21,8 +19,7 @@ struct tr_cfgwatch_data {
   int n_files; /* number of files in fstat_list */
   int change_detected; /* have we detected a change? */
   struct timeval last_change_detected; /* when did we last note a changed mtime? */
-  TALLOC_CTX *ctx; /* what context should own configuration talloc blocks? */
-  TR_INSTANCE *tr; /* what trust router are we updating? */
+  TR_CFG_MGR *cfg_mgr; /* what trust router config are we updating? */
 };
 typedef struct tr_cfgwatch_data TR_CFGWATCH;
 
index 8bc905a..af58db9 100644 (file)
 #include <syslog.h>
 #include <talloc.h>
 
-#include <tr.h>
+#include <tr_comm.h>
 #include <tr_rp.h>
 #include <tr_idp.h>
-#include <tr_comm.h>
 
 #define TR_DEFAULT_MAX_TREE_DEPTH 12
 #define TR_DEFAULT_TR_PORT 12308
 #define TR_DEFAULT_TIDS_PORT 12309
+#define TR_DEFAULT_TRPS_PORT 12310
 #define TR_DEFAULT_LOG_THRESHOLD LOG_INFO
 #define TR_DEFAULT_CONSOLE_THRESHOLD LOG_NOTICE
 
@@ -57,12 +57,13 @@ typedef enum tr_cfg_rc {
   TR_CFG_ERROR,                /* General processing error */
   TR_CFG_BAD_PARAMS,   /* Bad parameters passed to tr_config function */
   TR_CFG_NOPARSE,      /* Parsing error */
-  TR_CFG_NOMEM         /* Memory allocation error */
+  TR_CFG_NOMEM,                /* Memory allocation error */
 } TR_CFG_RC;
 
 typedef struct tr_cfg_internal {
   unsigned int max_tree_depth;
   unsigned int tids_port;
+  unsigned int trps_port;
   const char *hostname;
   int log_threshold;
   int console_threshold;
@@ -81,16 +82,23 @@ typedef struct tr_cfg {
   /* TBD -- Trust Links */
 } TR_CFG;
 
+typedef struct tr_cfg_mgr {
+  TR_CFG *active;
+  TR_CFG *new;
+} TR_CFG_MGR;
+
 int tr_find_config_files (const char *config_dir, struct dirent ***cfg_files);
 void tr_free_config_file_list(int n, struct dirent ***cfg_files);
-TR_CFG_RC tr_parse_config (TR_CFG *new_cfg, const char *config_dir, int n, struct dirent **cfg_files);
-TR_CFG_RC tr_apply_new_config (TR_CFG **active_cfg, TR_CFG **new_cfg);
+TR_CFG_RC tr_parse_config (TR_CFG_MGR *cfg_mgr, const char *config_dir, int n, struct dirent **cfg_files);
+TR_CFG_RC tr_apply_new_config (TR_CFG_MGR *cfg_mgr);
 TR_CFG_RC tr_cfg_validate (TR_CFG *trc);
 TR_CFG *tr_cfg_new(TALLOC_CTX *mem_ctx);
+TR_CFG_MGR *tr_cfg_mgr_new(TALLOC_CTX *mem_ctx);
 void tr_cfg_free(TR_CFG *cfg);
+void tr_cfg_mgr_free(TR_CFG_MGR *cfg);
 void tr_print_config(FILE *stream, TR_CFG *cfg);
 
-TR_IDP_REALM *tr_cfg_find_idp (TR_CFG *tr_cfg, TR_NAME *idp_id, TR_CFG_RC *rc);
-TR_RP_CLIENT *tr_cfg_find_rp (TR_CFG *tr_cfg, TR_NAME *rp_gss, TR_CFG_RC *rc);
+TR_IDP_REALM *tr_cfg_find_idp (TR_CFG *cfg, TR_NAME *idp_id, TR_CFG_RC *rc);
+TR_RP_CLIENT *tr_cfg_find_rp (TR_CFG *cfg, TR_NAME *rp_gss, TR_CFG_RC *rc);
 
 #endif
index e846437..fd01a10 100644 (file)
@@ -1,9 +1,12 @@
 #ifndef TR_TID_H
 #define TR_TID_H
 
-#include <tr.h>
 #include <tr_event.h>
+#include <tr_config.h>
 
-int tr_tids_event_init(struct event_base *base, TR_INSTANCE *tr, struct tr_socket_event *tids_ev);
+int tr_tids_event_init(struct event_base *base,
+                       TIDS_INSTANCE *tids,
+                       TR_CFG_MGR *cfg_mgr,
+                       struct tr_socket_event *tids_ev);
 
 #endif /* TR_TID_H */
diff --git a/include/tr_trp.h b/include/tr_trp.h
new file mode 100644 (file)
index 0000000..3ec12dc
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef TR_TRP_H
+#define TR_TRP_H
+
+#include <talloc.h>
+
+#include <tr_config.h>
+#include <tr_event.h>
+
+
+typedef struct trp_req {
+  int msg;
+} TRP_REQ;
+
+typedef struct trp_resp {
+  int msg;
+} TRP_RESP;
+
+typedef struct trps_instance TRPS_INSTANCE;
+
+typedef int (TRPS_REQ_FUNC)(TRPS_INSTANCE *, TRP_REQ *, TRP_RESP *, void *);
+typedef void (TRPS_RESP_FUNC)(TRPS_INSTANCE *, TRP_REQ *, TRP_RESP *, void *);
+typedef int (trps_auth_func)(gss_name_t client_name, TR_NAME *display_name, void *cookie);
+
+
+/* TRP Server Instance Data */
+struct trps_instance {
+  char *hostname;
+  unsigned int port;
+  TRPS_REQ_FUNC *req_handler;
+  trps_auth_func *auth_handler;
+  void *cookie;
+  struct tr_rp_client *rp_gss;         /* Client matching GSS name, TBD -- FIX ME (??) */
+};
+
+
+/* prototypes */
+TRPS_INSTANCE *trps_create (TALLOC_CTX *mem_ctx);
+void trps_destroy (TRPS_INSTANCE *trps);
+int tr_trps_event_init(struct event_base *base, TRPS_INSTANCE *trps, TR_CFG_MGR *cfg_mgr,
+                       struct tr_socket_event *trps_ev);
+int trps_accept(TRPS_INSTANCE *trps, int listen);
+
+#endif /* TR_TRP_H */
index d87e0e0..613541f 100644 (file)
@@ -35,6 +35,8 @@
 #ifndef TID_H
 #define TID_H
 
+#include <talloc.h>
+
 #include <arpa/inet.h>
 #include <openssl/dh.h>
 
@@ -144,7 +146,7 @@ TR_EXPORT DH *tidc_set_dh(TIDC_INSTANCE *, DH *);
 TR_EXPORT void tidc_destroy (TIDC_INSTANCE *tidc);
 
 /* TID Server functions, in tid/tids.c */
-TR_EXPORT TIDS_INSTANCE *tids_create (void);
+TR_EXPORT TIDS_INSTANCE *tids_create (TALLOC_CTX *mem_ctx);
 TR_EXPORT int tids_start (TIDS_INSTANCE *tids, TIDS_REQ_FUNC *req_handler,
                          tids_auth_func *auth_handler, const char *hostname, 
                          unsigned int port, void *cookie);
index dd60f8e..c334f41 100644 (file)
@@ -375,7 +375,7 @@ int main (int argc,
                     -1, &authorization_insert, NULL);
 
   /* Create a TID server instance */
-  if (NULL == (tids = tids_create())) {
+  if (NULL == (tids = tids_create(NULL))) {
     tr_crit("Unable to create TIDS instance, exiting.");
     return 1;
   }
index 02bc6f6..14c708d 100644 (file)
@@ -141,8 +141,9 @@ static int tids_auth_cb(gss_name_t clientName, gss_buffer_t displayName,
 }
 
 /* returns 0 on authorization success, 1 on failure, or -1 in case of error */
-static int tids_auth_connection (struct tids_instance *inst,
-                                int conn, gss_ctx_id_t *gssctx)
+static int tids_auth_connection (TIDS_INSTANCE *inst,
+                                int conn,
+                                 gss_ctx_id_t *gssctx)
 {
   int rc = 0;
   int auth, autherr = 0;
@@ -153,7 +154,7 @@ static int tids_auth_connection (struct tids_instance *inst,
   nameLen = asprintf(&name, "trustidentity@%s", inst->hostname);
   nameBuffer.length = nameLen;
   nameBuffer.value = name;
-  
+
   if (rc = gsscon_passive_authenticate(conn, nameBuffer, gssctx, tids_auth_cb, inst)) {
     tr_debug("tids_auth_connection: Error from gsscon_passive_authenticate(), rc = %d.", rc);
     return -1;
@@ -365,12 +366,9 @@ static void tids_handle_connection (TIDS_INSTANCE *tids, int conn)
   } 
 }
 
-TIDS_INSTANCE *tids_create (void)
+TIDS_INSTANCE *tids_create (TALLOC_CTX *mem_ctx)
 {
-  TIDS_INSTANCE *tids = NULL;
-  if (tids = malloc(sizeof(TIDS_INSTANCE)))
-    memset(tids, 0, sizeof(TIDS_INSTANCE));
-  return tids;
+  return talloc_zero(mem_ctx, TIDS_INSTANCE);
 }
 
 /* Get a listener for tids requests, returns its socket fd. Accept
diff --git a/tr/tr.c b/tr/tr.c
index 09438f7..bd3ce0a 100644 (file)
--- a/tr/tr.c
+++ b/tr/tr.c
 
 #include <stdlib.h>
 #include <string.h>
+#include <talloc.h>
 #include <tr.h>
+#include <tr_config.h>
 
-TR_INSTANCE *tr_create() {
-  TR_INSTANCE *tr = NULL;
-  if (tr = malloc(sizeof(TR_INSTANCE)))
-    memset(tr, 0, sizeof(TR_INSTANCE));
+TR_INSTANCE *tr_create(TALLOC_CTX *mem_ctx) {
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TR_INSTANCE *tr=talloc_zero(tmp_ctx, TR_INSTANCE);
+  if (tr != NULL) {
+    tr->cfg_mgr=tr_cfg_mgr_new(tr);
+    if (tr->cfg_mgr != NULL) {
+      /* success, hand over ownership */
+      talloc_steal(mem_ctx, tr);
+    }
+  }
+  talloc_free(tmp_ctx);
   return tr;
 }
 
 void tr_destroy(TR_INSTANCE *tr) {
-  free (tr);
+  talloc_free (tr);
 }
index 3439112..6e98651 100644 (file)
@@ -14,21 +14,10 @@ TR_CFGWATCH *tr_cfgwatch_create(TALLOC_CTX *mem_ctx)
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_CFGWATCH *new_cfg;
   
-  new_cfg=talloc(tmp_ctx, TR_CFGWATCH);
+  new_cfg=talloc_zero(tmp_ctx, TR_CFGWATCH);
   if (new_cfg == NULL) {
     tr_debug("tr_cfgwatch_create: Allocation failed.");
-  } else {
-    timerclear(&new_cfg->poll_interval);
-    timerclear(&new_cfg->settling_time);
-    new_cfg->config_dir=NULL;
-    new_cfg->fstat_list=NULL;
-    new_cfg->n_files=0;
-    new_cfg->change_detected=0;
-    timerclear(&new_cfg->last_change_detected);
-    new_cfg->ctx=NULL;
-    new_cfg->tr=NULL;
-  }
-
+  } 
   talloc_steal(mem_ctx, new_cfg);
   talloc_free(tmp_ctx);
   return new_cfg;
@@ -142,7 +131,7 @@ static int tr_cfgwatch_update_needed(TR_CFGWATCH *cfg_status)
     talloc_free(cfg_status->fstat_list);
     cfg_status->n_files=n_files;
     cfg_status->fstat_list=fstat_list;
-    talloc_steal(cfg_status->ctx, fstat_list);
+    talloc_steal(cfg_status, fstat_list);
     goto cleanup;
   }
 
@@ -154,7 +143,7 @@ static int tr_cfgwatch_update_needed(TR_CFGWATCH *cfg_status)
       talloc_free(cfg_status->fstat_list);
       cfg_status->n_files=n_files;
       cfg_status->fstat_list=fstat_list;
-      talloc_steal(cfg_status->ctx, fstat_list);
+      talloc_steal(cfg_status, fstat_list);
       goto cleanup;
     }
   }
@@ -164,6 +153,7 @@ static int tr_cfgwatch_update_needed(TR_CFGWATCH *cfg_status)
   talloc_free(tmp_ctx);
   return update_needed;
 }
+
 /* must specify the ctx and tr in cfgwatch! */
 int tr_read_and_apply_config(TR_CFGWATCH *cfgwatch)
 {
@@ -193,27 +183,17 @@ int tr_read_and_apply_config(TR_CFGWATCH *cfgwatch)
     retval=1; goto cleanup;
   }
   
-  /* allocate a new configuration, dumping an old one if needed */
-  if(cfgwatch->tr->new_cfg != NULL)
-    tr_cfg_free(cfgwatch->tr->new_cfg);
-  cfgwatch->tr->new_cfg=tr_cfg_new(tmp_ctx);
-  if (cfgwatch->tr->new_cfg==NULL) {
-    tr_debug("tr_read_and_apply_config: Error allocating new_cfg.");
-    retval=1; goto cleanup;
-  }
-  /* now fill it in */
-  if (TR_CFG_SUCCESS != (rc = tr_parse_config(cfgwatch->tr->new_cfg, config_dir, n_files, cfg_files))) {
+  /* now fill it in (tr_parse_config allocates space for new config) */
+  if (TR_CFG_SUCCESS != (rc = tr_parse_config(cfgwatch->cfg_mgr, config_dir, n_files, cfg_files))) {
     tr_debug("tr_read_and_apply_config: Error parsing configuration information, rc=%d.", rc);
     retval=1; goto cleanup;
   }
 
-  /* apply initial configuration (frees active_cfg and resets new_cfg to NULL) */
-  if (TR_CFG_SUCCESS != (rc = tr_apply_new_config(&cfgwatch->tr->active_cfg,
-                                                 &cfgwatch->tr->new_cfg))) {
+  /* apply new configuration (nulls new, manages context ownership) */
+  if (TR_CFG_SUCCESS != (rc = tr_apply_new_config(cfgwatch->cfg_mgr))) {
     tr_debug("tr_read_and_apply_config: Error applying configuration, rc = %d.", rc);
     retval=1; goto cleanup;
   }
-  talloc_steal(cfgwatch->ctx, cfgwatch->tr->active_cfg); /* hand over ownership */
 
   /* give ownership of the new_fstat_list to caller's context */
   if (cfgwatch->fstat_list != NULL) {
@@ -222,13 +202,13 @@ int tr_read_and_apply_config(TR_CFGWATCH *cfgwatch)
   }
   cfgwatch->n_files=n_files;
   cfgwatch->fstat_list=new_fstat_list;
-  talloc_steal(cfgwatch->ctx, new_fstat_list);
+  talloc_steal(cfgwatch, new_fstat_list);
   new_fstat_list=NULL;
 
  cleanup:
   tr_free_config_file_list(n_files, &cfg_files);
   talloc_free(tmp_ctx);
-  cfgwatch->tr->new_cfg=NULL; /* this has been freed, either explicitly or with tmp_ctx */
+  cfgwatch->cfg_mgr->new=NULL; /* this has been freed, either explicitly or with tmp_ctx */
   return retval;
 }
 
@@ -240,12 +220,10 @@ static void tr_cfgwatch_event_cb(int listener, short event, void *arg)
 
   if (tr_cfgwatch_update_needed(cfg_status)) {
     tr_notice("Configuration file change detected, waiting for changes to settle.");
-    /*    if (!cfg_status->change_detected) {*/
-      cfg_status->change_detected=1;
+    cfg_status->change_detected=1;
 
-      if (0 != gettimeofday(&cfg_status->last_change_detected, NULL)) {
-        tr_err("tr_cfgwatch_event_cb: gettimeofday() failed (1).");
-        /*      }*/
+    if (0 != gettimeofday(&cfg_status->last_change_detected, NULL)) {
+      tr_err("tr_cfgwatch_event_cb: gettimeofday() failed (1).");
     }
   }
 
index e81aab4..5b2559f 100644 (file)
@@ -43,6 +43,7 @@
 #include <tr.h>
 #include <tid_internal.h>
 #include <tr_tid.h>
+#include <tr_trp.h>
 #include <tr_config.h>
 #include <tr_event.h>
 #include <tr_cfgwatch.h>
@@ -112,9 +113,8 @@ int main (int argc, char *argv[])
   TR_INSTANCE *tr = NULL;
   struct cmdline_args opts;
   struct event_base *ev_base;
-  struct tr_socket_event tids_ev;
+  struct tr_socket_event tids_ev, trps_ev;
   struct event *cfgwatch_ev;
-  TR_CFGWATCH *cfgwatch; /* config file watcher status */
 
   /* Use standalone logging */
   tr_log_open();
@@ -129,34 +129,37 @@ int main (int argc, char *argv[])
   /* process options */
   remove_trailing_slash(opts.config_dir);
 
-  /* Get a configuration status object */
-  cfgwatch=tr_cfgwatch_create(main_ctx);
-  if (cfgwatch == NULL) {
-    tr_crit("Unable to create configuration watcher object, exiting.");
-    return 1;
-  }
-  
   /***** create a Trust Router instance *****/
-  if (NULL == (tr = tr_create())) {
+  if (NULL == (tr = tr_create(main_ctx))) {
     tr_crit("Unable to create Trust Router instance, exiting.");
     return 1;
   }
 
   /***** process configuration *****/
-  cfgwatch->config_dir=opts.config_dir;
-  cfgwatch->ctx=main_ctx;
-  cfgwatch->tr=tr;
-  if (0 != tr_read_and_apply_config(cfgwatch)) {
+  tr->cfgwatch=tr_cfgwatch_create(tr);
+  if (tr->cfgwatch == NULL) {
+    tr_crit("Unable to create configuration watcher object, exiting.");
+    return 1;
+  }
+  tr->cfgwatch->config_dir=opts.config_dir;
+  tr->cfgwatch->cfg_mgr=tr->cfg_mgr;
+  if (0 != tr_read_and_apply_config(tr->cfgwatch)) {
     tr_crit("Error reading configuration, exiting.");
     return 1;
   }
 
   /***** initialize the trust path query server instance *****/
-  if (0 == (tr->tids = tids_create ())) {
+  if (0 == (tr->tids = tids_create (tr))) {
     tr_crit("Error initializing Trust Path Query Server instance.");
     return 1;
   }
 
+  /***** initialize the trust router protocol server instance *****/
+  if (0 == (tr->trps = trps_create (tr))) {
+    tr_crit("Error initializing Trust Router Protocol Server instance.");
+    return 1;
+  }
+
   /***** Set up the event loop *****/
   ev_base=tr_event_loop_init(); /* Set up the event loop */
   if (ev_base==NULL) {
@@ -165,11 +168,12 @@ int main (int argc, char *argv[])
   }
 
   /* install configuration file watching events */
-  cfgwatch->poll_interval=(struct timeval) {1,0}; /* set poll interval in {sec, usec} */
-  cfgwatch->settling_time=(struct timeval) {5,0}; /* delay for changes to settle before updating */
-  
+  tr->cfgwatch->poll_interval=(struct timeval) {1,0}; /* set poll interval in {sec, usec} */
+  tr->cfgwatch->settling_time=(struct timeval) {5,0}; /* delay for changes to settle before updating */
+  /* TODO: pull these settings out of the configuration files */
+
   /* already set config_dir, fstat_list and n_files earlier */
-  if (0 != tr_cfgwatch_event_init(ev_base, cfgwatch, &cfgwatch_ev)) {
+  if (0 != tr_cfgwatch_event_init(ev_base, tr->cfgwatch, &cfgwatch_ev)) {
     tr_crit("Error initializing configuration file watcher.");
     return 1;
   }
@@ -177,19 +181,27 @@ int main (int argc, char *argv[])
   /*tr_status_event_init();*/ /* install status reporting events */
 
   /* install TID server events */
-  if (0 != tr_tids_event_init(ev_base, tr, &tids_ev)) {
+  if (0 != tr_tids_event_init(ev_base,
+                              tr->tids,
+                              tr->cfg_mgr,
+                             &tids_ev)) {
     tr_crit("Error initializing Trust Path Query Server instance.");
     return 1;
   }
 
-  /*tr_trp_event_init();*/ /* install TRP handler events */
+  /* install TRP handler events */
+  if (0 != tr_trps_event_init(ev_base,
+                              tr->trps,
+                              tr->cfg_mgr,
+                             &trps_ev)) {
+    tr_crit("Error initializing Trust Path Query Server instance.");
+    return 1;
+  }
 
-  fflush(stdout); fflush(stderr);
   tr_event_loop_run(ev_base); /* does not return until we are done */
 
-  /* TODO: update the cleanup code */
-  tids_destroy(tr->tids);
-  tr_destroy(tr);
+  /* TODO: ensure talloc is properly used so this actually works */
+  tr_destroy(tr); /* thanks to talloc, should destroy everything */
 
   talloc_free(main_ctx);
   return 0;
index fbaead4..c03e80a 100644 (file)
@@ -1,4 +1,3 @@
-#include <tr.h>
 #include <tid_internal.h>
 #include <tr_filter.h>
 #include <tr_comm.h>
@@ -7,14 +6,21 @@
 #include <tr_event.h>
 #include <tr_debug.h>
 #include <gsscon.h>
+#include <tr_config.h>
 #include <tr_tid.h>
 
 /* Structure to hold TR instance and original request in one cookie */
 typedef struct tr_resp_cookie {
-  TR_INSTANCE *tr;
+  TIDS_INSTANCE *tids;
   TID_REQ *orig_req;
 } TR_RESP_COOKIE;
 
+/* hold a tids instance and a config manager */
+struct tr_tids_event_cookie {
+  TIDS_INSTANCE *tids;
+  TR_CFG_MGR *cfg_mgr;
+};
+
 
 static void tr_tidc_resp_handler (TIDC_INSTANCE *tidc, 
                                   TID_REQ *req,
@@ -25,7 +31,7 @@ static void tr_tidc_resp_handler (TIDC_INSTANCE *tidc,
   req->resp_rcvd = 1;
 
   /* TBD -- handle concatentation of multiple responses to single req */
-  tids_send_response(((TR_RESP_COOKIE *)resp_cookie)->tr->tids, 
+  tids_send_response(((TR_RESP_COOKIE *)resp_cookie)->tids, 
                     ((TR_RESP_COOKIE *)resp_cookie)->orig_req, 
                     resp);
   
@@ -33,9 +39,9 @@ static void tr_tidc_resp_handler (TIDC_INSTANCE *tidc,
 }
 
 static int tr_tids_req_handler (TIDS_INSTANCE *tids,
-                     TID_REQ *orig_req, 
-                     TID_RESP *resp,
-                     void *tr_in)
+                                TID_REQ *orig_req, 
+                                TID_RESP *resp,
+                                void *cookie_in)
 {
   TIDC_INSTANCE *tidc = NULL;
   TR_RESP_COOKIE resp_cookie;
@@ -44,20 +50,20 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
   TID_REQ *fwd_req = NULL;
   TR_COMM *cfg_comm = NULL;
   TR_COMM *cfg_apc = NULL;
-  TR_INSTANCE *tr = (TR_INSTANCE *) tr_in;
   int oaction = TR_FILTER_ACTION_REJECT;
   int rc = 0;
   time_t expiration_interval;
+  struct tr_tids_event_cookie *cookie=(struct tr_tids_event_cookie *)cookie_in;
+  TR_CFG_MGR *cfg_mgr=cookie->cfg_mgr;
 
-  if ((!tids) || (!orig_req) || (!resp) ||  (!tr)) {
+  if ((!tids) || (!orig_req) || (!resp)) {
     tr_debug("tr_tids_req_handler: Bad parameters");
     return -1;
   }
 
   tr_debug("tr_tids_req_handler: Request received (conn = %d)! Realm = %s, Comm = %s", orig_req->conn, 
-        orig_req->realm->buf, orig_req->comm->buf);
-  if (tids)
-    tids->req_count++;
+           orig_req->realm->buf, orig_req->comm->buf);
+  tids->req_count++;
 
   /* Duplicate the request, so we can modify and forward it */
   if (NULL == (fwd_req = tid_dup_req(orig_req))) {
@@ -65,7 +71,7 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
     return -1;
   }
 
-  if (NULL == (cfg_comm = tr_comm_lookup(tids->cookie, orig_req->comm))) {
+  if (NULL == (cfg_comm = tr_comm_lookup(cfg_mgr->active->comms, orig_req->comm))) {
     tr_notice("tr_tids_req_hander: Request for unknown comm: %s.", orig_req->comm->buf);
     tids_send_err_response(tids, orig_req, "Unknown community");
     return -1;
@@ -74,14 +80,18 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
   /* Check that the rp_realm matches the filter for the GSS name that 
    * was received. */
 
-  if ((!(tr)->rp_gss) || 
-      (!(tr)->rp_gss->filter)) {
+  if ((!tids->rp_gss) || 
+      (!tids->rp_gss->filter)) {
     tr_notice("tr_tids_req_handler: No GSS name for incoming request.");
     tids_send_err_response(tids, orig_req, "No GSS name for request");
     return -1;
   }
 
-  if ((TR_FILTER_NO_MATCH == tr_filter_process_rp_permitted(orig_req->rp_realm, (tr)->rp_gss->filter, orig_req->cons, &fwd_req->cons, &oaction)) ||
+  if ((TR_FILTER_NO_MATCH == tr_filter_process_rp_permitted(orig_req->rp_realm,
+                                                            tids->rp_gss->filter,
+                                                            orig_req->cons,
+                                                           &fwd_req->cons,
+                                                           &oaction)) ||
       (TR_FILTER_ACTION_REJECT == 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");
@@ -106,7 +116,7 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
     apc = tr_dup_name(cfg_comm->apcs->id);
 
     /* Check that the APC is configured */
-    if (NULL == (cfg_apc = tr_comm_lookup(tids->cookie, apc))) {
+    if (NULL == (cfg_apc = tr_comm_lookup(cfg_mgr->active->comms, apc))) {
       tr_notice("tr_tids_req_hander: Request for unknown comm: %s.", apc->buf);
       tids_send_err_response(tids, orig_req, "Unknown APC");
       return -1;
@@ -124,16 +134,16 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
   }
 
   /* Find the AAA server(s) for this request */
-  if (NULL == (aaa_servers = tr_idp_aaa_server_lookup(((TR_INSTANCE *)tids->cookie)->active_cfg->idp_realms, 
-                                                     orig_req->realm, 
-                                                     orig_req->comm))) {
-      tr_debug("tr_tids_req_handler: No AAA Servers for realm %s, defaulting.", orig_req->realm->buf);
-      if (NULL == (aaa_servers = tr_default_server_lookup (((TR_INSTANCE *)tids->cookie)->active_cfg->default_servers,
-                                                          orig_req->comm))) {
-       tr_notice("tr_tids_req_handler: No default AAA servers, discarded.");
-        tids_send_err_response(tids, orig_req, "No path to AAA Server(s) for realm");
-        return -1;
-      }
+  if (NULL == (aaa_servers = tr_idp_aaa_server_lookup(cfg_mgr->active->idp_realms, 
+                                                      orig_req->realm, 
+                                                      orig_req->comm))) {
+    tr_debug("tr_tids_req_handler: No AAA Servers for realm %s, defaulting.", orig_req->realm->buf);
+    if (NULL == (aaa_servers = tr_default_server_lookup (cfg_mgr->active->default_servers,
+                                                         orig_req->comm))) {
+      tr_notice("tr_tids_req_handler: No default AAA servers, discarded.");
+      tids_send_err_response(tids, orig_req, "No path to AAA Server(s) for realm");
+      return -1;
+    }
   } else {
     /* if we aren't defaulting, check idp coi and apc membership */
     if (NULL == (tr_find_comm_idp(cfg_comm, fwd_req->realm))) {
@@ -168,14 +178,14 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
   tidc->client_dh = orig_req->tidc_dh;
 
   /* Save information about this request for the response */
-  resp_cookie.tr = tr;
+  resp_cookie.tids = tids;
   resp_cookie.orig_req = orig_req;
 
   /* Set-up TID connection */
   if (-1 == (fwd_req->conn = tidc_open_connection(tidc, 
-                                                 aaa_servers->hostname->buf,
-                                                 TID_PORT,
-                                             &(fwd_req->gssctx)))) {
+                                                  aaa_servers->hostname->buf,
+                                                  TID_PORT,
+                                                 &(fwd_req->gssctx)))) {
     tr_notice("tr_tids_req_handler: Error in tidc_open_connection.");
     tids_send_err_response(tids, orig_req, "Can't open connection to next hop TIDS");
     return -1;
@@ -194,25 +204,26 @@ static int tr_tids_req_handler (TIDS_INSTANCE *tids,
 }
 
 static int tr_tids_gss_handler(gss_name_t client_name, TR_NAME *gss_name,
-                               void *tr_in)
+                               void *data)
 {
   TR_RP_CLIENT *rp;
-  TR_INSTANCE *tr = (TR_INSTANCE *) tr_in;
+  struct tr_tids_event_cookie *cookie=(struct tr_tids_event_cookie *)data;
+  TIDS_INSTANCE *tids = cookie->tids;
+  TR_CFG_MGR *cfg_mgr = cookie->cfg_mgr;
 
-  if ((!client_name) || (!gss_name) || (!tr)) {
+  if ((!client_name) || (!gss_name) || (!tids) || (!cfg_mgr)) {
     tr_debug("tr_tidc_gss_handler: Bad parameters.");
     return -1;
   }
-  
+
   /* look up the RP client matching the GSS name */
-  if ((NULL == (rp = tr_rp_client_lookup(tr->active_cfg->rp_clients, 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);
     return -1;
   }
 
-  /* Store the rp client in the TR_INSTANCE structure for now... 
-   * TBD -- fix me for new tasking model. */
-  (tr)->rp_gss = rp;
+  /* Store the rp client */
+  tids->rp_gss = rp;
   tr_debug("Client's GSS Name: %s", gss_name->buf);
 
   return 0;
@@ -234,26 +245,45 @@ static void tr_tids_event_cb(int listener, short event, void *arg)
 
 /* Configure the tids instance and set up its event handler.
  * Returns 0 on success, nonzero on failure. Fills in
- * *tids_event (which should be allocated). */
+ * *tids_event (which should be allocated by caller). */
 int tr_tids_event_init(struct event_base *base,
-                       TR_INSTANCE *tr,
+                       TIDS_INSTANCE *tids,
+                       TR_CFG_MGR *cfg_mgr,
                        struct tr_socket_event *tids_ev)
 {
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  struct tr_tids_event_cookie *cookie=NULL;
+  int retval=0;
+
   if (tids_ev == NULL) {
     tr_debug("tr_tids_event_init: Null tids_ev.");
-    return 1;
+    retval=1;
+    goto cleanup;
+  }
+
+  /* Create the cookie for callbacks. We'll put it in the tids context, so it will
+   * be cleaned up when tids is freed by talloc_free. */
+  cookie=talloc(tmp_ctx, struct tr_tids_event_cookie);
+  if (cookie == NULL) {
+    tr_debug("tr_tids_event_init: Unable to allocate cookie.");
+    retval=1;
+    goto cleanup;
   }
+  cookie->tids=tids;
+  cookie->cfg_mgr=cfg_mgr;
+  talloc_steal(tids, cookie);
 
   /* get a tids listener */
-  tids_ev->sock_fd=tids_get_listener(tr->tids,
+  tids_ev->sock_fd=tids_get_listener(tids,
                                      tr_tids_req_handler,
                                      tr_tids_gss_handler,
-                                     tr->active_cfg->internal->hostname,
-                                     tr->active_cfg->internal->tids_port,
-                                     (void *)tr);
+                                     cfg_mgr->active->internal->hostname,
+                                     cfg_mgr->active->internal->tids_port,
+                                     (void *)cookie);
   if (tids_ev->sock_fd < 0) {
     tr_crit("Error opening TID server socket.");
-    return 1;
+    retval=1;
+    goto cleanup;
   }
 
   /* and its event */
@@ -261,8 +291,10 @@ int tr_tids_event_init(struct event_base *base,
                         tids_ev->sock_fd,
                         EV_READ|EV_PERSIST,
                         tr_tids_event_cb,
-                        (void *)tr->tids);
+                        (void *)tids);
   event_add(tids_ev->ev, NULL);
 
-  return 0;
+cleanup:
+  talloc_free(tmp_ctx);
+  return retval;
 }
diff --git a/tr/tr_trp.c b/tr/tr_trp.c
new file mode 100644 (file)
index 0000000..1269c80
--- /dev/null
@@ -0,0 +1,293 @@
+#include <fcntl.h>
+#include <event2/event.h>
+#include <talloc.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <gsscon.h>
+#include <tr_rp.h>
+#include <tr_config.h>
+#include <tr_event.h>
+#include <tr_debug.h>
+#include <tr_trp.h>
+
+/* hold a trps instance and a config manager */
+struct tr_trps_event_cookie {
+  TRPS_INSTANCE *trps;
+  TR_CFG_MGR *cfg_mgr;
+};
+
+
+/********** Ersatz TRPS implementation **********/
+TRPS_INSTANCE *trps_create (TALLOC_CTX *mem_ctx)
+{
+  return talloc_zero(mem_ctx, TRPS_INSTANCE);
+}
+
+void trps_destroy (TRPS_INSTANCE *trps)
+{
+  if (trps)
+    talloc_free(trps);
+}
+
+static int trps_listen (TRPS_INSTANCE *trps, int port) 
+{
+    int rc = 0;
+    int conn = -1;
+    int optval = 1;
+
+    union {
+      struct sockaddr_storage storage;
+      struct sockaddr_in in4;
+    } addr;
+
+    struct sockaddr_in *saddr = (struct sockaddr_in *) &addr.in4;
+
+    saddr->sin_port = htons (port);
+    saddr->sin_family = AF_INET;
+    saddr->sin_addr.s_addr = INADDR_ANY;
+
+    if (0 > (conn = socket (AF_INET, SOCK_STREAM, 0)))
+      return conn;
+
+    setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+
+    if (0 > (rc = bind (conn, (struct sockaddr *) saddr, sizeof(struct sockaddr_in))))
+      return rc;
+
+    if (0 > (rc = listen(conn, 512)))
+      return rc;
+
+    tr_debug("trps_listen: TRP Server listening on port %d", port);
+    return conn;
+}
+
+#if 0
+
+/* returns EACCES if authorization is denied */
+static int trps_auth_cb(gss_name_t clientName, gss_buffer_t displayName,
+                        void *data)
+{
+  TRPS_INSTANCE *inst = (TRPS_INSTANCE *)data;
+  TR_NAME name ={(char *) displayName->value,
+                 displayName->length};
+  int result=0;
+
+  if (0!=inst->auth_handler(clientName, &name, inst->cookie)) {
+    tr_debug("trps_auth_cb: client '%.*s' denied authorization.", name.len, name.buf);
+    result=EACCES; /* denied */
+  }
+
+  return result;
+}
+
+/* returns 0 on authorization success, 1 on failure, or -1 in case of error */
+static int trps_auth_connection (TRPS_INSTANCE *inst,
+                                 int conn,
+                                 gss_ctx_id_t *gssctx)
+{
+  int rc = 0;
+  int auth, autherr = 0;
+  gss_buffer_desc nameBuffer = {0, NULL};
+  char *name = 0;
+  int nameLen = 0;
+
+  nameLen = asprintf(&name, "trustrouter@%s", inst->hostname);
+  nameBuffer.length = nameLen;
+  nameBuffer.value = name;
+  
+  if (rc = gsscon_passive_authenticate(conn, nameBuffer, gssctx, trps_auth_cb, inst)) {
+    tr_debug("trps_auth_connection: Error from gsscon_passive_authenticate(), rc = %d.", rc);
+    return -1;
+  }
+
+  if (rc = gsscon_authorize(*gssctx, &auth, &autherr)) {
+    tr_debug("trps_auth_connection: Error from gsscon_authorize, rc = %d, autherr = %d.", 
+           rc, autherr);
+    return -1;
+  }
+
+  if (auth)
+    tr_debug("trps_auth_connection: Connection authenticated, conn = %d.", conn);
+  else
+    tr_debug("trps_auth_connection: Authentication failed, conn %d.", conn);
+
+  return !auth;
+}
+#endif
+
+static int tr_trps_req_handler (TRPS_INSTANCE *trps,
+                                TRP_REQ *orig_req, 
+                                TRP_RESP *resp,
+                                void *tr_in)
+{
+  if (orig_req != NULL) 
+    free(orig_req);
+  return -1; /* not handling anything right now */
+}
+
+static void trps_handle_connection (TRPS_INSTANCE *trps, int conn)
+{
+  return;
+}
+
+static int tr_trps_gss_handler(gss_name_t client_name, TR_NAME *gss_name,
+                               void *cookie_in)
+{
+  TR_RP_CLIENT *rp;
+  struct tr_trps_event_cookie *cookie=(struct tr_trps_event_cookie *)cookie_in;
+  TRPS_INSTANCE *trps = cookie->trps;
+  TR_CFG_MGR *cfg_mgr = cookie->cfg_mgr;
+
+  tr_debug("tr_trps_gss_handler()");
+
+  if ((!client_name) || (!gss_name) || (!trps) || (!cfg_mgr)) {
+    tr_debug("tr_trps_gss_handler: Bad parameters.");
+    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_trps_gss_handler: Unknown GSS name %s", gss_name->buf);
+    return -1;
+  }
+
+  trps->rp_gss = rp;
+  tr_debug("Client's GSS Name: %s", gss_name->buf);
+
+  return 0;
+}
+
+
+static int trps_get_listener(TRPS_INSTANCE *trps,
+                             TRPS_REQ_FUNC *req_handler,
+                             trps_auth_func *auth_handler,
+                             const char *hostname,
+                             unsigned int port,
+                             void *cookie)
+{
+  int listen = -1;
+
+  if (0 > (listen = trps_listen(trps, port))) {
+    char errbuf[256];
+    if (0 == strerror_r(errno, errbuf, 256)) {
+      tr_debug("trps_get_listener: Error opening port %d: %s.", port, errbuf);
+    } else {
+      tr_debug("trps_get_listener: Unknown error openining port %d.", port);
+    }
+  } 
+
+  if (listen > 0) {
+    /* opening port succeeded */
+    tr_debug("trps_get_listener: Opened port %d.", port);
+    
+    /* make this socket non-blocking */
+    if (0 != fcntl(listen, F_SETFL, O_NONBLOCK)) {
+      tr_debug("trps_get_listener: Error setting O_NONBLOCK.");
+      close(listen);
+      listen=-1;
+    }
+  }
+
+  if (listen > 0) {
+    /* store the caller's request handler & cookie */
+    trps->req_handler = req_handler;
+    trps->auth_handler = auth_handler;
+    trps->hostname = talloc_strdup(trps, hostname);
+    trps->port = port;
+    trps->cookie = cookie;
+  }
+
+  return listen;
+}
+
+
+/* Accept and process a connection on a port opened with trps_get_listener() */
+int trps_accept(TRPS_INSTANCE *trps, int listen)
+{
+  int conn=-1;
+
+  conn = accept(listen, NULL, NULL);
+
+  if (0 > conn) {
+    perror("Error from TRP Server accept()");
+    return 1;
+  }
+
+  /* does not fork, handles request in main process */
+  trps_handle_connection(trps, conn);
+  write(conn, "TRP Online\n", strlen("TRP Online\n"));
+  close(conn);
+  return 0;
+}
+
+
+/********** Event Handling **********/
+
+/* called when a connection to the TRPS port is received */
+static void tr_trps_event_cb(int listener, short event, void *arg)
+{
+  TRPS_INSTANCE *trps = (TRPS_INSTANCE *)arg;
+
+  if (0==(event & EV_READ))
+    tr_debug("tr_trps_event_cb: unexpected event on TRPS socket (event=0x%X)", event);
+  else 
+    trps_accept(trps, listener);
+}
+
+
+/* Configure the trps instance and set up its event handler.
+ * Returns 0 on success, nonzero on failure. Fills in
+ * *trps_event (which should be allocated by caller). */
+int tr_trps_event_init(struct event_base *base,
+                       TRPS_INSTANCE *trps,
+                       TR_CFG_MGR *cfg_mgr,
+                       struct tr_socket_event *trps_ev)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  struct tr_trps_event_cookie *cookie;
+  int retval=0;
+
+  if (trps_ev == NULL) {
+    tr_debug("tr_trps_event_init: Null trps_ev.");
+    retval=1;
+    goto cleanup;
+  }
+
+  /* Create the cookie for callbacks. It is part of the trps context, so it will
+   * be cleaned up when trps is freed by talloc_free. */
+  cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+  if (cookie == NULL) {
+    tr_debug("tr_trps_event_init: Unable to allocate cookie.");
+    retval=1;
+    goto cleanup;
+  }
+  cookie->trps=trps;
+  cookie->cfg_mgr=cfg_mgr;
+  talloc_steal(trps, cookie);
+
+  /* get a trps listener */
+  trps_ev->sock_fd=trps_get_listener(trps,
+                                     tr_trps_req_handler,
+                                     tr_trps_gss_handler,
+                                     cfg_mgr->active->internal->hostname,
+                                     cfg_mgr->active->internal->trps_port,
+                                     (void *)cookie);
+  if (trps_ev->sock_fd < 0) {
+    tr_crit("Error opening TRP server socket.");
+    retval=1;
+    goto cleanup;
+  }
+
+  /* and its event */
+  trps_ev->ev=event_new(base,
+                        trps_ev->sock_fd,
+                        EV_READ|EV_PERSIST,
+                        tr_trps_event_cb,
+                        (void *)trps);
+  event_add(trps_ev->ev, NULL);
+
+cleanup:
+  talloc_free(tmp_ctx);
+  return retval;
+}