trp/trp_upd.c
trp/trpc.c
trp/trps.c include/tr_name_internal.h mon/mon_req.c mon/mon_req_encode.c mon/mon_req_decode.c
- mon/mon_resp.c mon/mon_common.c mon/mon_resp_encode.c tr/tr_mon.c mon/mons.c include/tr_socket.h common/tr_gss.c include/tr_gss.h common/tr_config_internal.c)
+ mon/mon_resp.c mon/mon_common.c mon/mon_resp_encode.c mon/mon_resp_decode.c tr/tr_mon.c mon/mons.c include/tr_socket.h common/tr_gss.c include/tr_gss.h common/tr_config_internal.c mon/mons_handlers.c include/mons_handlers.h)
# Does not actually build!
add_executable(trust_router ${SOURCE_FILES})
+add_executable(trmon mon/monc.c tr/trmon_main.c common/tr_gss_client.c include/tr_gss_client.h)
+
# Test build targets - for debugging
add_executable(test_mon_req_encode mon/mon_common.c mon/mon_req.c mon/tests/test_mon_req_encode.c mon/mon_req_encode.c)
target_link_libraries(test_mon_req_encode jansson talloc glib-2.0)
bin_PROGRAMS= tr/trust_router tr/trpc tid/example/tidc tid/example/tids common/tests/tr_dh_test common/tests/mq_test \
common/tests/thread_test trp/msgtst trp/test/rtbl_test trp/test/ptbl_test common/tests/cfg_test \
common/tests/commtest common/tests/name_test common/tests/filt_test mon/tests/test_mon_req_encode \
- mon/tests/test_mon_req_decode mon/tests/test_mon_resp_encode
+ mon/tests/test_mon_req_decode mon/tests/test_mon_resp_encode tr/trmon
AM_CPPFLAGS=-I$(srcdir)/include $(GLIB_CFLAGS)
AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses $(GLIB_CFLAGS)
SUBDIRS = gsscon
common/tr_idp.c \
common/tr_filter.c \
common/tr_gss_names.c \
- common/tr_socket.c
+ common/tr_socket.c \
+ $(mon_srcs)
tid_srcs = tid/tid_resp.c \
tid/tid_req.c \
common/tr_config_internal.c \
common/tr_mq.c
+# general monitoring message sources
mon_srcs = \
- mon/mons.c \
mon/mon_common.c \
mon/mon_req.c \
mon/mon_req_encode.c \
mon/mon_req_decode.c \
mon/mon_resp.c \
+ mon/mon_resp_decode.c \
mon/mon_resp_encode.c
+# monitoring server sources
+mons_srcs = \
+ mon/mons.c \
+ mon/mons_handlers.c
+
check_PROGRAMS = common/t_constraint
TESTS = common/t_constraint
TEST_CFLAGS = -Wno-missing-prototypes
tr/tr_trp.c \
tr/tr_mon.c \
common/tr_gss.c \
+common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs) \
-$(mon_srcs) \
-$(common_srcs)
+$(common_srcs) \
+$(mons_srcs)
tr_trust_router_LDFLAGS = $(AM_LDFLAGS) -levent_pthreads -pthread
tr_trust_router_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
+
tr_trpc_SOURCES =tr/trpc_main.c \
tr/tr_trp.c \
common/tr_gss.c \
+common/tr_gss_client.c \
$(trp_srcs) \
$(tid_srcs) \
$(common_srcs)
tr_trpc_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
tr_trpc_LDFLAGS = $(AM_LDFLAGS) -pthread
+tr_trmon_SOURCES = tr/trmon_main.c \
+common/tr_gss.c \
+common/tr_gss_client.c \
+$(tid_srcs) \
+$(trp_srcs) \
+$(common_srcs) \
+mon/monc.c
+
+tr_trmon_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
+tr_trmon_LDFLAGS = $(AM_LDFLAGS) -pthread
+
trp_msgtst_SOURCES = trp/msgtst.c \
$(common_srcs) \
trp/trp_req.c \
trp_test_ptbl_test_SOURCES = trp/test/ptbl_test.c \
common/tr_gss.c \
+common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs) \
$(common_srcs)
tid_example_tidc_SOURCES = tid/example/tidc_main.c \
common/tr_gss.c \
+common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs) \
$(common_srcs)
tid_example_tids_SOURCES = tid/example/tids_main.c \
common/tr_gss.c \
+common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs) \
$(common_srcs)
common_tests_cfg_test_SOURCES = common/tests/cfg_test.c \
$(common_srcs) \
common/tr_gss.c \
+common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs)
common_tests_cfg_test_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
common_tests_commtest_SOURCES = common/tests/commtest.c \
$(common_srcs) \
common/tr_gss.c \
+common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs)
common_tests_commtest_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
common_tests_name_test_SOURCES = common/tests/name_test.c \
$(common_srcs) \
common/tr_gss.c \
+ common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs)
common_tests_name_test_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
common_tests_filt_test_SOURCES = common/tests/filt_test.c \
$(common_srcs) \
common/tr_gss.c \
+ common/tr_gss_client.c \
$(tid_srcs) \
$(trp_srcs)
common_tests_filt_test_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
json_decref(decoded);
assert(encoded);
- assert(msg=tr_msg_decode(encoded, strlen(encoded)));
+ assert(msg= tr_msg_decode(NULL, encoded, strlen(encoded)));
assert(upd=tr_msg_get_trp_upd(msg));
assert(inforec=trp_upd_get_inforec(upd));
/* now remove the inforec from the update context */
msglen=fread(msgbuf, 1, MAX_FILE_SIZE, f);
assert(msglen);
assert(feof(f));
- msg=tr_msg_decode(msgbuf, msglen);
+ msg= tr_msg_decode(NULL, msgbuf, msglen);
free(msgbuf);
msgbuf=NULL;
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
gss_ctx_id_t gssctx = GSS_C_NO_CONTEXT;
char *req_str = NULL;
+ size_t req_len = 0;
+ TR_MSG *req_msg = NULL;
+ TR_MSG *resp_msg = NULL;
char *resp_str = NULL;
if (tr_gss_auth_connection(conn,
tr_debug("tr_gss_handle_connection: Connection authorized");
// TODO: should there be a timeout on this?
- while (1) { /* continue until an error breaks us out */
+ do {
+ /* continue until an error breaks us out */
// try to read a request
req_str = tr_gss_read_req(tmp_ctx, conn, gssctx);
- if ( req_str == NULL) {
+ if (req_str == NULL) {
// an error occurred, give up
tr_notice("tr_gss_handle_connection: Error reading request");
goto cleanup;
- } else if (strlen(req_str) > 0) {
- // we got a request message, exit the loop and process it
- break;
}
- // no error, but no message, keep waiting for one
- talloc_free(req_str); // this would be cleaned up anyway, but may as well free it
+ req_len = strlen(req_str);
+
+ /* If we got no characters, we will loop again. Free the empty response for the next loop. */
+ if (req_len == 0)
+ talloc_free(req_str);
+
+ } while (req_len == 0);
+
+ /* Decode the request */
+ req_msg = tr_msg_decode(tmp_ctx, req_str, req_len);
+ if (req_msg == NULL) {
+ tr_notice("tr_gss_handle_connection: Error decoding response");
+ goto cleanup;
}
/* Hand off the request for processing and get the response */
- resp_str = req_cb(tmp_ctx, req_str, req_cookie);
+ resp_msg = req_cb(tmp_ctx, req_msg, req_cookie);
- if (resp_str == NULL) {
+ if (resp_msg == NULL) {
// no response, clean up
goto cleanup;
}
+ /* Encode the response */
+ resp_str = tr_msg_encode(tmp_ctx, resp_msg);
+ if (resp_str == NULL) {
+ /* We apparently can't encode a response, so just return */
+ tr_err("tr_gss_handle_connection: Error encoding response");
+ goto cleanup;
+ }
+
// send the response
if (tr_gss_write_resp(conn, gssctx, resp_str)) {
- tr_notice("tr_gss_handle_connection: Error writing response");
+ tr_err("tr_gss_handle_connection: Error writing response");
+ goto cleanup;
}
cleanup:
--- /dev/null
+/*
+ * Copyright (c) 2012, 2014-2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <talloc.h>
+
+#include <trust_router/tr_dh.h>
+#include <tr_msg.h>
+#include <gsscon.h>
+#include <tr_debug.h>
+#include <tr_gss_client.h>
+
+static int tr_gssc_destructor(void *obj)
+{
+ TR_GSSC_INSTANCE *tr_gssc=talloc_get_type_abort(obj, TR_GSSC_INSTANCE);
+ if (NULL!=tr_gssc) {
+ if (NULL!=tr_gssc->client_dh)
+ tr_destroy_dh_params(tr_gssc->client_dh);
+ }
+ return 0;
+}
+
+TR_GSSC_INSTANCE *tr_gssc_instance_new(TALLOC_CTX *mem_ctx)
+{
+ TR_GSSC_INSTANCE *gssc=talloc(NULL, TR_GSSC_INSTANCE);
+ if (gssc != NULL) {
+ gssc->service_name = NULL;
+ gssc->client_dh = NULL;
+ gssc->conn = -1;
+ gssc->gss_ctx = talloc(gssc, gss_ctx_id_t);
+ if (gssc->gss_ctx == NULL) {
+ talloc_free(gssc); /* before the destructor is set */
+ return NULL;
+ }
+ talloc_set_destructor((void *)gssc, tr_gssc_destructor);
+ }
+ return gssc;
+}
+
+void tr_gssc_instance_free(TR_GSSC_INSTANCE *tr_gssc)
+{
+ talloc_free(tr_gssc);
+}
+
+/**
+ * Open a connection to the requested server:port
+ *
+ * @param gssc client instance
+ * @param server server name/address
+ * @param port TCP port to connect
+ * @return 0 on success, -1 on failure
+ */
+int tr_gssc_open_connection(TR_GSSC_INSTANCE *gssc, const char *server, unsigned int port)
+{
+ tr_debug("tr_gssc_open_connection: opening connection to %s:%d", server, port);
+ if (0 != gsscon_connect(server, port, gssc->service_name, &(gssc->conn), gssc->gss_ctx))
+ return -1;
+
+ return 0; /* success */
+}
+
+/**
+ * Send a request message and retrieve a response message
+ *
+ * @param mem_ctx
+ * @param gssc
+ * @param req_msg
+ * @return decoded message, or null on error
+ */
+TR_MSG *tr_gssc_exchange_msgs(TALLOC_CTX *mem_ctx, TR_GSSC_INSTANCE *gssc, TR_MSG *req_msg)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ char *req_buf = NULL;
+ char *resp_buf = NULL;
+ size_t resp_buflen = 0;
+ TR_MSG *resp_msg = NULL; /* this is the return value */
+ int err;
+
+ /* Validate inputs */
+ if ((gssc == NULL) || (req_msg == NULL))
+ goto cleanup;
+
+ /* Encode the request into a json string */
+ if (!(req_buf = tr_msg_encode(tmp_ctx, req_msg))) {
+ tr_err("tr_gssc_exchange_msgs: Error encoding request message.\n");
+ goto cleanup;
+ }
+
+ tr_debug( "tr_gssc_exchange_msgs: Sending request message:\n%s\n", req_buf);
+
+ /* Send the request over the connection */
+ err = gsscon_write_encrypted_token(gssc->conn, *(gssc->gss_ctx), req_buf, strlen(req_buf));
+ if (err) {
+ tr_err( "tr_gssc_exchange_msgs: Error sending request.\n");
+ goto cleanup;
+ }
+
+ /* Read the response from the connection */
+ /* TBD -- timeout? */
+ if (gsscon_read_encrypted_token(gssc->conn, *(gssc->gss_ctx), &resp_buf, &resp_buflen))
+ goto cleanup;
+
+ tr_debug( "tr_gssc_exchange_msgs: Response Received (%u bytes).\n%s\n", (unsigned) resp_buflen, resp_buf);
+ resp_msg = tr_msg_decode(mem_ctx, resp_buf, resp_buflen);
+ free(resp_buf);
+
+ if (resp_msg == NULL) {
+ tr_err( "tr_gssc_exchange_msgs: Error decoding response.\n");
+ goto cleanup;
+ }
+
+ /* If we get here, then we decoded the message and resp_msg is not null. Nothing more to do. */
+
+cleanup:
+ talloc_free(tmp_ctx);
+ return resp_msg;
+}
+
+DH * tr_gssc_get_dh(TR_GSSC_INSTANCE *inst)
+{
+ return inst->client_dh;
+}
+
+DH *tr_gssc_set_dh(TR_GSSC_INSTANCE *inst, DH *dh)
+{
+ inst->client_dh = dh;
+ return dh;
+}
#include <tr_apc.h>
#include <tr_comm.h>
+#include <mon_internal.h>
+#include <trp_internal.h>
#include <tr_msg.h>
#include <tr_name_internal.h>
-#include <trp_internal.h>
#include <trust_router/tr_constraint.h>
#include <trust_router/tr_dh.h>
#include <tr_debug.h>
msg->msg_type = type;
}
+/* NOTE: If you are manipulating messages with these getters/setters, the msg_rep
+ * objects are *not* put in the talloc context of the msg. If you are allocating
+ * the message directly with talloc, then you can talloc_steal() the rep into the
+ * message's context, but this is not handled automatically. */
+
+/**
+ * Get a TID_REQ message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TID_REQUEST message
+ */
TID_REQ *tr_msg_get_req(TR_MSG *msg)
{
if (msg->msg_type == TID_REQUEST)
return NULL;
}
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
void tr_msg_set_req(TR_MSG *msg, TID_REQ *req)
{
msg->msg_rep = req;
msg->msg_type = TID_REQUEST;
}
+/**
+ * Get a TID_RESP message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TID_RESPONSE message
+ */
TID_RESP *tr_msg_get_resp(TR_MSG *msg)
{
if (msg->msg_type == TID_RESPONSE)
return NULL;
}
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
void tr_msg_set_resp(TR_MSG *msg, TID_RESP *resp)
{
msg->msg_rep = resp;
msg->msg_type = TID_RESPONSE;
}
+/**
+ * Get a MON_REQ message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a MON_REQUEST message
+ */
+MON_REQ *tr_msg_get_mon_req(TR_MSG *msg)
+{
+ if (msg->msg_type == MON_REQUEST)
+ return (MON_REQ *)msg->msg_rep;
+ return NULL;
+}
+
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
+void tr_msg_set_mon_req(TR_MSG *msg, MON_REQ *req)
+{
+ msg->msg_rep = req;
+ msg->msg_type = MON_REQUEST;
+}
+
+/**
+ * Get a MON_RESP message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a MON_RESPONSE message
+ */
+MON_RESP *tr_msg_get_mon_resp(TR_MSG *msg)
+{
+ if (msg->msg_type == MON_RESPONSE)
+ return (MON_RESP *)msg->msg_rep;
+ return NULL;
+}
+
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
+void tr_msg_set_mon_resp(TR_MSG *msg, MON_RESP *resp)
+{
+ msg->msg_rep = resp;
+ msg->msg_type = MON_RESPONSE;
+}
+
+/**
+ * Get a TRP_UPD message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TRP_UPDATE message
+ */
TRP_UPD *tr_msg_get_trp_upd(TR_MSG *msg)
{
if (msg->msg_type == TRP_UPDATE)
return NULL;
}
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
void tr_msg_set_trp_upd(TR_MSG *msg, TRP_UPD *update)
{
msg->msg_rep=update;
- talloc_steal(NULL, update); /* should attach to msg, but TR_MSG not usually talloc'ed */
msg->msg_type=TRP_UPDATE;
}
+/**
+ * Get a TRP_REQ message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TRP_REQUEST message
+ */
TRP_REQ *tr_msg_get_trp_req(TR_MSG *msg)
{
if (msg->msg_type == TRP_REQUEST)
return NULL;
}
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
void tr_msg_set_trp_req(TR_MSG *msg, TRP_REQ *req)
{
msg->msg_rep=req;
if ((!req) || (!req->rp_realm) || (!req->realm) || !(req->comm))
return NULL;
- assert(jreq = json_object());
+ jreq = json_object();
+ assert(jreq);
jstr = tr_name_to_json_string(req->rp_realm);
json_object_set_new(jreq, "rp_realm", jstr);
return jreq;
}
-static TID_REQ *tr_msg_decode_tidreq(json_t *jreq)
+static TID_REQ *tr_msg_decode_tidreq(TALLOC_CTX *mem_ctx, json_t *jreq)
{
TID_REQ *treq = NULL;
json_t *jrp_realm = NULL;
tr_crit("tr_msg_decode_tidreq(): Error allocating TID_REQ structure.");
return NULL;
}
-
+ talloc_steal(mem_ctx, treq);
+
/* store required fields from request */
if ((NULL == (jrp_realm = json_object_get(jreq, "rp_realm"))) ||
(NULL == (jrealm = json_object_get(jreq, "target_realm"))) ||
return jresp;
}
-static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
+static TID_RESP *tr_msg_decode_tidresp(TALLOC_CTX *mem_ctx, json_t *jresp)
{
TID_RESP *tresp = NULL;
json_t *jresult = NULL;
json_t *jservers = NULL;
json_t *jerr_msg = NULL;
- if (!(tresp=tid_resp_new(NULL))) {
+ if (!(tresp=tid_resp_new(mem_ctx))) {
tr_crit("tr_msg_decode_tidresp(): Error allocating TID_RESP structure.");
return NULL;
}
-
/* store required fields from response */
if ((NULL == (jresult = json_object_get(jresp, "result"))) ||
TID_REQ *tidreq=NULL;
TRP_UPD *trpupd=NULL;
TRP_REQ *trpreq=NULL;
+ MON_REQ *monreq=NULL;
+ MON_RESP *monresp=NULL;
/* TBD -- add error handling */
jmsg = json_object();
- switch (msg->msg_type)
- {
+ switch (msg->msg_type) {
case TID_REQUEST:
jmsg_type = json_string("tid_request");
json_object_set_new(jmsg, "msg_type", jmsg_type);
json_object_set_new(jmsg, "msg_body", tr_msg_encode_trp_req(trpreq));
break;
+ case MON_REQUEST:
+ jmsg_type = json_string("mon_request");
+ json_object_set_new(jmsg, "msg_type", jmsg_type);
+ monreq=tr_msg_get_mon_req(msg);
+ json_object_set_new(jmsg, "msg_body", mon_req_encode(monreq));
+ break;
+
+ case MON_RESPONSE:
+ jmsg_type = json_string("mon_response");
+ json_object_set_new(jmsg, "msg_type", jmsg_type);
+ monresp=tr_msg_get_mon_resp(msg);
+ json_object_set_new(jmsg, "msg_body", mon_resp_encode(monresp));
+ break;
+
default:
json_decref(jmsg);
return NULL;
- }
+ }
/* We should perhaps use json_set_alloc_funcs to automatically use talloc, but for
* now, we'll encode to a malloc'ed buffer, then copy that to a talloc'ed buffer. */
return encoded;
}
-TR_MSG *tr_msg_decode(const char *jbuf, size_t buflen)
+TR_MSG *tr_msg_decode(TALLOC_CTX *mem_ctx, const char *jbuf, size_t buflen)
{
TR_MSG *msg=NULL;
json_t *jmsg = NULL;
return NULL;
}
- if (!(msg = malloc(sizeof(TR_MSG)))) {
+ if (!(msg = talloc_zero(mem_ctx, TR_MSG))) {
tr_debug("tr_msg_decode(): Error allocating TR_MSG structure.");
json_decref(jmsg);
return NULL;
}
- memset(msg, 0, sizeof(TR_MSG));
-
if ((NULL == (jtype = json_object_get(jmsg, "msg_type"))) ||
(NULL == (jbody = json_object_get(jmsg, "msg_body")))) {
tr_debug("tr_msg_decode(): Error parsing message header.");
if (0 == strcmp(mtype, "tid_request")) {
msg->msg_type = TID_REQUEST;
- tr_msg_set_req(msg, tr_msg_decode_tidreq(jbody));
+ tr_msg_set_req(msg, tr_msg_decode_tidreq(msg, jbody));
}
else if (0 == strcmp(mtype, "tid_response")) {
msg->msg_type = TID_RESPONSE;
- tr_msg_set_resp(msg, tr_msg_decode_tidresp(jbody));
+ tr_msg_set_resp(msg, tr_msg_decode_tidresp(msg, jbody));
}
else if (0 == strcmp(mtype, "trp_update")) {
msg->msg_type = TRP_UPDATE;
- tr_msg_set_trp_upd(msg, tr_msg_decode_trp_upd(NULL, jbody)); /* null talloc context for now */
+ tr_msg_set_trp_upd(msg, tr_msg_decode_trp_upd(msg, jbody));
}
else if (0 == strcmp(mtype, "trp_request")) {
msg->msg_type = TRP_UPDATE;
- tr_msg_set_trp_req(msg, tr_msg_decode_trp_req(NULL, jbody)); /* null talloc context for now */
+ tr_msg_set_trp_req(msg, tr_msg_decode_trp_req(msg, jbody));
+ }
+ else if (0 == strcmp(mtype, "mon_request")) {
+ msg->msg_type = MON_REQUEST;
+ tr_msg_set_mon_req(msg, mon_req_decode(msg, jbody));
+ }
+ /* We do not currently handle monitoring responses */
+ else if (0 == strcmp(mtype, "mon_response")) {
+ msg->msg_type = MON_RESPONSE;
+ tr_msg_set_mon_resp(msg, mon_resp_decode(msg, jbody));
}
else {
msg->msg_type = TR_UNKNOWN;
void tr_msg_free_encoded(char *jmsg)
{
if (jmsg)
- free (jmsg);
+ talloc_free(jmsg);
}
void tr_msg_free_decoded(TR_MSG *msg)
{
- if (msg) {
- if (msg->msg_rep!=NULL) {
- switch (msg->msg_type) {
- case TID_REQUEST:
- tid_req_free(tr_msg_get_req(msg));
- break;
- case TID_RESPONSE:
- tid_resp_free(tr_msg_get_resp(msg));
- break;
- case TRP_UPDATE:
- trp_upd_free(tr_msg_get_trp_upd(msg));
- break;
- case TRP_REQUEST:
- trp_req_free(tr_msg_get_trp_req(msg));
- default:
- break;
- }
- }
- free (msg);
- }
+ if (msg)
+ talloc_free(msg);
}
--- /dev/null
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef TRUST_ROUTER_MON_H
+#define TRUST_ROUTER_MON_H
+
+#include <gssapi.h>
+#include <trust_router/tr_name.h>
+
+/* Typedefs */
+typedef struct mon_req MON_REQ;
+typedef struct mon_resp MON_RESP;
+
+typedef enum mon_cmd MON_CMD;
+typedef enum mon_resp_code MON_RESP_CODE;
+
+typedef struct mon_opt MON_OPT;
+typedef enum mon_opt_type MON_OPT_TYPE;
+
+typedef enum mon_rc MON_RC;
+
+typedef struct mons_instance MONS_INSTANCE;
+typedef struct monc_instance MONC_INSTANCE;
+
+typedef struct mons_dispatch_table_entry MONS_DISPATCH_TABLE_ENTRY;
+
+typedef int (MONS_REQ_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
+typedef int (MONS_AUTH_FUNC)(gss_name_t client_name, TR_NAME *display_name, void *cookie);
+typedef int (MONC_RESP_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
+
+#endif //TRUST_ROUTER_MON_H
#include <stdint.h>
#include <jansson.h>
#include <gmodule.h>
+#include <gssapi.h>
+#include <trust_router/tid.h>
#include <trp_internal.h>
#include <tr_gss_names.h>
+#include <tr_gss_client.h>
#include <tr_name_internal.h>
-#include <gssapi.h>
+#include <trust_router/tr_dh.h>
+#include <mon.h>
/* Typedefs */
typedef struct mon_req MON_REQ;
typedef enum mon_rc MON_RC;
typedef struct mons_instance MONS_INSTANCE;
+typedef struct monc_instance MONC_INSTANCE;
typedef int (MONS_REQ_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
typedef int (MONS_AUTH_FUNC)(gss_name_t client_name, TR_NAME *display_name, void *cookie);
+typedef int (MONC_RESP_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
/* Struct and enum definitions */
enum mon_rc {
enum mon_opt_type {
OPT_TYPE_UNKNOWN=0,
+ OPT_TYPE_ANY,
// System information
OPT_TYPE_SHOW_VERSION,
};
struct mon_resp {
- MON_REQ *req; // request this responds to
MON_RESP_CODE code;
TR_NAME *message;
json_t *payload;
MONS_REQ_FUNC *req_handler;
MONS_AUTH_FUNC *auth_handler;
void *cookie;
+ GPtrArray *handlers;
+};
+
+/* Client instance */
+struct monc_instance {
+ TR_GSSC_INSTANCE *gssc;
};
/* Prototypes */
json_t *mon_req_encode(MON_REQ *req);
/* mon_req_decode.c */
-MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, const char *req_json);
+MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, json_t *req_json);
+MON_REQ *mon_req_parse(TALLOC_CTX *mem_ctx, const char *input);
/* mon_resp.c */
-MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx,
- MON_REQ *req,
- MON_RESP_CODE code,
- const char *msg,
- json_t *payload);
+MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx, MON_RESP_CODE code, const char *msg, json_t *payload);
void mon_resp_free(MON_RESP *resp);
+int mon_resp_set_message(MON_RESP *resp, const char *new_msg);
+void mon_resp_set_payload(MON_RESP *resp, json_t *new_payload);
/* mon_resp_encode.c */
json_t *mon_resp_encode(MON_RESP *resp);
+/* mon_resp_decode.c */
+MON_RESP * mon_resp_decode(TALLOC_CTX *mem_ctx, json_t *resp_json);
+
/* mons.c */
MONS_INSTANCE *mons_new(TALLOC_CTX *mem_ctx);
int mons_get_listener(MONS_INSTANCE *mons, MONS_REQ_FUNC *req_handler, MONS_AUTH_FUNC *auth_handler, const char *hostname,
unsigned int port, void *cookie, int *fd_out, size_t max_fd);
int mons_accept(MONS_INSTANCE *mons, int listen);
+/* monc.c */
+MONC_INSTANCE *monc_new(TALLOC_CTX *mem_ctx);
+void monc_free(MONC_INSTANCE *monc);
+DH *monc_get_dh(MONC_INSTANCE *inst);
+DH *monc_set_dh(MONC_INSTANCE *inst, DH *dh);
+int monc_open_connection(MONC_INSTANCE *monc, const char *server, unsigned int port);
+MON_RESP *monc_send_request(TALLOC_CTX *mem_ctx, MONC_INSTANCE *monc, MON_REQ *req);
+
#endif //TRUST_ROUTER_MON_REQ_H
--- /dev/null
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef TRUST_ROUTER_MONS_HANDLERS_H
+#define TRUST_ROUTER_MONS_HANDLERS_H
+
+typedef json_t *(MONS_HANDLER_FUNC)(void *);
+
+struct mons_dispatch_table_entry {
+ MON_CMD command;
+ MON_OPT_TYPE opt_type;
+ MONS_HANDLER_FUNC *handler;
+ void *cookie;
+};
+
+/* mons_handlers.c */
+MON_RESP *mons_handle_request(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req);
+MON_RC mons_register_handler(MONS_INSTANCE *mons, MON_CMD cmd, MON_OPT_TYPE opt_type, MONS_HANDLER_FUNC *f, void *cookie);
+
+#endif //TRUST_ROUTER_MONS_HANDLERS_H
#include <tr_rp.h>
#include <trust_router/tid.h>
#include <jansson.h>
+#include "tr_gss_client.h"
struct tid_srvr_blk {
TID_SRVR_BLK *next;
};
struct tidc_instance {
- // TID_REQ *req_list;
- // TBD -- Do we still need a separate private key */
- // char *priv_key;
- // int priv_len;
- DH *client_dh; /* Client's DH struct with priv and pub keys */
+ TR_GSSC_INSTANCE *gssc;
};
struct tids_instance {
#include <tr_msg.h>
typedef int (TR_GSS_AUTH_FN)(gss_name_t, TR_NAME *, void *);
-typedef char *(TR_GSS_HANDLE_REQ_FN)(TALLOC_CTX *, const char *, void *);
+typedef TR_MSG *(TR_GSS_HANDLE_REQ_FN)(TALLOC_CTX *, TR_MSG *, void *);
void tr_gss_handle_connection(int conn, const char *acceptor_name, const char *acceptor_realm, TR_GSS_AUTH_FN auth_cb,
void *auth_cookie, TR_GSS_HANDLE_REQ_FN req_cb, void *req_cookie);
--- /dev/null
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TRUST_ROUTER_TR_GSS_CLIENT_H
+#define TRUST_ROUTER_TR_GSS_CLIENT_H
+
+#include <gssapi.h>
+#include <trust_router/tr_dh.h>
+#include <tr_msg.h>
+
+typedef struct tr_gssc_instance TR_GSSC_INSTANCE;
+
+/* Client instance */
+struct tr_gssc_instance {
+ const char *service_name;
+ DH *client_dh;
+ gss_ctx_id_t *gss_ctx;
+ int conn;
+};
+
+/* tr_gss_client.c */
+TR_GSSC_INSTANCE *tr_gssc_instance_new(TALLOC_CTX *mem_ctx);
+void tr_gssc_instance_free(TR_GSSC_INSTANCE *tr_gssc);
+int tr_gssc_open_connection(TR_GSSC_INSTANCE *gssc, const char *server, unsigned int port);
+TR_MSG *tr_gssc_exchange_msgs(TALLOC_CTX *mem_ctx, TR_GSSC_INSTANCE *gssc, TR_MSG *req_msg);
+DH * tr_gssc_get_dh(TR_GSSC_INSTANCE *inst);
+DH *tr_gssc_set_dh(TR_GSSC_INSTANCE *inst, DH *dh);
+
+#endif //TRUST_ROUTER_TR_GSS_CLIENT_H
#include <tr_event.h>
#include <tr_config.h>
#include <mon_internal.h>
+#include <mons_handlers.h>
int tr_mons_event_init(struct event_base *base,
MONS_INSTANCE *mons,
#include <jansson.h>
#include <trust_router/tid.h>
#include <trust_router/trp.h>
+#include <mon.h>
+
typedef struct tr_msg TR_MSG;
enum msg_type {
TID_REQUEST,
TID_RESPONSE,
TRP_UPDATE,
- TRP_REQUEST
+ TRP_REQUEST,
+ MON_REQUEST,
+ MON_RESPONSE
};
/* Union of TR message types to hold message of any type. */
void tr_msg_set_trp_upd(TR_MSG *msg, TRP_UPD *req);
TRP_REQ *tr_msg_get_trp_req(TR_MSG *msg);
void tr_msg_set_trp_req(TR_MSG *msg, TRP_REQ *req);
+MON_REQ *tr_msg_get_mon_req(TR_MSG *msg);
+void tr_msg_set_mon_req(TR_MSG *msg, MON_REQ *req);
+MON_RESP *tr_msg_get_mon_resp(TR_MSG *msg);
+void tr_msg_set_mon_resp(TR_MSG *msg, MON_RESP *resp);
/* Encoders/Decoders */
char *tr_msg_encode(TALLOC_CTX *mem_ctx, TR_MSG *msg);
-TR_MSG *tr_msg_decode(const char *jmsg, size_t len);
+TR_MSG *tr_msg_decode(TALLOC_CTX *mem_ctx, const char *jmsg, size_t len);
void tr_msg_free_encoded(char *jmsg);
void tr_msg_free_decoded(TR_MSG *msg);
TR_EXPORT int tid_srvr_get_key_expiration(const TID_SRVR_BLK *, struct timeval *tv_out);
#define tid_resp_servers_foreach(RESP, SERVER, INDEX) \
- for (INDEX=0,SERVER=NULL; \
- ((INDEX < tid_resp_get_num_servers(RESP))&&(SERVER = tid_resp_get_server(resp, INDEX))); \
- INDEX++)
+ for ((INDEX)=0,(SERVER)=NULL; \
+ (((INDEX) < tid_resp_get_num_servers(RESP))&&((SERVER) = tid_resp_get_server(resp, (INDEX)))); \
+ (INDEX)++)
/* TID Client functions, in tid/tidc.c */
{
switch(opt_type) {
case OPT_TYPE_UNKNOWN:
+ case OPT_TYPE_ANY:
return NULL;
case OPT_TYPE_SHOW_VERSION:
MON_OPT *result = &g_array_index(req->options, MON_OPT, index);
return result;
}
+
}
/**
- * Parse JSON for a request
+ * Parse a JSON string into a request
*/
-static json_t *mon_req_parse(const char *input)
+MON_REQ *mon_req_parse(TALLOC_CTX *mem_ctx, const char *input)
{
json_t *parsed_json = NULL;
json_error_t json_error;
parsed_json = json_loads(input, JSON_REJECT_DUPLICATES, &json_error);
- return parsed_json;
+ return mon_req_decode(mem_ctx, parsed_json);
}
/**
* @param req_json reference to JSON request object
* @return decoded request struct or NULL on failure
*/
-MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, const char *req_str)
+MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, json_t *req_json)
{
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
MON_REQ *req = NULL;
- json_t *req_json = NULL;
json_t *jval = NULL;
json_t *opts_json = NULL;
MON_CMD cmd = MON_CMD_UNKNOWN;
- req_json = mon_req_parse(req_str); // TODO: Check errors
-
if (! json_is_object(req_json))
goto cleanup;
* Makes its own copy of the message, so caller can dispose of
* that after allocating the response.
*
- * Steals the reference to the payload JSON object. Does not modify the
- * object. Caller should not modify it after allocating the response or
- * undefined behavior will result. If allocation fails, the stolen reference
- * will be released --- if you need to keep a reference, use incref before
- * calling this.
+ * Increments the reference count of the payload if it is not null.
*
* @param mem_ctx talloc context for allocation
* @param req MON_REQ this response corresponds to
* @param payload JSON object to be send as payload, or null for no payload
* @return response allocated in the requested talloc context, null on failure
*/
-MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx,
- MON_REQ *req,
- MON_RESP_CODE code,
- const char *msg,
- json_t *payload)
+MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx, MON_RESP_CODE code, const char *msg, json_t *payload)
{
MON_RESP *resp = talloc(mem_ctx, MON_RESP);
if (resp) {
- resp->req = req;
resp->code = code;
resp->message = tr_new_name(msg);
+
resp->payload = payload;
+ if (resp->payload)
+ json_incref(resp->payload);
+
talloc_set_destructor((void *)resp, mon_resp_destructor);
if (resp->message == NULL) {
talloc_free(resp); // destructor will be called
}
/**
+ * Set or replace the response message
+ *
+ * Does not change the message if it fails
+ *
+ * @param resp
+ * @param new_msg
+ * @return 1 on success, 0 on error
+ */
+int mon_resp_set_message(MON_RESP *resp, const char *new_msg)
+{
+ TR_NAME *n = tr_new_name(new_msg);
+
+ if (n == NULL)
+ return 0; /* failed */
+
+ if (resp->message)
+ tr_free_name(resp->message);
+ resp->message = n;
+ return 1; /* succeeded */
+}
+
+/**
+ * Set or replace the payload
+ *
+ * Manages JSON reference counts
+ *
+ * @param resp
+ * @param new_payload
+ */
+void mon_resp_set_payload(MON_RESP *resp, json_t *new_payload)
+{
+ if (resp->payload)
+ json_decref(resp->payload);
+ resp->payload = new_payload;
+ if (resp->payload)
+ json_incref(new_payload);
+}
+
+/**
* Free a monitoring response
*
* @param resp request to free, must not be null
--- /dev/null
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <talloc.h>
+#include <jansson.h>
+
+#include <mon_internal.h>
+
+// Monitoring response decoder
+
+/**
+ * Decode a JSON response
+ *
+ * Expected format:
+ * {
+ * "code": 0,
+ * "message": "success",
+ * "payload": {
+ * "serial": 12345,
+ * ...
+ * }
+ * }
+ *
+ * Caller must free the return value with MON_REQ_free().
+ *
+ * @param mem_ctx talloc context for the returned struct
+ * @param resp_json reference to JSON request object
+ * @return decoded request struct or NULL on failure
+ */
+MON_RESP *mon_resp_decode(TALLOC_CTX *mem_ctx, json_t *resp_json)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ MON_RESP *resp = NULL;
+ json_t *jcode = NULL;
+ json_t *jmessage = NULL;
+ json_t *jpayload = NULL;
+
+ if (! json_is_object(resp_json))
+ goto cleanup;
+
+ /* Get the response code, which is an integer */
+ jcode = json_object_get(resp_json, "code");
+ if (! json_is_integer(jcode))
+ goto cleanup;
+
+ /* Get the response message, which is a string */
+ jmessage = json_object_get(resp_json, "message");
+ if (! json_is_string(jmessage))
+ goto cleanup;
+
+ /* Get the payload if we have one */
+ jpayload = json_object_get(resp_json, "payload");
+
+ /* Get a response in the tmp_ctx context. The payload may be null. */
+ resp = mon_resp_new(tmp_ctx,
+ (MON_RESP_CODE) json_integer_value(jcode),
+ json_string_value(jmessage),
+ jpayload);
+ if (resp == NULL)
+ goto cleanup;
+
+ /* Success! Put the request in the caller's talloc context */
+ talloc_steal(mem_ctx, resp);
+
+cleanup:
+ talloc_free(tmp_ctx);
+ if (resp_json)
+ json_decref(resp_json);
+
+ return resp;
+}
{
json_t *resp_json = NULL;
json_t *jval = NULL;
- const char *cmd_str = NULL;
/* Get a JSON object */
resp_json = json_object();
/* If we have a payload, add it */
if (resp->payload) {
- cmd_str = mon_cmd_to_string(resp->req->command); // key for the response payload
- object_set_or_free_and_return(resp_json, jval, cmd_str, resp->payload);
+ object_set_or_free_and_return(resp_json, jval, "payload", resp->payload);
}
return resp_json;
--- /dev/null
+/*
+ * Copyright (c) 2012, 2014-2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <jansson.h>
+#include <talloc.h>
+
+#include <trust_router/tr_dh.h>
+#include <mon_internal.h>
+#include <tr_msg.h>
+#include <gsscon.h>
+#include <tr_debug.h>
+
+
+MONC_INSTANCE *monc_new(TALLOC_CTX *mem_ctx)
+{
+ MONC_INSTANCE *monc=talloc(mem_ctx, MONC_INSTANCE);
+ if (monc!=NULL) {
+ monc->gssc = tr_gssc_instance_new(monc);
+ if (monc->gssc == NULL) {
+ talloc_free(monc);
+ return NULL;
+ }
+
+ monc->gssc->service_name = "trustmonitor";
+ }
+ return monc;
+}
+
+void monc_free(MONC_INSTANCE *monc)
+{
+ talloc_free(monc);
+}
+
+int monc_open_connection(MONC_INSTANCE *monc,
+ const char *server,
+ unsigned int port)
+{
+ return tr_gssc_open_connection(monc->gssc, server, port);
+}
+
+MON_RESP *monc_send_request(TALLOC_CTX *mem_ctx, MONC_INSTANCE *monc, MON_REQ *req)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ TR_MSG *msg = NULL;
+ TR_MSG *resp_msg = NULL;
+ MON_RESP *resp = NULL;
+
+ /* Create and populate a msg structure */
+ if (!(msg = talloc_zero(tmp_ctx, TR_MSG)))
+ goto cleanup;
+
+ msg->msg_type = MON_REQUEST;
+ tr_msg_set_mon_req(msg, req);
+
+ resp_msg = tr_gssc_exchange_msgs(tmp_ctx, monc->gssc, msg);
+ if (resp_msg == NULL)
+ goto cleanup;
+
+ resp = tr_msg_get_mon_resp(resp_msg);
+
+ /* if we got a response, steal it from resp_msg's context so we can return it */
+ if (resp)
+ talloc_steal(mem_ctx, resp);
+
+cleanup:
+ talloc_free(tmp_ctx);
+ return resp;
+}
+
+DH *monc_get_dh(MONC_INSTANCE *inst)
+{
+ return tr_gssc_get_dh(inst->gssc);
+}
+
+DH *monc_set_dh(MONC_INSTANCE *inst, DH *dh)
+{
+ return tr_gssc_set_dh(inst->gssc, dh);
+}
#include <sys/wait.h>
#include <tr_gss.h>
+#include "mons_handlers.h"
+
+static int mons_destructor(void *object)
+{
+ MONS_INSTANCE *mons = talloc_get_type_abort(object, MONS_INSTANCE);
+ if (mons->handlers) {
+ g_ptr_array_unref(mons->handlers);
+ }
+ return 0;
+}
+
/**
* Allocate a new MONS_INSTANCE
*
mons->req_handler = NULL;
mons->auth_handler = NULL;
mons->cookie = NULL;
+
+ /* Before any steps that may fail, install the destructor */
+ talloc_set_destructor((void *)mons, mons_destructor);
+
mons->authorized_gss_names = tr_gss_names_new(mons);
if (mons->authorized_gss_names == NULL) {
talloc_free(mons);
- mons = NULL;
+ return NULL;
+ }
+
+ mons->handlers = g_ptr_array_new();
+ if (mons->handlers == NULL) {
+ talloc_free(mons);
+ return NULL;
}
}
return mons;
* @param data pointer to a MONS_INSTANCE
* @return pointer to the response string or null to send no response
*/
-static char *mons_req_cb(TALLOC_CTX *mem_ctx, const char *req_str, void *data)
+static TR_MSG *mons_req_cb(TALLOC_CTX *mem_ctx, TR_MSG *req_msg, void *data)
{
- return "This is a response.";
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ MONS_INSTANCE *mons = talloc_get_type_abort(data, MONS_INSTANCE);
+ MON_REQ *req = NULL;
+ MON_RESP *resp = NULL;
+ TR_MSG *resp_msg = NULL; /* This is the response value */
+
+ /* Validate inputs */
+ if (req_msg == NULL)
+ goto cleanup;
+
+ req = tr_msg_get_mon_req(req_msg);
+ if (req == NULL) {
+ /* this is an internal error */
+ tr_err("mons_req_cb: Received incorrect message type (was %d, expected %d)",
+ tr_msg_get_msg_type(req_msg),
+ MON_REQUEST);
+ /* TODO send an error response */
+ goto cleanup;
+ }
+
+ /* Allocate a response message */
+ resp_msg = talloc(tmp_ctx, TR_MSG);
+ if (resp_msg == NULL) {
+ /* can't return a message, just emit an error */
+ tr_crit("mons_req_cb: Error allocating response message.");
+ goto cleanup;
+ }
+
+ /* Handle the request */
+ resp = mons_handle_request(resp_msg, mons, req);
+ if (resp == NULL) {
+ /* error processing the request */
+ /* TODO send back an error */
+ goto cleanup;
+ }
+
+ /* Set the response message payload */
+ tr_msg_set_mon_resp(resp_msg, resp);
+
+ /* Put the response message in the caller's context so it does not get freed when we exit */
+ talloc_steal(mem_ctx, resp_msg);
+
+cleanup:
+ talloc_free(tmp_ctx);
+ return resp_msg;
}
/**
--- /dev/null
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Handlers for monitoring requests */
+
+#include <gmodule.h>
+
+#include <tr_debug.h>
+#include <mon_internal.h>
+#include <mons_handlers.h>
+
+
+/* Static Prototypes */
+static int dispatch_entry_matches(MONS_DISPATCH_TABLE_ENTRY *e, MON_CMD command, MON_OPT_TYPE opt_type);
+static MONS_HANDLER_FUNC *mons_find_handler(MONS_INSTANCE *mons, MON_CMD cmd, MON_OPT_TYPE opt_type);
+static void request_helper(void *element, void *data);
+
+struct request_helper_data {
+ MON_CMD command;
+ MON_OPT_TYPE opt_type;
+ json_t *payload;
+};
+
+/**
+ * Call the appropriate handler for a request
+ *
+ * TODO: report errors from handlers
+ *
+ * @return a MON_RESP structure or null if there was a processing error
+ */
+MON_RESP *mons_handle_request(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req)
+{
+ MON_RESP *resp = NULL;
+ json_t *payload = NULL;
+ struct request_helper_data cookie;
+ size_t ii = 0;
+
+ tr_debug("mons_handle_request: Handling a request");
+
+ /* Start off by allocating our response with a generic error message */
+ resp = mon_resp_new(mem_ctx,
+ MON_RESP_ERROR,
+ "Error processing show request",
+ NULL);
+ if (resp == NULL) {
+ /* we can't respond, just return */
+ tr_crit("mons_handle_request: Error allocating response structure.");
+ goto cleanup;
+ }
+
+ /* Now get a JSON object for our return payload */
+ payload = json_object();
+ if (payload == NULL) {
+ tr_crit("mons_handle_request: Error allocating response payload.");
+ goto cleanup; /* This will return the generic error message set earlier */
+ }
+
+ /* Now call handlers */
+ cookie.command = req->command;
+ cookie.payload = payload; /* borrowed reference */
+
+ if (mon_req_opt_count(req) == 0) {
+ /* call every handler that matches the command */
+ cookie.opt_type = OPT_TYPE_ANY;
+ g_ptr_array_foreach(mons->handlers, request_helper, &cookie);
+ } else {
+ /* call only those handlers that match an option */
+ for (ii=0; ii < mon_req_opt_count(req); ii++) {
+ cookie.opt_type = mon_req_opt_index(req, ii)->type;
+ /* Loop over all handlers - we know we can only have one match for each opt type */
+ g_ptr_array_foreach(mons->handlers, request_helper, &cookie);
+ }
+ }
+
+ /* If we get here, then we successfully processed the request. Return a successful reply. */
+ if (mon_resp_set_message(resp, "success") == 0) {
+ /* Failed to set the response message to success - fail ironically */
+ tr_crit("mons_handle_request: Error setting response message to 'success'.");
+ goto cleanup;
+ }
+
+ /* Attach the accumulated payload to the response */
+ if (json_object_size(payload) > 0)
+ mon_resp_set_payload(resp, payload);
+
+ resp->code = MON_RESP_SUCCESS; /* at last... */
+ tr_debug("mons_handle_request: Successfully processed request.");
+
+cleanup:
+ if (payload)
+ json_decref(payload);
+ return resp;
+}
+
+/**
+ * Register a handler for a command/option combination
+ *
+ * @param mons
+ * @param cmd
+ * @param opt_type
+ * @param f
+ * @param cookie
+ * @return
+ */
+MON_RC mons_register_handler(MONS_INSTANCE *mons,
+ MON_CMD cmd,
+ MON_OPT_TYPE opt_type,
+ MONS_HANDLER_FUNC *f,
+ void *cookie)
+{
+ MONS_DISPATCH_TABLE_ENTRY *entry = NULL;
+
+ if (mons_find_handler(mons, cmd, opt_type) != NULL) {
+ return MON_ERROR;
+ }
+
+ /* Put these in the mons talloc context so we don't have to muck about with
+ * a free function for the GPtrArray */
+ entry = talloc(mons, MONS_DISPATCH_TABLE_ENTRY);
+ if (entry == NULL) {
+ return MON_NOMEM;
+ }
+ entry->command = cmd;
+ entry->opt_type = opt_type;
+ entry->handler = f;
+ entry->cookie = cookie;
+
+ g_ptr_array_add(mons->handlers, entry);
+ return MON_SUCCESS;
+}
+
+/**
+ * Two table entries match if none of the commands or opt_types are unknown,
+ * if the commands match, and if the opt types either match or at least one is
+ * OPT_TYPE_ANY.
+ *
+ * No comparison of the handler pointer is included.
+ *
+ * @return 1 if the two match, 0 if not
+ */
+static int dispatch_entry_matches(MONS_DISPATCH_TABLE_ENTRY *e,
+ MON_CMD command,
+ MON_OPT_TYPE opt_type)
+{
+ if ((command == MON_CMD_UNKNOWN) || (opt_type == OPT_TYPE_UNKNOWN))
+ return 0; /* request is invalid */
+
+ if ((e->command == MON_CMD_UNKNOWN) || (e->opt_type == OPT_TYPE_UNKNOWN))
+ return 0; /* e1 is invalid */
+
+ if (e->command != command)
+ return 0; /* commands do not match */
+
+ if (e->opt_type == opt_type)
+ return 1; /* exact match */
+
+ if ( (e->opt_type == OPT_TYPE_ANY) || (opt_type == OPT_TYPE_ANY) )
+ return 1; /* one is a wildcard */
+
+ return 0; /* commands matched but opt_types did not */
+}
+
+static MONS_HANDLER_FUNC *mons_find_handler(MONS_INSTANCE *mons, MON_CMD cmd, MON_OPT_TYPE opt_type)
+{
+ guint index;
+
+ for (index=0; index < mons->handlers->len; index++) {
+ if (dispatch_entry_matches(g_ptr_array_index(mons->handlers, index), cmd, opt_type))
+ return g_ptr_array_index(mons->handlers, index);
+ }
+ return NULL;
+}
+
+/**
+ * This calls every request handler that matches a command/opt_type,
+ * gathering their results.
+ *
+ * @param element
+ * @param data
+ */
+static void request_helper(void *element, void *data)
+{
+ MONS_DISPATCH_TABLE_ENTRY *entry = talloc_get_type_abort(element, MONS_DISPATCH_TABLE_ENTRY);
+ struct request_helper_data *helper_data = data;
+
+ if (dispatch_entry_matches(entry, helper_data->command, helper_data->opt_type)) {
+ json_object_set(helper_data->payload,
+ mon_opt_type_to_string(entry->opt_type),
+ entry->handler(entry->cookie));
+ }
+}
+
req_json_str = read_file(filename);
assert(req_json_str);
- req = mon_req_decode(NULL, req_json_str);
+ req = mon_req_parse(NULL, req_json_str);
assert(req);
assert(equal(req, expected));
req = mon_req_new(NULL, MON_CMD_RECONFIGURE);
assert(req);
- resp = mon_resp_new(NULL, req, code, message, NULL);
+ resp = mon_resp_new(NULL, code, message, NULL);
assert(resp);
resp_json = mon_resp_encode(resp);
mon_opt_type_to_string(OPT_TYPE_SHOW_TID_REQ_COUNT),
json_integer(1432)));
- resp = mon_resp_new(NULL, req, MON_RESP_SUCCESS, "success", payload);
+ resp = mon_resp_new(NULL, MON_RESP_SUCCESS, "success", payload);
assert(resp);
resp_json = mon_resp_encode(resp);
/* Create a TID client instance & the client DH */
tidc = tidc_create();
- if (NULL == (tidc->client_dh = tr_create_dh_params(NULL, 0))) {
+ tidc_set_dh(tidc, tr_create_dh_params(NULL, 0));
+ if (tidc_get_dh(tidc) == NULL) {
printf("Error creating client DH params.\n");
return 1;
}
#include <jansson.h>
#include <talloc.h>
+#include <gsscon.h>
#include <trust_router/tr_dh.h>
#include <tid_internal.h>
#include <tr_msg.h>
-#include <gsscon.h>
#include <tr_debug.h>
int tmp_len = 32;
-static int tidc_destructor(void *obj)
-{
- TIDC_INSTANCE *tidc=talloc_get_type_abort(obj, TIDC_INSTANCE);
- if (NULL!=tidc) {
- if (NULL!=tidc->client_dh)
- tr_destroy_dh_params(tidc->client_dh);
- }
- return 0;
-}
-
/* creates struct in talloc null context */
TIDC_INSTANCE *tidc_create(void)
{
TIDC_INSTANCE *tidc=talloc(NULL, TIDC_INSTANCE);
if (tidc!=NULL) {
- tidc->client_dh=NULL;
- talloc_set_destructor((void *)tidc, tidc_destructor);
+ tidc->gssc = tr_gssc_instance_new(tidc);
+ if (tidc->gssc == NULL) {
+ talloc_free(tidc);
+ return NULL;
+ }
+
+ tidc->gssc->service_name = "trustidentity";
}
return tidc;
}
}
int tidc_open_connection (TIDC_INSTANCE *tidc,
- const char *server,
- unsigned int port,
- gss_ctx_id_t *gssctx)
+ const char *server,
+ unsigned int port,
+ gss_ctx_id_t *gssctx)
{
- int err = 0;
- int conn = -1;
unsigned int use_port = 0;
+ tidc->gssc->gss_ctx = gssctx;
if (0 == port)
use_port = TID_PORT;
else
use_port = port;
- tr_debug("tidc_open_connection: opening tidc connection to %s:%d", server, port);
- err = gsscon_connect(server, use_port, "trustidentity", &conn, gssctx);
-
- if (!err)
- return conn;
+ tr_debug("tidc_open_connection: opening tidc connection to %s:%d", server, use_port);
+ if (0 == tr_gssc_open_connection(tidc->gssc, server, use_port))
+ return tidc->gssc->conn;
else
return -1;
}
int tidc_send_request (TIDC_INSTANCE *tidc,
- int conn,
- gss_ctx_id_t gssctx,
- const char *rp_realm,
- const char *realm,
- const char *comm,
- TIDC_RESP_FUNC *resp_handler,
- void *cookie)
+ int conn,
+ gss_ctx_id_t gssctx,
+ const char *rp_realm,
+ const char *realm,
+ const char *comm,
+ TIDC_RESP_FUNC *resp_handler,
+ void *cookie)
{
TID_REQ *tid_req = NULL;
int rc;
+ int orig_conn = 0;
+ gss_ctx_id_t *orig_gss_ctx = NULL;
+
+ /* For ABI compatibility, replace the generic GSS client parameters
+ * with the arguments we were passed. */
+ orig_conn = tidc->gssc->conn; /* save to restore later */
+ if (conn != tidc->gssc->conn) {
+ tr_warning("tidc_send_request: WARNING: socket connection FD does not match FD opened by tidc_open_connection()");
+ tidc->gssc->conn = conn;
+ }
+ orig_gss_ctx = tidc->gssc->gss_ctx; /* save to restore later */
+ if (gssctx != *(tidc->gssc->gss_ctx)) {
+ tr_warning("tidc_send_request: WARNING: sending request with different GSS context than used for tidc_open_connection()");
+ *tidc->gssc->gss_ctx = gssctx;
+ }
/* Create and populate a TID req structure */
if (!(tid_req = tid_req_new()))
- return -1;
+ goto error;
tid_req->conn = conn;
tid_req->gssctx = gssctx;
goto error;
}
- tid_req->tidc_dh = tr_dh_dup(tidc->client_dh);
+ tid_req->tidc_dh = tr_dh_dup(tidc->gssc->client_dh);
rc = tidc_fwd_request(tidc, tid_req, resp_handler, cookie);
goto cleanup;
error:
rc = -1;
cleanup:
- tid_req_free(tid_req);
+ if (tid_req)
+ tid_req_free(tid_req);
+
+ tidc->gssc->conn = orig_conn;
+ tidc->gssc->gss_ctx = orig_gss_ctx;
return rc;
}
int tidc_fwd_request(TIDC_INSTANCE *tidc,
TID_REQ *tid_req,
- TIDC_RESP_FUNC *resp_handler,
+ TIDC_RESP_FUNC *resp_handler,
void *cookie)
{
- char *req_buf = NULL;
- char *resp_buf = NULL;
- size_t resp_buflen = 0;
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
TR_MSG *msg = NULL;
TR_MSG *resp_msg = NULL;
- int err;
int rc = 0;
/* Create and populate a TID msg structure */
- if (!(msg = talloc_zero(tid_req, TR_MSG)))
+ if (!(msg = talloc_zero(tmp_ctx, TR_MSG)))
goto error;
msg->msg_type = TID_REQUEST;
tr_msg_set_req(msg, tid_req);
- /* store the response function and cookie */
- // tid_req->resp_func = resp_handler;
- // tid_req->cookie = cookie;
-
- /* Encode the request into a json string */
- if (!(req_buf = tr_msg_encode(NULL, msg))) {
- tr_err("tidc_fwd_request: Error encoding TID request.\n");
- goto error;
- }
-
- tr_debug( "tidc_fwd_request: Sending TID request:\n");
- tr_debug( "%s\n", req_buf);
+ tr_debug( "tidc_fwd_request: Sending TID request\n");
/* Send the request over the connection */
- if (err = gsscon_write_encrypted_token (tid_req->conn, tid_req->gssctx, req_buf,
- strlen(req_buf))) {
- tr_err( "tidc_fwd_request: Error sending request over connection.\n");
+ resp_msg = tr_gssc_exchange_msgs(tmp_ctx, tidc->gssc, msg);
+ if (resp_msg == NULL)
goto error;
- }
-
- /* TBD -- queue request on instance, read resps in separate thread */
-
- /* Read the response from the connection */
- /* TBD -- timeout? */
- if (err = gsscon_read_encrypted_token(tid_req->conn, tid_req->gssctx, &resp_buf, &resp_buflen)) {
- if (resp_buf)
- free(resp_buf);
- goto error;
- }
-
- tr_debug( "tidc_fwd_request: Response Received (%u bytes).\n", (unsigned) resp_buflen);
- tr_debug( "%s\n", resp_buf);
-
- if (NULL == (resp_msg = tr_msg_decode(resp_buf, resp_buflen))) {
- tr_err( "tidc_fwd_request: Error decoding response.\n");
- goto error;
- }
/* TBD -- Check if this is actually a valid response */
if (TID_RESPONSE != tr_msg_get_msg_type(resp_msg)) {
error:
rc = -1;
cleanup:
- if (msg)
- talloc_free(msg);
- if (req_buf)
- free(req_buf);
- if (resp_buf)
- free(resp_buf);
- if (resp_msg)
- tr_msg_free_decoded(resp_msg);
+ talloc_free(tmp_ctx);
return rc;
}
DH * tidc_get_dh(TIDC_INSTANCE *inst)
{
- return inst->client_dh;
+ return tr_gssc_get_dh(inst->gssc);
}
DH *tidc_set_dh(TIDC_INSTANCE *inst, DH *dh)
{
- inst->client_dh = dh;
- return dh;
+ return tr_gssc_set_dh(inst->gssc, dh);
}
* @param data pointer to a TIDS_INSTANCE
* @return pointer to the response string or null to send no response
*/
-static char *tids_req_cb(TALLOC_CTX *mem_ctx, const char *req_str, void *data)
+static TR_MSG *tids_req_cb(TALLOC_CTX *mem_ctx, TR_MSG *mreq, void *data)
{
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
TIDS_INSTANCE *tids = talloc_get_type_abort(data, TIDS_INSTANCE);
- TR_MSG *mreq = NULL;
TID_REQ *req = NULL;
TID_RESP *resp = NULL;
- char *resp_str = NULL;
+ TR_MSG *resp_msg = NULL; /* this is the return value */
int rc = 0;
- mreq = tr_msg_decode(req_str, strlen(req_str)); // allocates memory on success!
- if (mreq == NULL) {
- tr_debug("tids_req_cb: Error decoding request.");
- return NULL;
- }
-
/* If this isn't a TID Request, just drop it. */
if (mreq->msg_type != TID_REQUEST) {
- tr_msg_free_decoded(mreq);
tr_debug("tids_req_cb: Not a TID request, dropped.");
- return NULL;
+ goto cleanup;
}
/* Get a handle on the request itself. Don't free req - it belongs to mreq */
req = tr_msg_get_req(mreq);
- /* Allocate a response structure and populate common fields. The resp is in req's talloc context,
- * which will be cleaned up when mreq is freed. */
- resp = tids_create_response(req, req);
+ /* Allocate a response message */
+ resp_msg = talloc(tmp_ctx, TR_MSG);
+ if (resp_msg == NULL) {
+ /* We cannot create a response message, so all we can really do is emit
+ * an error message and return. */
+ tr_crit("tids_req_cb: Error allocating response message.");
+ goto cleanup;
+ }
+
+ /* Allocate a response structure and populate common fields. Put it in the
+ * response message's talloc context. */
+ resp = tids_create_response(resp_msg, req);
if (resp == NULL) {
/* If we were unable to create a response, we cannot reply. Log an
* error if we can, then drop the request. */
- tr_msg_free_decoded(mreq);
tr_crit("tids_req_cb: Error creating response structure.");
- return NULL;
+ resp_msg = NULL; /* the contents are in tmp_ctx, so they will still be cleaned up */
+ goto cleanup;
}
+ /* Now officially assign the response to the message. */
+ tr_msg_set_resp(resp_msg, resp);
/* Handle the request and fill in resp */
rc = tids_handle_request(tids, req, resp);
/* Fall through, to send the response, either way */
}
- /* Convert the completed response into an encoded response */
- resp_str = tids_encode_response(mem_ctx, resp);
+ /* put the response message in the caller's context */
+ talloc_steal(mem_ctx, resp_msg);
- /* Finished; free the request and return */
- tr_msg_free_decoded(mreq); // this frees req and resp, too
- return resp_str;
+cleanup:
+ talloc_free(tmp_ctx);
+ return resp_msg;
}
TIDS_INSTANCE *tids_new(TALLOC_CTX *mem_ctx)
#include <event2/event.h>
#include <talloc.h>
#include <signal.h>
+#include <time.h>
#include <tid_internal.h>
#include <mon_internal.h>
pthread_sigmask(SIG_BLOCK, &signals, NULL);
}
+/* TODO move this function */
+static json_t *tr_mon_handle_version(void *cookie)
+{
+ return json_string(PACKAGE_VERSION);
+}
+
+static json_t *tr_mon_handle_uptime(void *cookie)
+{
+ time_t *start_time = cookie;
+ return json_integer(time(NULL) - (*start_time));
+}
+
int main(int argc, char *argv[])
{
TALLOC_CTX *main_ctx=NULL;
struct tr_socket_event mon_ev = {0};
struct event *cfgwatch_ev;
+ time_t start_time = time(NULL); /* TODO move this? */
+
configure_signals();
/* we're going to be multithreaded, so disable null context tracking */
tr->mons->tids = tr->tids;
tr->mons->trps = tr->trps;
+ /* TODO do this more systematically */
+ mons_register_handler(tr->mons, MON_CMD_SHOW, OPT_TYPE_SHOW_VERSION, tr_mon_handle_version, NULL);
+ mons_register_handler(tr->mons, MON_CMD_SHOW, OPT_TYPE_SHOW_UPTIME, tr_mon_handle_uptime, &start_time);
+
/***** process configuration *****/
tr->cfgwatch=tr_cfgwatch_create(tr);
if (tr->cfgwatch == NULL) {
--- /dev/null
+/*
+ * Copyright (c) 2012-2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <talloc.h>
+#include <argp.h>
+#include <unistd.h>
+
+#include <mon_internal.h>
+#include <gsscon.h>
+#include <tr_debug.h>
+#include <trust_router/tr_dh.h>
+
+
+/* command-line option setup */
+
+/* argp global parameters */
+const char *argp_program_bug_address=PACKAGE_BUGREPORT; /* bug reporting address */
+
+/* doc strings */
+static const char doc[]=PACKAGE_NAME " - TR Monitoring Client";
+static const char arg_doc[]="<message> <server> [<port>]"; /* string describing arguments, if any */
+
+/* define the options here. Fields are:
+ * { long-name, short-name, variable name, options, help description } */
+static const struct argp_option cmdline_options[] = {
+ { "repeat", 'r', "N", OPTION_ARG_OPTIONAL, "Repeat message until terminated, or N times." },
+ {NULL}
+};
+
+/* structure for communicating with option parser */
+struct cmdline_args {
+ char *msg;
+ char *server;
+ unsigned int port; /* optional */
+ int repeat; /* how many times to repeat, or -1 for infinite */
+};
+
+/* parser for individual options - fills in a struct cmdline_args */
+static error_t parse_option(int key, char *arg, struct argp_state *state)
+{
+ long tmp_l = 0;
+
+ /* get a shorthand to the command line argument structure, part of state */
+ struct cmdline_args *arguments=state->input;
+
+ switch (key) {
+ case 'r':
+ if (arg==NULL)
+ arguments->repeat=-1;
+ else
+ tmp_l = strtol(arg, NULL, 10);
+ if ((errno == 0) && (tmp_l > 0) && (tmp_l < INT_MAX))
+ arguments->repeat = (int) tmp_l;
+ else
+ argp_usage(state);
+ break;
+
+ case ARGP_KEY_ARG: /* handle argument (not option) */
+ switch (state->arg_num) {
+ case 0:
+ arguments->msg=arg;
+ break;
+
+ case 1:
+ arguments->server=arg;
+ break;
+
+ case 2:
+ tmp_l = strtol(arg, NULL, 10);
+ if (errno || (tmp_l < 0) || (tmp_l > 65535)) /* max valid port */
+ argp_usage(state);
+
+ arguments->port=(unsigned int) tmp_l;
+ break;
+
+ default:
+ /* too many arguments */
+ argp_usage(state);
+ }
+ break;
+
+ case ARGP_KEY_END: /* no more arguments */
+ if (state->arg_num < 2) {
+ /* not enough arguments encountered */
+ argp_usage(state);
+ }
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0; /* success */
+}
+
+
+/* assemble the argp parser */
+static struct argp argp = {cmdline_options, parse_option, arg_doc, doc};
+
+int main(int argc, char *argv[])
+{
+ TALLOC_CTX *main_ctx=talloc_new(NULL);
+ MONC_INSTANCE *monc = NULL;
+ MON_REQ *req = NULL;
+ MON_RESP *resp = NULL;
+
+ struct cmdline_args opts;
+ int retval=1; /* exit with an error status unless this gets set to zero */
+
+ /* parse the command line*/
+ /* set defaults */
+ opts.msg=NULL;
+ opts.server=NULL;
+ opts.port=TRP_PORT;
+ opts.repeat=1;
+
+ argp_parse(&argp, argc, argv, 0, 0, &opts);
+
+ /* Use standalone logging */
+ tr_log_open();
+
+ /* set logging levels */
+ talloc_set_log_stderr();
+ tr_log_threshold(LOG_CRIT);
+ tr_console_threshold(LOG_DEBUG);
+
+ printf("TR Monitor:\nServer = %s, port = %i\n", opts.server, opts.port);
+
+ /* Create a MON client instance & the client DH */
+ monc = monc_new(main_ctx);
+ if (monc == NULL) {
+ printf("Error allocating client instance.\n");
+ goto cleanup;
+ }
+
+
+ /* fill in the DH parameters */
+ monc_set_dh(monc, tr_create_dh_params(NULL, 0));
+ if (monc_get_dh(monc) == NULL) {
+ printf("Error creating client DH params.\n");
+ goto cleanup;
+ }
+
+ /* Set-up MON connection */
+ if (0 != monc_open_connection(monc, opts.server, opts.port)) {
+ /* Handle error */
+ printf("Error opening connection to %s:%d.\n", opts.server, opts.port);
+ goto cleanup;
+ };
+
+ req = mon_req_new(main_ctx, MON_CMD_SHOW);
+
+ /* Send a MON request and get the response */
+ resp = monc_send_request(main_ctx, monc, req);
+
+ if (resp == NULL) {
+ /* Handle error */
+ printf("Error executing monitoring request.\n");
+ goto cleanup;
+ }
+
+ /* success */
+ retval = 0;
+
+ /* Clean-up the MON client instance, and exit */
+cleanup:
+ talloc_free(main_ctx);
+ return retval;
+}
+
if (buflen>=MAX_MSG_LEN)
printf("Warning: file may exceed maximum message length (%d bytes).\n", MAX_MSG_LEN);
- msg=tr_msg_decode(buf, buflen);
+ msg= tr_msg_decode(NULL, buf, buflen);
/* if (rc==TRP_SUCCESS)
trp_msg_print(msg);*/
tr_debug("trps_read_message: message received, %u bytes.", (unsigned) buflen);
tr_debug("trps_read_message: %.*s", buflen, buf);
- *msg=tr_msg_decode(buf, buflen);
+ *msg= tr_msg_decode(NULL, buf, buflen);
free(buf);
if (*msg==NULL)
return TRP_NOPARSE;