From 63189ccb50596b232c7d35bb429e3ef655da3124 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Wed, 25 May 2016 22:42:13 -0400 Subject: [PATCH] Add TRP handling events, plus change to cfg layout. 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. --- Makefile.am | 4 +- common/tr_comm.c | 2 - common/tr_config.c | 125 ++++++++++++------- include/tid_internal.h | 4 +- include/tr.h | 12 +- include/tr_cfgwatch.h | 5 +- include/tr_config.h | 22 ++-- include/tr_tid.h | 7 +- include/tr_trp.h | 43 +++++++ include/trust_router/tid.h | 4 +- tid/example/tids_main.c | 2 +- tid/tids.c | 14 +-- tr/tr.c | 19 ++- tr/tr_cfgwatch.c | 50 +++----- tr/tr_main.c | 62 ++++++---- tr/tr_tid.c | 128 ++++++++++++-------- tr/tr_trp.c | 293 +++++++++++++++++++++++++++++++++++++++++++++ 17 files changed, 606 insertions(+), 190 deletions(-) create mode 100644 include/tr_trp.h create mode 100644 tr/tr_trp.c diff --git a/Makefile.am b/Makefile.am index 5dbd8cb..83a3478 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/common/tr_comm.c b/common/tr_comm.c index a471cf4..92bd2e0 100644 --- a/common/tr_comm.c +++ b/common/tr_comm.c @@ -32,10 +32,8 @@ * */ -#include #include #include -#include #include #include diff --git a/common/tr_config.c b/common/tr_config.c index f7fdf39..0625790 100644 --- a/common/tr_config.c +++ b/common/tr_config.c @@ -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; iid_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; iid_name); - } - } + } return n; } diff --git a/include/tid_internal.h b/include/tid_internal.h index 8502185..6fa8e38 100644 --- a/include/tid_internal.h +++ b/include/tid_internal.h @@ -35,8 +35,9 @@ #ifndef TID_INTERNAL_H #define TID_INTERNAL_H #include -#include +#include +#include #include 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 */ }; diff --git a/include/tr.h b/include/tr.h index 9d75fa5..8878161 100644 --- a/include/tr.h +++ b/include/tr.h @@ -35,20 +35,24 @@ #ifndef TR_H #define TR_H +#include + #include #include #include #include +#include +#include #include 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 diff --git a/include/tr_cfgwatch.h b/include/tr_cfgwatch.h index 92ad9cb..434202f 100644 --- a/include/tr_cfgwatch.h +++ b/include/tr_cfgwatch.h @@ -5,8 +5,6 @@ #include #include -#include - 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; diff --git a/include/tr_config.h b/include/tr_config.h index 8bc905a..af58db9 100644 --- a/include/tr_config.h +++ b/include/tr_config.h @@ -41,14 +41,14 @@ #include #include -#include +#include #include #include -#include #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 diff --git a/include/tr_tid.h b/include/tr_tid.h index e846437..fd01a10 100644 --- a/include/tr_tid.h +++ b/include/tr_tid.h @@ -1,9 +1,12 @@ #ifndef TR_TID_H #define TR_TID_H -#include #include +#include -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 index 0000000..3ec12dc --- /dev/null +++ b/include/tr_trp.h @@ -0,0 +1,43 @@ +#ifndef TR_TRP_H +#define TR_TRP_H + +#include + +#include +#include + + +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 */ diff --git a/include/trust_router/tid.h b/include/trust_router/tid.h index d87e0e0..613541f 100644 --- a/include/trust_router/tid.h +++ b/include/trust_router/tid.h @@ -35,6 +35,8 @@ #ifndef TID_H #define TID_H +#include + #include #include @@ -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); diff --git a/tid/example/tids_main.c b/tid/example/tids_main.c index dd60f8e..c334f41 100644 --- a/tid/example/tids_main.c +++ b/tid/example/tids_main.c @@ -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; } diff --git a/tid/tids.c b/tid/tids.c index 02bc6f6..14c708d 100644 --- a/tid/tids.c +++ b/tid/tids.c @@ -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 --- a/tr/tr.c +++ b/tr/tr.c @@ -34,15 +34,24 @@ #include #include +#include #include +#include -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); } diff --git a/tr/tr_cfgwatch.c b/tr/tr_cfgwatch.c index 3439112..6e98651 100644 --- a/tr/tr_cfgwatch.c +++ b/tr/tr_cfgwatch.c @@ -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)."); } } diff --git a/tr/tr_main.c b/tr/tr_main.c index e81aab4..5b2559f 100644 --- a/tr/tr_main.c +++ b/tr/tr_main.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/tr/tr_tid.c b/tr/tr_tid.c index fbaead4..c03e80a 100644 --- a/tr/tr_tid.c +++ b/tr/tr_tid.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,14 +6,21 @@ #include #include #include +#include #include /* 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 index 0000000..1269c80 --- /dev/null +++ b/tr/tr_trp.c @@ -0,0 +1,293 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* 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; +} -- 2.1.4