static int tr_msg_decode_one_server(json_t *jsrvr, TID_SRVR_BLK *srvr) { json_t *jsrvr_addr = NULL; json_t *jsrvr_kn = NULL; json_t *jsrvr_dh = NULL; json_t *jsrvr_expire = NULL; if (jsrvr == NULL) return -1; if ((NULL == (jsrvr_addr = json_object_get(jsrvr, "server_addr"))) || (NULL == (jsrvr_kn = json_object_get(jsrvr, "key_name"))) || (NULL == (jsrvr_dh = json_object_get(jsrvr, "server_dh")))) { tr_notice("tr_msg_decode_one_server(): Error parsing required fields."); return -1; } /* TBD -- handle IPv6 Addresses */ inet_aton(json_string_value(jsrvr_addr), &(srvr->aaa_server_addr)); srvr->key_name = tr_new_name((char *)json_string_value(jsrvr_kn)); srvr->aaa_server_dh = tr_msg_decode_dh(jsrvr_dh); srvr->path = json_object_get(jsrvr, "path"); jsrvr_expire = json_object_get(jsrvr, "key_expiration"); if (jsrvr_expire && json_is_string(jsrvr_expire)) { if (!g_time_val_from_iso8601(json_string_value(jsrvr_expire), &srvr->key_expiration)) tr_notice("Key expiration %s cannot be parsed", json_string_value(jsrvr_expire)); } return 0; }
static int tids_handle_request(TIDS_INSTANCE *tids, TID_REQ *req, TID_RESP *resp) { int rc=-1; /* Check that this is a valid TID Request. If not, send an error return. */ if ((!req) || (!(req->rp_realm)) || (!(req->realm)) || (!(req->comm))) { tr_notice("tids_handle_request(): Not a valid TID Request."); tid_resp_set_result(resp, TID_ERROR); tid_resp_set_err_msg(resp, tr_new_name("Bad request format")); return -1; } tr_debug("tids_handle_request: adding self to req path."); tid_req_add_path(req, tids->hostname, tids->tids_port); /* Call the caller's request handler */ /* TBD -- Handle different error returns/msgs */ if (0 > (rc = (*tids->req_handler)(tids, req, resp, tids->cookie))) { /* set-up an error response */ tr_debug("tids_handle_request: req_handler returned error."); tid_resp_set_result(resp, TID_ERROR); if (!tid_resp_get_err_msg(resp)) /* Use msg set by handler, if any */ tid_resp_set_err_msg(resp, tr_new_name("Internal processing error")); } else { /* set-up a success response */ tr_debug("tids_handle_request: req_handler returned success."); tid_resp_set_result(resp, TID_SUCCESS); resp->err_msg = NULL; /* No error msg on successful return */ } return rc; }
/** * Encode/send a response * * Part of the public interface * * @param tids not actually used, but kept for ABI compatibility * @param req * @param resp * @return */ int tids_send_response (TIDS_INSTANCE *tids, TID_REQ *req, TID_RESP *resp) { int err; char *resp_buf; if ((!tids) || (!req) || (!resp)) { tr_debug("tids_send_response: Invalid parameters."); return -1; } /* Never send a second response if we already sent one. */ if (req->resp_sent) return 0; resp_buf = tids_encode_response(NULL, NULL); if (resp_buf == NULL) { tr_err("tids_send_response: Error encoding json response."); tr_audit_req(req); return -1; } tr_debug("tids_send_response: Encoded response: %s", resp_buf); /* If external logging is enabled, fire off a message */ /* TODO Can be moved to end once segfault in gsscon_write_encrypted_token fixed */ tr_audit_resp(resp); /* Send the response over the connection */ err = gsscon_write_encrypted_token (req->conn, req->gssctx, resp_buf, strlen(resp_buf) + 1); if (err) { tr_notice("tids_send_response: Error sending response over connection."); tr_audit_req(req); return -1; } /* indicate that a response has been sent for this request */ req->resp_sent = 1; free(resp_buf); return 0; }
/** * Handle a request/response connection * * Authorizes/authenticates the connection, then reads a response, passes that to a * callback to get a response, sends that, then returns. * * @param conn connection file descriptor * @param acceptor_service acceptor name to present * @param acceptor_hostname acceptor hostname to present * @param auth_cb callback for authorization * @param auth_cookie cookie for the auth_cb * @param req_cb callback to handle the request and produce the response * @param req_cookie cookie for the req_cb */ TR_GSS_RC tr_gss_handle_connection(int conn, const char *acceptor_service, const char *acceptor_hostname, TR_GSS_AUTH_FN auth_cb, void *auth_cookie, TR_GSS_HANDLE_REQ_FN req_cb, void *req_cookie) { 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; TR_GSS_RC rc = TR_GSS_ERROR; tr_debug("tr_gss_handle_connection: Attempting to accept %s connection on fd %d.", acceptor_service, conn); if (tr_gss_auth_connection(conn, acceptor_service, acceptor_hostname, &gssctx, auth_cb, auth_cookie)) { tr_notice("tr_gss_handle_connection: Error authorizing connection."); goto cleanup; } tr_debug("tr_gss_handle_connection: Connection authorized"); // TODO: should there be a timeout on this? 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) { // an error occurred, give up tr_notice("tr_gss_handle_connection: Error reading request"); goto cleanup; } 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 */ rc = req_cb(tmp_ctx, req_msg, &resp_msg, req_cookie); 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_err("tr_gss_handle_connection: Error writing response"); goto cleanup; } /* we successfully sent a response */ rc = TR_GSS_SUCCESS; cleanup: talloc_free(tmp_ctx); return rc; }
static TID_REQ *tr_msg_decode_tidreq(json_t *jreq) { TID_REQ *treq = NULL; json_t *jrp_realm = NULL; json_t *jrealm = NULL; json_t *jcomm = NULL; json_t *jorig_coi = NULL; json_t *jdh = NULL; json_t *jpath = NULL; json_t *jexpire_interval = NULL; if (!(treq =tid_req_new())) { tr_crit("tr_msg_decode_tidreq(): Error allocating TID_REQ structure."); return NULL; } /* store required fields from request */ if ((NULL == (jrp_realm = json_object_get(jreq, "rp_realm"))) || (NULL == (jrealm = json_object_get(jreq, "target_realm"))) || (NULL == (jcomm = json_object_get(jreq, "community")))) { tr_notice("tr_msg_decode(): Error parsing required fields."); tid_req_free(treq); return NULL; } jpath = json_object_get(jreq, "path"); jexpire_interval = json_object_get(jreq, "expiration_interval"); treq->rp_realm = tr_new_name((char *)json_string_value(jrp_realm)); treq->realm = tr_new_name((char *)json_string_value(jrealm)); treq->comm = tr_new_name((char *)json_string_value(jcomm)); /* Get DH Info from the request */ if (NULL == (jdh = json_object_get(jreq, "dh_info"))) { tr_debug("tr_msg_decode(): Error parsing dh_info."); tid_req_free(treq); return NULL; } treq->tidc_dh = tr_msg_decode_dh(jdh); /* store optional "orig_coi" field */ if (NULL != (jorig_coi = json_object_get(jreq, "orig_coi"))) { treq->orig_coi = tr_new_name((char *)json_string_value(jorig_coi)); } treq->cons = (TR_CONSTRAINT_SET *) json_object_get(jreq, "constraints"); if (treq->cons) { if (!tr_constraint_set_validate(treq->cons)) { tr_debug("Constraint set validation failed"); tid_req_free(treq); return NULL; } json_incref((json_t *) treq->cons); tid_req_cleanup_json(treq, (json_t *) treq->cons); } if (jpath) { json_incref(jpath); treq->path = jpath; tid_req_cleanup_json(treq, jpath); } if (jexpire_interval) treq->expiration_interval = json_integer_value(jexpire_interval); return treq; }