From e0169137250febe055236d6bbb0faee7a3c4f569 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Mon, 8 Aug 2011 17:48:56 +0200 Subject: [PATCH] refactoring of tnc-ifmap plugin --- .../plugins/tnc_ifmap/tnc_ifmap_listener.c | 15 +- .../plugins/tnc_ifmap/tnc_ifmap_soap.c | 515 +++++++++--------- 2 files changed, 257 insertions(+), 273 deletions(-) diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c index 4a76fc692..b7a889c3d 100644 --- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c @@ -52,13 +52,7 @@ static bool publish_ike_sa(private_tnc_ifmap_listener_t *this, id = ike_sa->get_other_id(ike_sa); host = ike_sa->get_other_host(ike_sa); - DBG2(DBG_TNC, "sending ifmap->publish"); - if (!this->ifmap->publish(this->ifmap, ike_sa_id, id, host, up)) - { - DBG1(DBG_TNC, "ifmap->publish with MAP server failed"); - return FALSE; - } - return TRUE; + return this->ifmap->publish(this->ifmap, ike_sa_id, id, host, up); } /** @@ -126,23 +120,16 @@ tnc_ifmap_listener_t *tnc_ifmap_listener_create(bool reload) destroy(this); return NULL; } - - DBG2(DBG_TNC, "sending ifmap->newSession"); if (!this->ifmap->newSession(this->ifmap)) { - DBG1(DBG_TNC, "ifmap->newSession with MAP server failed"); destroy(this); return NULL; } - - DBG2(DBG_TNC, "sending ifmap->purgePublisher"); if (!this->ifmap->purgePublisher(this->ifmap)) { - DBG1(DBG_TNC, "ifmap->purgePublisher with MAP server failed"); destroy(this); return NULL; } - if (reload) { if (!reload_metadata(this)) diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c index 5fae6eab4..acef2cc5e 100644 --- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c +++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c @@ -65,91 +65,120 @@ struct private_tnc_ifmap_soap_t { }; +/** + * Send request and receive result via SOAP + */ +static bool send_receive(private_tnc_ifmap_soap_t *this, + char *request_qname, axiom_node_t *request, + char *receipt_qname, axiom_node_t **result) + +{ + axiom_node_t *parent, *node; + axiom_element_t *el; + axutil_qname_t *qname; + bool success = FALSE; + + /* send request and receive result */ + DBG2(DBG_TNC, "sending ifmap %s", request_qname); + + parent = axis2_svc_client_send_receive(this->svc_client, this->env, request); + if (!parent) + { + DBG1(DBG_TNC, "no ifmap %s received from MAP server", receipt_qname); + return FALSE; + } + + /* pre-process result */ + node = axiom_node_get_first_child(parent, this->env); + if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT) + { + el = (axiom_element_t *)axiom_node_get_data_element(node, this->env); + + qname = axiom_element_get_qname(el, this->env, node); + success = streq(receipt_qname, axutil_qname_to_string(qname, this->env)); + if (success) + { + DBG2(DBG_TNC, "received ifmap %s", receipt_qname); + if (result) + { + *result = parent; + } + else + { + /* no further processing requested */ + axiom_node_free_tree(parent, this->env); + } + return TRUE; + } + /* TODO proper error handling */ + DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node)); + } + + /* free parent in the error case */ + axiom_node_free_tree(parent, this->env); + + return FALSE; +} + METHOD(tnc_ifmap_soap_t, newSession, bool, private_tnc_ifmap_soap_t *this) { axiom_node_t *request, *result, *node; axiom_element_t *el; axiom_namespace_t *ns; - axiom_attribute_t *attr; axis2_char_t *value; - axutil_qname_t *qname; - bool success = FALSE; /* build newSession request */ ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); el = axiom_element_create(this->env, NULL, "newSession", ns, &request); - attr = axiom_attribute_create(this->env, "max-poll-result-size", "1000000", NULL); - axiom_element_add_attribute(el, this->env, attr, request); - /* send newSession request */ - result = axis2_svc_client_send_receive(this->svc_client, this->env, request); - if (!result) + /* send newSession request and receive newSessionResult */ + if (!send_receive(this, "newSession", request, "newSessionResult", &result)) { return FALSE; } /* process newSessionResult */ node = axiom_node_get_first_child(result, this->env); - if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT) - { - el = (axiom_element_t *)axiom_node_get_data_element(node, this->env); - qname = axiom_element_get_qname(el, this->env, node); - success = streq("newSessionResult", - axutil_qname_to_string(qname, this->env)); - - /* process the attributes */ - if (success) - { - value = axiom_element_get_attribute_value_by_name(el, this->env, + el = (axiom_element_t *)axiom_node_get_data_element(node, this->env); + + /* get session-id */ + value = axiom_element_get_attribute_value_by_name(el, this->env, "session-id"); - this->session_id = strdup(value); - value = axiom_element_get_attribute_value_by_name(el, this->env, + this->session_id = strdup(value); + + /* get ifmap-publisher-id */ + value = axiom_element_get_attribute_value_by_name(el, this->env, "ifmap-publisher-id"); - this->ifmap_publisher_id = strdup(value); + this->ifmap_publisher_id = strdup(value); - DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s", - this->session_id, this->ifmap_publisher_id); - success = this->session_id && this->ifmap_publisher_id; + DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s", + this->session_id, this->ifmap_publisher_id); - value = axiom_element_get_attribute_value_by_name(el, this->env, - "max-poll-result-size"); - if (value) - { - DBG1(DBG_TNC, "max-poll-result-size: %s", value); - } + /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */ + this->device_name = lib->settings->get_str(lib->settings, + "charon.plugins.tnc-ifmap.device_name", + this->ifmap_publisher_id); + this->device_name = strdup(this->device_name); - /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */ - this->device_name = lib->settings->get_str(lib->settings, - "charon.plugins.tnc-ifmap.device_name", - this->ifmap_publisher_id); - this->device_name = strdup(this->device_name); - } - else - { - DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node)); - } - } + /* free result */ axiom_node_free_tree(result, this->env); - return success; + return this->session_id && this->ifmap_publisher_id; } METHOD(tnc_ifmap_soap_t, purgePublisher, bool, private_tnc_ifmap_soap_t *this) { - axiom_node_t *request, *result, *node; + axiom_node_t *request; axiom_element_t *el; axiom_namespace_t *ns; axiom_attribute_t *attr; - axutil_qname_t *qname; - bool success = FALSE; /* build purgePublisher request */ ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); - el = axiom_element_create(this->env, NULL, "purgePublisher", ns, - &request); + el = axiom_element_create(this->env, NULL, "purgePublisher", ns, &request); attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL); axiom_element_add_attribute(el, this->env, attr, request); @@ -157,88 +186,47 @@ METHOD(tnc_ifmap_soap_t, purgePublisher, bool, this->ifmap_publisher_id, NULL); axiom_element_add_attribute(el, this->env, attr, request); - /* send purgePublisher request */ - result = axis2_svc_client_send_receive(this->svc_client, this->env, request); - if (!result) - { - return FALSE; - } - - /* process purgePublisherReceived */ - node = axiom_node_get_first_child(result, this->env); - if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT) - { - el = (axiom_element_t *)axiom_node_get_data_element(node, this->env); - qname = axiom_element_get_qname(el, this->env, node); - success = streq("purgePublisherReceived", - axutil_qname_to_string(qname, this->env)); - if (!success) - { - DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node)); - } - } - axiom_node_free_tree(result, this->env); - - return success; + /* send purgePublisher request and receive purgePublisherReceived */ + return send_receive(this, "purgePublisher", request, + "purgePublisherReceived", NULL); } -METHOD(tnc_ifmap_soap_t, publish, bool, - private_tnc_ifmap_soap_t *this, u_int32_t ike_sa_id, identification_t *id, - host_t *host, bool up) +/** + * Create an access-request based on device_name and ike_sa_id + */ +static axiom_node_t* create_access_request(private_tnc_ifmap_soap_t *this, + u_int32_t id) { - axiom_node_t *request, *result, *node, *node2, *node3, *node4; axiom_element_t *el; - axiom_namespace_t *ns, *ns_meta; + axiom_node_t *node; axiom_attribute_t *attr; - axiom_text_t *text; - axutil_qname_t *qname; - char buf[BUF_LEN], *id_type; - bool success = FALSE; + char buf[BUF_LEN]; - /* build publish request */ - ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); - el = axiom_element_create(this->env, NULL, "publish", ns, &request); - ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); - axiom_element_declare_namespace(el, this->env, request, ns_meta); - attr = axiom_attribute_create(this->env, "session-id", this->session_id, - NULL); - axiom_element_add_attribute(el, this->env, attr, request); + el = axiom_element_create(this->env, NULL, "access-request", NULL, &node); - /** - * update or delete authenticated-as metadata - */ - if (up) - { - el = axiom_element_create(this->env, NULL, "update", NULL, &node); - axiom_node_add_child(request, this->env, node); - } - else - { - el = axiom_element_create(this->env, NULL, "delete", NULL, &node); - axiom_node_add_child(request, this->env, node); - - /* add filter */ - snprintf(buf, BUF_LEN, "meta:authenticated-as[@ifmap-publisher-id='%s']", - this->ifmap_publisher_id); - attr = axiom_attribute_create(this->env, "filter", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node); - } - - /* add access-request */ - el = axiom_element_create(this->env, NULL, "access-request", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - - snprintf(buf, BUF_LEN, "%s:%d", this->device_name, ike_sa_id); + snprintf(buf, BUF_LEN, "%s:%d", this->device_name, id); attr = axiom_attribute_create(this->env, "name", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node2); + axiom_element_add_attribute(el, this->env, attr, node); - /* add identity */ - el = axiom_element_create(this->env, NULL, "identity", NULL, &node2); - axiom_node_add_child(node, this->env, node2); + return node; +} + +/** + * Create an identity + */ +static axiom_node_t* create_identity(private_tnc_ifmap_soap_t *this, + identification_t *id) +{ + axiom_element_t *el; + axiom_node_t *node; + axiom_attribute_t *attr; + char buf[BUF_LEN], *id_type; + + el = axiom_element_create(this->env, NULL, "identity", NULL, &node); snprintf(buf, BUF_LEN, "%Y", id); attr = axiom_attribute_create(this->env, "name", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node2); + axiom_element_add_attribute(el, this->env, attr, node); switch (id->get_type(id)) { @@ -255,22 +243,136 @@ METHOD(tnc_ifmap_soap_t, publish, bool, id_type = "other"; } attr = axiom_attribute_create(this->env, "type", id_type, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + return node; +} + +/** + * Create an ip-address + */ +static axiom_node_t* create_ip_address(private_tnc_ifmap_soap_t *this, + host_t *host) +{ + axiom_element_t *el; + axiom_node_t *node; + axiom_attribute_t *attr; + char buf[BUF_LEN]; + + el = axiom_element_create(this->env, NULL, "ip-address", NULL, &node); + + snprintf(buf, BUF_LEN, "%H", host); + attr = axiom_attribute_create(this->env, "value", buf, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + attr = axiom_attribute_create(this->env, "type", + host->get_family(host) == AF_INET ? "IPv4" : "IPv6", NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + return node; +} + +/** + * Create a device + */ +static axiom_node_t* create_device(private_tnc_ifmap_soap_t *this) +{ + axiom_element_t *el; + axiom_node_t *node, *node2, *node3; + axiom_text_t *text; + + el = axiom_element_create(this->env, NULL, "device", NULL, &node); + el = axiom_element_create(this->env, NULL, "name", NULL, &node2); + axiom_node_add_child(node, this->env, node2); + text = axiom_text_create(this->env, node2, this->device_name, &node3); + + return node; +} + +/** + * Create metadata + */ +static axiom_node_t* create_metadata(private_tnc_ifmap_soap_t *this, + char *metadata) +{ + axiom_element_t *el; + axiom_node_t *node, *node2; + axiom_attribute_t *attr; + axiom_namespace_t *ns_meta; + + el = axiom_element_create(this->env, NULL, "metadata", NULL, &node); + ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); + + el = axiom_element_create(this->env, NULL, metadata, ns_meta, &node2); + axiom_node_add_child(node, this->env, node2); + attr = axiom_attribute_create(this->env, "ifmap-cardinality", "singleValue", + NULL); axiom_element_add_attribute(el, this->env, attr, node2); + return node; +} + +/** + * Create delete filter + */ +static axiom_node_t* create_delete_filter(private_tnc_ifmap_soap_t *this, + char *metadata) +{ + axiom_element_t *el; + axiom_node_t *node; + axiom_attribute_t *attr; + char buf[BUF_LEN]; + + el = axiom_element_create(this->env, NULL, "delete", NULL, &node); + + snprintf(buf, BUF_LEN, "meta:%s[@ifmap-publisher-id='%s']", + metadata, this->ifmap_publisher_id); + attr = axiom_attribute_create(this->env, "filter", buf, NULL); + axiom_element_add_attribute(el, this->env, attr, node); + + return node; +} + +METHOD(tnc_ifmap_soap_t, publish, bool, + private_tnc_ifmap_soap_t *this, u_int32_t ike_sa_id, identification_t *id, + host_t *host, bool up) +{ + axiom_node_t *request, *node; + axiom_element_t *el; + axiom_namespace_t *ns, *ns_meta; + axiom_attribute_t *attr; + + /* build publish request */ + ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); + el = axiom_element_create(this->env, NULL, "publish", ns, &request); + ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); + axiom_element_declare_namespace(el, this->env, request, ns_meta); + attr = axiom_attribute_create(this->env, "session-id", this->session_id, + NULL); + axiom_element_add_attribute(el, this->env, attr, request); + + /** + * update or delete authenticated-as metadata + */ + if (up) + { + el = axiom_element_create(this->env, NULL, "update", NULL, &node); + } + else + { + node = create_delete_filter(this, "authenticated-as"); + } + axiom_node_add_child(request, this->env, node); + + /* add access-request, identity and [if up] metadata */ + axiom_node_add_child(node, this->env, + create_access_request(this, ike_sa_id)); + axiom_node_add_child(node, this->env, + create_identity(this, id)); if (up) { - /* add metadata */ - el = axiom_element_create(this->env, NULL, "metadata", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - - ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); - - el = axiom_element_create(this->env, NULL, "authenticated-as", ns_meta, - &node3); - axiom_node_add_child(node2, this->env, node3); - attr = axiom_attribute_create(this->env, "ifmap-cardinality", - "singleValue", NULL); - axiom_element_add_attribute(el, this->env, attr, node3); + axiom_node_add_child(node, this->env, + create_metadata(this, "authenticated-as")); } /** @@ -279,52 +381,22 @@ METHOD(tnc_ifmap_soap_t, publish, bool, if (up) { el = axiom_element_create(this->env, NULL, "update", NULL, &node); - axiom_node_add_child(request, this->env, node); } else { - el = axiom_element_create(this->env, NULL, "delete", NULL, &node); - axiom_node_add_child(request, this->env, node); - - /* add filter */ - snprintf(buf, BUF_LEN, "meta:access-request-ip[@ifmap-publisher-id='%s']", - this->ifmap_publisher_id); - attr = axiom_attribute_create(this->env, "filter", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node); + node = create_delete_filter(this, "access-request-ip"); } + axiom_node_add_child(request, this->env, node); - /* add access-request */ - el = axiom_element_create(this->env, NULL, "access-request", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - - snprintf(buf, BUF_LEN, "%s:%d", this->device_name, ike_sa_id); - attr = axiom_attribute_create(this->env, "name", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node2); - - /* add ip-address */ - el = axiom_element_create(this->env, NULL, "ip-address", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - - snprintf(buf, BUF_LEN, "%H", host); - attr = axiom_attribute_create(this->env, "value", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node2); - - attr = axiom_attribute_create(this->env, "type", - host->get_family(host) == AF_INET ? "IPv4" : "IPv6", NULL); - axiom_element_add_attribute(el, this->env, attr, node2); - + /* add access-request, ip-address and [if up] metadata */ + axiom_node_add_child(node, this->env, + create_access_request(this, ike_sa_id)); + axiom_node_add_child(node, this->env, + create_ip_address(this, host)); if (up) { - /* add metadata */ - el = axiom_element_create(this->env, NULL, "metadata", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); - el = axiom_element_create(this->env, NULL, "access-request-ip", ns_meta, - &node3); - axiom_node_add_child(node2, this->env, node3); - attr = axiom_attribute_create(this->env, "ifmap-cardinality", - "singleValue", NULL); - axiom_element_add_attribute(el, this->env, attr, node3); + axiom_node_add_child(node, this->env, + create_metadata(this, "access-request-ip")); } /** @@ -333,83 +405,35 @@ METHOD(tnc_ifmap_soap_t, publish, bool, if (up) { el = axiom_element_create(this->env, NULL, "update", NULL, &node); - axiom_node_add_child(request, this->env, node); } else { - el = axiom_element_create(this->env, NULL, "delete", NULL, &node); - axiom_node_add_child(request, this->env, node); - - /* add filter */ - snprintf(buf, BUF_LEN, "meta:authenticated-by[@ifmap-publisher-id='%s']", - this->ifmap_publisher_id); - attr = axiom_attribute_create(this->env, "filter", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node); + node = create_delete_filter(this, "authenticated-by"); } + axiom_node_add_child(request, this->env, node); - /* add access-request */ - el = axiom_element_create(this->env, NULL, "access-request", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - - snprintf(buf, BUF_LEN, "%s:%d", this->device_name, ike_sa_id); - attr = axiom_attribute_create(this->env, "name", buf, NULL); - axiom_element_add_attribute(el, this->env, attr, node2); - - /* add device */ - el = axiom_element_create(this->env, NULL, "device", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - el = axiom_element_create(this->env, NULL, "name", NULL, &node3); - axiom_node_add_child(node2, this->env, node3); - text = axiom_text_create(this->env, node3, this->device_name, &node4); - + /* add access-request, device and [if up] metadata */ + axiom_node_add_child(node, this->env, + create_access_request(this, ike_sa_id)); + axiom_node_add_child(node, this->env, + create_device(this)); if (up) { - /* add metadata */ - el = axiom_element_create(this->env, NULL, "metadata", NULL, &node2); - axiom_node_add_child(node, this->env, node2); - ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta"); - el = axiom_element_create(this->env, NULL, "authenticated-by", ns_meta, - &node3); - axiom_node_add_child(node2, this->env, node3); - attr = axiom_attribute_create(this->env, "ifmap-cardinality", - "singleValue", NULL); - axiom_element_add_attribute(el, this->env, attr, node3); + axiom_node_add_child(node, this->env, + create_metadata(this, "authenticated-by")); } - /* send publish request */ - result = axis2_svc_client_send_receive(this->svc_client, this->env, request); - if (!result) - { - return FALSE; - } - - /* process publishReceived */ - node = axiom_node_get_first_child(result, this->env); - if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT) - { - el = (axiom_element_t *)axiom_node_get_data_element(node, this->env); - qname = axiom_element_get_qname(el, this->env, node); - success = streq("publishReceived", - axutil_qname_to_string(qname, this->env)); - if (!success) - { - DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node)); - } - } - axiom_node_free_tree(result, this->env); - - return TRUE; + /* send publish request and receive publishReceived */ + return send_receive(this, "publish", request, "publishReceived", NULL); } METHOD(tnc_ifmap_soap_t, endSession, bool, private_tnc_ifmap_soap_t *this) { - axiom_node_t *request, *result, *node; + axiom_node_t *request; axiom_element_t *el; axiom_namespace_t *ns; axiom_attribute_t *attr; - axutil_qname_t *qname; - bool success = FALSE; /* build endSession request */ ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap"); @@ -417,31 +441,8 @@ METHOD(tnc_ifmap_soap_t, endSession, bool, attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL); axiom_element_add_attribute(el, this->env, attr, request); - /* send endSession request */ - result = axis2_svc_client_send_receive(this->svc_client, this->env, request); - if (!result) - { - return FALSE; - } - - /* process endSessionResult */ - node = axiom_node_get_first_child(result, this->env); - if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT) - { - el = (axiom_element_t *)axiom_node_get_data_element(node, this->env); - qname = axiom_element_get_qname(el, this->env, node); - success = streq("endSessionResult", - axutil_qname_to_string(qname, this->env)); - if (!success) - { - DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node)); - } - } - axiom_node_free_tree(result, this->env); - - return success; - - return TRUE; + /* send endSession request and receive end SessionResult */ + return send_receive(this, "endSession", request, "endSessionResult", NULL); } METHOD(tnc_ifmap_soap_t, destroy, void, @@ -449,11 +450,7 @@ METHOD(tnc_ifmap_soap_t, destroy, void, { if (this->session_id) { - DBG2(DBG_TNC, "sending ifmap->endSession"); - if (!endSession(this)) - { - DBG1(DBG_TNC, "ifmap->endSession with MAP server failed"); - } + endSession(this); free(this->session_id); free(this->ifmap_publisher_id); free(this->device_name);