2 * Copyright (C) 2011 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "tnc_ifmap_listener.h"
19 #include <config/child_cfg.h>
21 #include <axis2_util.h>
22 #include <axis2_client.h>
23 #include <axiom_soap.h>
25 #define IFMAP_NS "http://www.trustedcomputinggroup.org/2010/IFMAP/2"
26 #define IFMAP_META_NS "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2"
27 #define IFMAP_LOGFILE "strongswan_ifmap.log"
28 #define IFMAP_SERVER "https://localhost:8443/"
30 typedef struct private_tnc_ifmap_listener_t private_tnc_ifmap_listener_t
;
33 * Private data of an tnc_ifmap_listener_t object.
35 struct private_tnc_ifmap_listener_t
{
38 * Public tnc_ifmap_listener_t interface.
40 tnc_ifmap_listener_t
public;
48 * Axis2 service client
50 axis2_svc_client_t
* svc_client
;
60 char *ifmap_publisher_id
;
64 static bool newSession(private_tnc_ifmap_listener_t
*this)
66 axiom_node_t
*request
, *result
, *node
;
68 axiom_namespace_t
*ns
;
69 axiom_attribute_t
*attr
;
71 axutil_qname_t
*qname
;
75 /* build newSession request */
76 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
77 el
= axiom_element_create(this->env
, NULL
, "newSession", ns
, &request
);
78 attr
= axiom_attribute_create(this->env
, "max-poll-result-size", "1000000", NULL
);
79 axiom_element_add_attribute(el
, this->env
, attr
, request
);
81 /* send newSession request */
82 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
88 /* process newSessionResult */
89 node
= axiom_node_get_first_child(result
, this->env
);
90 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
92 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
93 qname
= axiom_element_get_qname(el
, this->env
, node
);
94 success
= streq("newSessionResult",
95 axutil_qname_to_string(qname
, this->env
));
97 /* process the attributes */
100 value
= axiom_element_get_attribute_value_by_name(el
, this->env
,
102 this->session_id
= strdup(value
);
103 value
= axiom_element_get_attribute_value_by_name(el
, this->env
,
104 "ifmap-publisher-id");
105 this->ifmap_publisher_id
= strdup(value
);
107 DBG1(DBG_TNC
, "session-id: %s, ifmap-publisher-id: %s",
108 this->session_id
, this->ifmap_publisher_id
);
109 success
= this->session_id
&& this->ifmap_publisher_id
;
111 value
= axiom_element_get_attribute_value_by_name(el
, this->env
,
112 "max-poll-result-size");
115 DBG1(DBG_TNC
, "max-poll-result-size: %s", value
);
120 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
123 axiom_node_free_tree(result
, this->env
);
128 static bool purgePublisher(private_tnc_ifmap_listener_t
*this)
130 axiom_node_t
*request
, *result
, *node
;
132 axiom_namespace_t
*ns
;
133 axiom_attribute_t
*attr
;
134 axutil_qname_t
*qname
;
135 bool success
= FALSE
;
137 /* build purgePublisher request */
138 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
139 el
= axiom_element_create(this->env
, NULL
, "purgePublisher", ns
,
141 attr
= axiom_attribute_create(this->env
, "session-id",
142 this->session_id
, NULL
);
143 axiom_element_add_attribute(el
, this->env
, attr
, request
);
144 attr
= axiom_attribute_create(this->env
, "ifmap-publisher-id",
145 this->ifmap_publisher_id
, NULL
);
146 axiom_element_add_attribute(el
, this->env
, attr
, request
);
148 /* send purgePublisher request */
149 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
155 /* process purgePublisherReceived */
156 node
= axiom_node_get_first_child(result
, this->env
);
157 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
159 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
160 qname
= axiom_element_get_qname(el
, this->env
, node
);
161 success
= streq("purgePublisherReceived",
162 axutil_qname_to_string(qname
, this->env
));
165 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
168 axiom_node_free_tree(result
, this->env
);
173 static bool publish(private_tnc_ifmap_listener_t
*this, u_int32_t ike_sa_id
,
174 identification_t
*id
, host_t
*host
, bool up
)
176 axiom_node_t
*request
, *result
, *node
, *node2
, *node3
, *node4
;
178 axiom_namespace_t
*ns
, *ns_meta
;
179 axiom_attribute_t
*attr
;
181 axutil_qname_t
*qname
;
182 char buf
[BUF_LEN
], *id_type
;
183 bool success
= FALSE
;
185 /* build publish request */
186 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
187 el
= axiom_element_create(this->env
, NULL
, "publish", ns
, &request
);
188 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
189 axiom_element_declare_namespace(el
, this->env
, request
, ns_meta
);
190 attr
= axiom_attribute_create(this->env
, "session-id", this->session_id
,
192 axiom_element_add_attribute(el
, this->env
, attr
, request
);
195 * update or delete authenticated-as metadata
199 el
= axiom_element_create(this->env
, NULL
, "update", NULL
, &node
);
200 axiom_node_add_child(request
, this->env
, node
);
204 el
= axiom_element_create(this->env
, NULL
, "delete", NULL
, &node
);
205 axiom_node_add_child(request
, this->env
, node
);
208 snprintf(buf
, BUF_LEN
, "meta:authenticated-as[@ifmap-publisher-id='%s']",
209 this->ifmap_publisher_id
);
210 attr
= axiom_attribute_create(this->env
, "filter", buf
, NULL
);
211 axiom_element_add_attribute(el
, this->env
, attr
, node
);
214 /* add access-request */
215 el
= axiom_element_create(this->env
, NULL
, "access-request", NULL
, &node2
);
216 axiom_node_add_child(node
, this->env
, node2
);
218 snprintf(buf
, BUF_LEN
, "%s:%d", this->ifmap_publisher_id
, ike_sa_id
);
219 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
220 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
223 el
= axiom_element_create(this->env
, NULL
, "identity", NULL
, &node2
);
224 axiom_node_add_child(node
, this->env
, node2
);
226 snprintf(buf
, BUF_LEN
, "%Y", id
);
227 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
228 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
230 switch (id
->get_type(id
))
233 id_type
= "dns-name";
236 id_type
= "email-address";
239 id_type
= "distinguished-name";
244 attr
= axiom_attribute_create(this->env
, "type", id_type
, NULL
);
245 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
250 el
= axiom_element_create(this->env
, NULL
, "metadata", NULL
, &node2
);
251 axiom_node_add_child(node
, this->env
, node2
);
253 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
255 el
= axiom_element_create(this->env
, NULL
, "authenticated-as", ns_meta
,
257 axiom_node_add_child(node2
, this->env
, node3
);
258 attr
= axiom_attribute_create(this->env
, "ifmap-cardinality",
259 "singleValue", NULL
);
260 axiom_element_add_attribute(el
, this->env
, attr
, node3
);
264 * update or delete access-request-ip metadata
268 el
= axiom_element_create(this->env
, NULL
, "update", NULL
, &node
);
269 axiom_node_add_child(request
, this->env
, node
);
273 el
= axiom_element_create(this->env
, NULL
, "delete", NULL
, &node
);
274 axiom_node_add_child(request
, this->env
, node
);
277 snprintf(buf
, BUF_LEN
, "meta:access-request-ip[@ifmap-publisher-id='%s']",
278 this->ifmap_publisher_id
);
279 attr
= axiom_attribute_create(this->env
, "filter", buf
, NULL
);
280 axiom_element_add_attribute(el
, this->env
, attr
, node
);
283 /* add access-request */
284 el
= axiom_element_create(this->env
, NULL
, "access-request", NULL
, &node2
);
285 axiom_node_add_child(node
, this->env
, node2
);
287 snprintf(buf
, BUF_LEN
, "%s:%d", this->ifmap_publisher_id
, ike_sa_id
);
288 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
289 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
292 el
= axiom_element_create(this->env
, NULL
, "ip-address", NULL
, &node2
);
293 axiom_node_add_child(node
, this->env
, node2
);
295 snprintf(buf
, BUF_LEN
, "%H", host
);
296 attr
= axiom_attribute_create(this->env
, "value", buf
, NULL
);
297 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
299 attr
= axiom_attribute_create(this->env
, "type",
300 host
->get_family(host
) == AF_INET ?
"IPv4" : "IPv6", NULL
);
301 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
306 el
= axiom_element_create(this->env
, NULL
, "metadata", NULL
, &node2
);
307 axiom_node_add_child(node
, this->env
, node2
);
308 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
309 el
= axiom_element_create(this->env
, NULL
, "access-request-ip", ns_meta
,
311 axiom_node_add_child(node2
, this->env
, node3
);
312 attr
= axiom_attribute_create(this->env
, "ifmap-cardinality",
313 "singleValue", NULL
);
314 axiom_element_add_attribute(el
, this->env
, attr
, node3
);
318 * update or delete authenticated-by metadata
322 el
= axiom_element_create(this->env
, NULL
, "update", NULL
, &node
);
323 axiom_node_add_child(request
, this->env
, node
);
327 el
= axiom_element_create(this->env
, NULL
, "delete", NULL
, &node
);
328 axiom_node_add_child(request
, this->env
, node
);
331 snprintf(buf
, BUF_LEN
, "meta:authenticated-by[@ifmap-publisher-id='%s']",
332 this->ifmap_publisher_id
);
333 attr
= axiom_attribute_create(this->env
, "filter", buf
, NULL
);
334 axiom_element_add_attribute(el
, this->env
, attr
, node
);
337 /* add access-request */
338 el
= axiom_element_create(this->env
, NULL
, "access-request", NULL
, &node2
);
339 axiom_node_add_child(node
, this->env
, node2
);
341 snprintf(buf
, BUF_LEN
, "%s:%d", this->ifmap_publisher_id
, ike_sa_id
);
342 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
343 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
346 el
= axiom_element_create(this->env
, NULL
, "device", NULL
, &node2
);
347 axiom_node_add_child(node
, this->env
, node2
);
348 el
= axiom_element_create(this->env
, NULL
, "name", NULL
, &node3
);
349 axiom_node_add_child(node2
, this->env
, node3
);
350 text
= axiom_text_create(this->env
, node3
, this->ifmap_publisher_id
, &node4
);
355 el
= axiom_element_create(this->env
, NULL
, "metadata", NULL
, &node2
);
356 axiom_node_add_child(node
, this->env
, node2
);
357 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
358 el
= axiom_element_create(this->env
, NULL
, "authenticated-by", ns_meta
,
360 axiom_node_add_child(node2
, this->env
, node3
);
361 attr
= axiom_attribute_create(this->env
, "ifmap-cardinality",
362 "singleValue", NULL
);
363 axiom_element_add_attribute(el
, this->env
, attr
, node3
);
366 /* send publish request */
367 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
373 /* process publishReceived */
374 node
= axiom_node_get_first_child(result
, this->env
);
375 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
377 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
378 qname
= axiom_element_get_qname(el
, this->env
, node
);
379 success
= streq("publishReceived",
380 axutil_qname_to_string(qname
, this->env
));
383 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
386 axiom_node_free_tree(result
, this->env
);
391 static bool endSession(private_tnc_ifmap_listener_t
*this)
393 axiom_node_t
*request
, *result
, *node
;
395 axiom_namespace_t
*ns
;
396 axiom_attribute_t
*attr
;
397 axutil_qname_t
*qname
;
398 bool success
= FALSE
;
400 /* build endSession request */
401 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
402 el
= axiom_element_create(this->env
, NULL
, "endSession", ns
, &request
);
403 attr
= axiom_attribute_create(this->env
, "session-id", this->session_id
, NULL
);
404 axiom_element_add_attribute(el
, this->env
, attr
, request
);
406 /* send endSession request */
407 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
413 /* process endSessionResult */
414 node
= axiom_node_get_first_child(result
, this->env
);
415 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
417 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
418 qname
= axiom_element_get_qname(el
, this->env
, node
);
419 success
= streq("endSessionResult",
420 axutil_qname_to_string(qname
, this->env
));
423 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
426 axiom_node_free_tree(result
, this->env
);
433 METHOD(listener_t
, ike_updown
, bool,
434 private_tnc_ifmap_listener_t
*this, ike_sa_t
*ike_sa
, bool up
)
437 identification_t
*id
;
440 ike_sa_id
= ike_sa
->get_unique_id(ike_sa
);
441 id
= ike_sa
->get_other_id(ike_sa
);
442 host
= ike_sa
->get_other_host(ike_sa
);
444 DBG2(DBG_TNC
, "sending publish");
445 if (!publish(this, ike_sa_id
, id
, host
, up
))
447 DBG1(DBG_TNC
, "publish with MAP server failed");
453 METHOD(tnc_ifmap_listener_t
, destroy
, void,
454 private_tnc_ifmap_listener_t
*this)
456 if (this->session_id
)
458 DBG2(DBG_TNC
, "sending endSession");
459 if (!endSession(this))
461 DBG1(DBG_TNC
, "endSession with MAP server failed");
463 free(this->session_id
);
464 free(this->ifmap_publisher_id
);
466 if (this->svc_client
)
468 axis2_svc_client_free(this->svc_client
, this->env
);
472 axutil_env_free(this->env
);
480 tnc_ifmap_listener_t
*tnc_ifmap_listener_create()
482 private_tnc_ifmap_listener_t
*this;
483 axis2_char_t
*server
, *client_home
, *username
, *password
, *auth_type
;
484 axis2_endpoint_ref_t
* endpoint_ref
= NULL
;
485 axis2_options_t
*options
= NULL
;
487 client_home
= lib
->settings
->get_str(lib
->settings
,
488 "charon.plugins.tnc-ifmap.client_home",
489 AXIS2_GETENV("AXIS2C_HOME"));
490 server
= lib
->settings
->get_str(lib
->settings
,
491 "charon.plugins.tnc-ifmap.server", IFMAP_SERVER
);
492 auth_type
= lib
->settings
->get_str(lib
->settings
,
493 "charon.plugins.tnc-ifmap.auth_type", "Basic");
494 username
= lib
->settings
->get_str(lib
->settings
,
495 "charon.plugins.tnc-ifmap.username", NULL
);
496 password
= lib
->settings
->get_str(lib
->settings
,
497 "charon.plugins.tnc-ifmap.password", NULL
);
499 if (!username
|| !password
)
501 DBG1(DBG_TNC
, "MAP client %s%s%s not defined",
502 (!username
) ?
"username" : "",
503 (!username
&& ! password
) ?
" and " : "",
504 (!password
) ?
"password" : "");
510 .ike_updown
= _ike_updown
,
516 /* Create Axis2/C environment and options */
517 this->env
= axutil_env_create_all(IFMAP_LOGFILE
, AXIS2_LOG_LEVEL_TRACE
);
518 options
= axis2_options_create(this->env
);
520 /* Define the IF-MAP server as the to endpoint reference */
521 endpoint_ref
= axis2_endpoint_ref_create(this->env
, server
);
522 axis2_options_set_to(options
, this->env
, endpoint_ref
);
524 /* Create the axis2 service client */
525 this->svc_client
= axis2_svc_client_create(this->env
, client_home
);
526 if (!this->svc_client
)
528 DBG1(DBG_TNC
, "Error creating axis2 service client");
529 AXIS2_LOG_ERROR(this->env
->log
, AXIS2_LOG_SI
,
530 "Stub invoke FAILED: Error code: %d :: %s",
531 this->env
->error
->error_number
,
532 AXIS2_ERROR_GET_MESSAGE(this->env
->error
));
537 axis2_svc_client_set_options(this->svc_client
, this->env
, options
);
538 axis2_options_set_http_auth_info(options
, this->env
, username
, password
,
540 DBG1(DBG_TNC
, "connecting as MAP client '%s' to MAP server at '%s'",
543 DBG2(DBG_TNC
, "sending newSession");
544 if (!newSession(this))
546 DBG1(DBG_TNC
, "newSession with MAP server failed");
550 DBG2(DBG_TNC
, "sending purgePublisher");
551 if (!purgePublisher(this))
553 DBG1(DBG_TNC
, "purgePublisher with MAP server failed");
558 return &this->public;