Read GSS credentials for monitoring service
authorJennifer Richards <jennifer@painless-security.com>
Fri, 20 Apr 2018 22:32:38 +0000 (18:32 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Fri, 20 Apr 2018 22:32:38 +0000 (18:32 -0400)
Some refactoring here and there, too.

common/tr_config_internal.c
common/tr_config_orgs.c
common/tr_config_rp_clients.c
common/tr_gss_names.c
common/tr_socket.c
include/tr_config.h
include/tr_gss_names.h
tr/tr_mon.c
tr/tr_trp.c

index 82a57e2..0ab306c 100644 (file)
 #include <tr_cfgwatch.h>
 
 /**
+ * Parse a boolean
+ *
+ * If the key does not exist in the src object, returns success but does fill in *dest.
+ *
+ * @param src JSON object to pull a value from
+ * @param key key to pull
+ * @param dest (output) pointer to an allocated integer
+ * @return TR_CFG_SUCCESS or an error code
+ */
+static TR_CFG_RC tr_cfg_parse_boolean(json_t *src, const char *key, int *dest)
+{
+  json_t *jtmp;
+
+  /* Validate parameters */
+  if ((src == NULL) || (key == NULL) || (dest == NULL))
+    return TR_CFG_BAD_PARAMS;
+
+  /* See if we have a value for this key; do nothing if not */
+  jtmp = json_object_get(src, key);
+  if (jtmp) {
+    if (json_is_boolean(jtmp)) {
+      *dest = json_boolean_value(jtmp);
+    } else {
+      tr_debug("tr_cfg_parse_unsigned: Parsing error, %s is not a boolean.", key);
+      return TR_CFG_NOPARSE;
+    }
+  }
+
+  return TR_CFG_SUCCESS;
+}
+
+/**
  * Parse an unsigned integer
  *
  * If the key does not exist in the src object, returns success but does fill in *dest.
@@ -118,6 +150,7 @@ static void set_defaults(TR_CFG_INTERNAL *cfg)
   cfg->max_tree_depth = TR_DEFAULT_MAX_TREE_DEPTH;
   cfg->tids_port = TR_DEFAULT_TIDS_PORT;
   cfg->trps_port = TR_DEFAULT_TRPS_PORT;
+  cfg->monitoring_port = TR_DEFAULT_MONITORING_PORT;
   cfg->cfg_poll_interval = TR_CFGWATCH_DEFAULT_POLL;
   cfg->cfg_settling_time = TR_CFGWATCH_DEFAULT_SETTLE;
   cfg->trp_connect_interval = TR_DEFAULT_TRP_CONNECT_INTERVAL;
@@ -128,6 +161,7 @@ static void set_defaults(TR_CFG_INTERNAL *cfg)
   cfg->tid_resp_denom = TR_DEFAULT_TID_RESP_DENOM;
   cfg->log_threshold = TR_DEFAULT_LOG_THRESHOLD;
   cfg->console_threshold = TR_DEFAULT_CONSOLE_THRESHOLD;
+  cfg->monitoring_credentials = NULL;
 }
 
 /* Helper that checks return value of a parse fn and returns if it failed */
index 5674fce..f6925ca 100644 (file)
@@ -215,7 +215,7 @@ static TR_CFG_RC tr_cfg_parse_one_peer_org(TR_CFG *trc, json_t *jporg)
   else
     trp_peer_set_port(new_peer, json_integer_value(jport));
 
-  names=tr_cfg_parse_gss_names(tmp_ctx, jgss, &rc);
+  rc = tr_cfg_parse_gss_names(tmp_ctx, jgss, &names);
   if (rc!=TR_CFG_SUCCESS) {
     tr_err("tr_cfg_parse_one_peer_org: unable to parse gss names.");
     rc=TR_CFG_NOPARSE;
index 01b36ba..960edce 100644 (file)
 #endif
 
 
-TR_GSS_NAMES *tr_cfg_parse_gss_names(TALLOC_CTX *mem_ctx, json_t *jgss_names, TR_CFG_RC *rc)
+TR_CFG_RC tr_cfg_parse_gss_names(TALLOC_CTX *mem_ctx, json_t *jgss_names, TR_GSS_NAMES **gssn_out)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_GSS_NAMES *gn=NULL;
   json_t *jname=NULL;
-  int ii=0;
+  size_t ii=0;
   TR_NAME *name=NULL;
+  TR_CFG_RC rc = TR_CFG_ERROR;
 
-  if ((rc==NULL) || (jgss_names==NULL)) {
+  if (jgss_names==NULL) {
     tr_err("tr_cfg_parse_gss_names: Bad parameters.");
-    *rc=TR_CFG_BAD_PARAMS;
-
+    rc=TR_CFG_BAD_PARAMS;
+    goto cleanup;
   }
 
   if (!json_is_array(jgss_names)) {
     tr_err("tr_cfg_parse_gss_names: gss_names not an array.");
-    *rc=TR_CFG_NOPARSE;
+    rc=TR_CFG_NOPARSE;
     goto cleanup;
   }
 
@@ -79,33 +80,32 @@ TR_GSS_NAMES *tr_cfg_parse_gss_names(TALLOC_CTX *mem_ctx, json_t *jgss_names, TR
     jname=json_array_get(jgss_names, ii);
     if (!json_is_string(jname)) {
       tr_err("tr_cfg_parse_gss_names: Encountered non-string gss name.");
-      *rc=TR_CFG_NOPARSE;
+      rc=TR_CFG_NOPARSE;
       goto cleanup;
     }
 
     name=tr_new_name(json_string_value(jname));
     if (name==NULL) {
       tr_err("tr_cfg_parse_gss_names: Out of memory allocating gss name.");
-      *rc=TR_CFG_NOMEM;
+      rc=TR_CFG_NOMEM;
       goto cleanup;
     }
 
     if (tr_gss_names_add(gn, name)!=0) {
       tr_free_name(name);
       tr_err("tr_cfg_parse_gss_names: Unable to add gss name to RP client.");
-      *rc=TR_CFG_ERROR;
+      rc=TR_CFG_ERROR;
       goto cleanup;
     }
   }
 
-  talloc_steal(mem_ctx, gn);
-  *rc=TR_CFG_SUCCESS;
+  *gssn_out = gn;
+  talloc_steal(mem_ctx, *gssn_out);
+  rc=TR_CFG_SUCCESS;
 
 cleanup:
   talloc_free(tmp_ctx);
-  if ((*rc!=TR_CFG_SUCCESS) && (gn!=NULL))
-    gn=NULL;
-  return gn;
+  return rc;
 }
 
 /* default filter accepts realm and *.realm */
@@ -306,7 +306,7 @@ static TR_RP_CLIENT *tr_cfg_parse_one_rp_client(TALLOC_CTX *mem_ctx, json_t *jre
     goto cleanup;
   }
 
-  client->gss_names=tr_cfg_parse_gss_names(client, json_object_get(jrealm, "gss_names"), &call_rc);
+  call_rc = tr_cfg_parse_gss_names(client, json_object_get(jrealm, "gss_names"), &(client->gss_names));
 
   if (call_rc!=TR_CFG_SUCCESS) {
     tr_err("tr_cfg_parse_one_rp_client: could not parse gss_names.");
index 970efdb..df15202 100644 (file)
@@ -35,6 +35,7 @@
 #include <talloc.h>
 
 #include <tr_gss_names.h>
+#include <tr_debug.h>
 
 static int tr_gss_names_destructor(void *obj)
 {
@@ -81,6 +82,36 @@ int tr_gss_names_add(TR_GSS_NAMES *gn, TR_NAME *new)
     return -1;
 }
 
+/**
+ * Create a duplicate GSS names struct
+ *
+ * @param mem_ctx
+ * @param orig
+ * @return
+ */
+TR_GSS_NAMES *tr_gss_names_dup(TALLOC_CTX *mem_ctx, TR_GSS_NAMES *orig)
+{
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+  TR_GSS_NAMES *new = tr_gss_names_new(tmp_ctx);
+  TR_GSS_NAMES_ITER *iter = tr_gss_names_iter_new(tmp_ctx);
+  TR_NAME *this = NULL;
+
+  if ( !orig || !new || !iter ) {
+    talloc_free(tmp_ctx);
+    return NULL;
+  }
+  this = tr_gss_names_iter_first(iter, orig);
+  while (this) {
+    if (tr_gss_names_add(new, tr_dup_name(this)) != 0) {
+      talloc_free(tmp_ctx);
+      return NULL;
+    }
+    this = tr_gss_names_iter_next(iter);
+  }
+  /* success */
+  talloc_steal(mem_ctx, new);
+  return new;
+}
 int tr_gss_names_matches(TR_GSS_NAMES *gn, TR_NAME *name)
 {
   int ii=0;
index 313d931..7f1c917 100644 (file)
@@ -129,7 +129,7 @@ nfds_t tr_sock_listen_all(unsigned int port, int *fd_out, nfds_t max_fd)
     return 0;
   }
 
-  tr_debug("tr_sock_listen_all: monitoring interface listening on port %d on %d socket%s",
+  tr_debug("tr_sock_listen_all: listening on port %d on %d socket%s",
            port,
            n_opened,
            (n_opened==1)?"":"s");
index e83071c..30317de 100644 (file)
@@ -53,6 +53,7 @@
 #define TR_DEFAULT_MAX_TREE_DEPTH 12
 #define TR_DEFAULT_TRPS_PORT 12308
 #define TR_DEFAULT_TIDS_PORT 12309
+#define TR_DEFAULT_MONITORING_PORT 0 /* defaults to being turned off */
 #define TR_DEFAULT_LOG_THRESHOLD LOG_INFO
 #define TR_DEFAULT_CONSOLE_THRESHOLD LOG_NOTICE
 #define TR_DEFAULT_APC_EXPIRATION_INTERVAL 43200
@@ -89,6 +90,7 @@ typedef struct tr_cfg_internal {
   unsigned int tid_req_timeout;
   unsigned int tid_resp_numer; /* numerator of fraction of AAA servers to wait for in unshared mode */
   unsigned int tid_resp_denom; /* denominator of fraction of AAA servers to wait for in unshared mode */
+  TR_GSS_NAMES *monitoring_credentials;
 } TR_CFG_INTERNAL;
 
 /* record of files loaded for this configuration */
@@ -150,7 +152,7 @@ TR_APC *tr_cfg_parse_apcs(TALLOC_CTX *mem_ctx, json_t *japcs, TR_CFG_RC *rc);
 
 /* tr_config_rp_clients.c */
 TR_RP_CLIENT *tr_cfg_parse_rp_clients(TALLOC_CTX *mem_ctx, json_t *jrealms, TR_CFG_RC *rc);
-TR_GSS_NAMES *tr_cfg_parse_gss_names(TALLOC_CTX *mem_ctx, json_t *jgss_names, TR_CFG_RC *rc);
+TR_CFG_RC tr_cfg_parse_gss_names(TALLOC_CTX *mem_ctx, json_t *jgss_names, TR_GSS_NAMES **gssn_out);
 
 /* tr_config_encoders.c */
 json_t *tr_cfg_files_to_json_array(TR_CFG *cfg);
index 7585798..f8f97a2 100644 (file)
@@ -52,6 +52,7 @@ typedef struct tr_gss_names_iter {
 TR_GSS_NAMES *tr_gss_names_new(TALLOC_CTX *mem_ctx);
 void tr_gss_names_free(TR_GSS_NAMES *gn);
 int tr_gss_names_add(TR_GSS_NAMES *gn, TR_NAME *new);
+TR_GSS_NAMES *tr_gss_names_dup(TALLOC_CTX *mem_ctx, TR_GSS_NAMES *orig);
 int tr_gss_names_matches(TR_GSS_NAMES *gn, TR_NAME *name);
 
 TR_GSS_NAMES_ITER *tr_gss_names_iter_new(TALLOC_CTX *mem_ctx);
index 8138198..beb258e 100644 (file)
@@ -96,13 +96,13 @@ static int tr_mons_auth_handler(gss_name_t client_name, TR_NAME *gss_name, void
 {
   struct tr_mons_event_cookie *cookie=talloc_get_type_abort(cookie_in, struct tr_mons_event_cookie);
   MONS_INSTANCE *mons = cookie->mons;
-  TR_CFG_MGR *cfg_mgr = cookie->cfg_mgr;
 
-  if ((!client_name) || (!gss_name) || (!mons) || (!cfg_mgr)) {
+  if ((!client_name) || (!gss_name) || (!mons)) {
     tr_debug("tr_mons_gss_handler: Bad parameters.");
     return -1;
   }
 
+  tr_debug("tr_mons_gss_handler: %p", mons->authorized_gss_names);
   /* Ensure at least one client exists using this GSS name */
   if (! tr_gss_names_matches(mons->authorized_gss_names, gss_name)) {
     tr_info("tr_mons_gss_handler: Unauthorized request from %.*s", gss_name->len, gss_name->buf);
@@ -145,6 +145,12 @@ int tr_mons_event_init(struct event_base *base,
     goto cleanup;
   }
 
+  if (cfg_mgr->active->internal->monitoring_port == 0) {
+    tr_notice("tr_mons_event_init: monitoring is disabled, not enabling events or opening sockets");
+    retval = 0;
+    goto cleanup;
+  }
+
   /* Create the cookie for callbacks. We'll put it in the mons context, so it will
    * be cleaned up when mons is freed by talloc_free. */
   cookie=talloc(tmp_ctx, struct tr_mons_event_cookie);
index 9dc1f8d..e075d58 100644 (file)
@@ -876,6 +876,16 @@ void tr_config_changed(TR_CFG *new_cfg, void *cookie)
   tr->tids->hostname = new_cfg->internal->hostname;
   tr->mons->hostname = new_cfg->internal->hostname;
 
+  /* Update the authorized monitoring gss names */
+  if (tr->mons->authorized_gss_names) {
+    tr_debug("tr_config_changed: freeing tr->mons->authorized_gss_names");
+    tr_gss_names_free(tr->mons->authorized_gss_names);
+  }
+  tr->mons->authorized_gss_names = tr_gss_names_dup(tr->mons, new_cfg->internal->monitoring_credentials);
+  if (tr->mons->authorized_gss_names == NULL) {
+    tr_err("tr_config_changed: Error configuring monitoring credentials");
+  }
+
   trps_set_connect_interval(trps, new_cfg->internal->trp_connect_interval);
   trps_set_update_interval(trps, new_cfg->internal->trp_update_interval);
   trps_set_sweep_interval(trps, new_cfg->internal->trp_sweep_interval);