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_soap.h"
20 #include <axis2_util.h>
21 #include <axis2_client.h>
22 #include <axiom_soap.h>
24 #define IFMAP_NS "http://www.trustedcomputinggroup.org/2010/IFMAP/2"
25 #define IFMAP_META_NS "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2"
26 #define IFMAP_LOGFILE "strongswan_ifmap.log"
27 #define IFMAP_SERVER "https://localhost:8443/"
29 typedef struct private_tnc_ifmap_soap_t private_tnc_ifmap_soap_t
;
32 * Private data of an tnc_ifmap_soap_t object.
34 struct private_tnc_ifmap_soap_t
{
37 * Public tnc_ifmap_soap_t interface.
39 tnc_ifmap_soap_t
public;
47 * Axis2 service client
49 axis2_svc_client_t
* svc_client
;
59 char *ifmap_publisher_id
;
62 * PEP and PDP device name
68 METHOD(tnc_ifmap_soap_t
, newSession
, bool,
69 private_tnc_ifmap_soap_t
*this)
71 axiom_node_t
*request
, *result
, *node
;
73 axiom_namespace_t
*ns
;
74 axiom_attribute_t
*attr
;
76 axutil_qname_t
*qname
;
80 /* build newSession request */
81 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
82 el
= axiom_element_create(this->env
, NULL
, "newSession", ns
, &request
);
83 attr
= axiom_attribute_create(this->env
, "max-poll-result-size", "1000000", NULL
);
84 axiom_element_add_attribute(el
, this->env
, attr
, request
);
86 /* send newSession request */
87 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
93 /* process newSessionResult */
94 node
= axiom_node_get_first_child(result
, this->env
);
95 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
97 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
98 qname
= axiom_element_get_qname(el
, this->env
, node
);
99 success
= streq("newSessionResult",
100 axutil_qname_to_string(qname
, this->env
));
102 /* process the attributes */
105 value
= axiom_element_get_attribute_value_by_name(el
, this->env
,
107 this->session_id
= strdup(value
);
108 value
= axiom_element_get_attribute_value_by_name(el
, this->env
,
109 "ifmap-publisher-id");
110 this->ifmap_publisher_id
= strdup(value
);
112 DBG1(DBG_TNC
, "session-id: %s, ifmap-publisher-id: %s",
113 this->session_id
, this->ifmap_publisher_id
);
114 success
= this->session_id
&& this->ifmap_publisher_id
;
116 value
= axiom_element_get_attribute_value_by_name(el
, this->env
,
117 "max-poll-result-size");
120 DBG1(DBG_TNC
, "max-poll-result-size: %s", value
);
123 /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
124 this->device_name
= lib
->settings
->get_str(lib
->settings
,
125 "charon.plugins.tnc-ifmap.device_name",
126 this->ifmap_publisher_id
);
127 this->device_name
= strdup(this->device_name
);
131 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
134 axiom_node_free_tree(result
, this->env
);
139 METHOD(tnc_ifmap_soap_t
, purgePublisher
, bool,
140 private_tnc_ifmap_soap_t
*this)
142 axiom_node_t
*request
, *result
, *node
;
144 axiom_namespace_t
*ns
;
145 axiom_attribute_t
*attr
;
146 axutil_qname_t
*qname
;
147 bool success
= FALSE
;
149 /* build purgePublisher request */
150 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
151 el
= axiom_element_create(this->env
, NULL
, "purgePublisher", ns
,
153 attr
= axiom_attribute_create(this->env
, "session-id",
154 this->session_id
, NULL
);
155 axiom_element_add_attribute(el
, this->env
, attr
, request
);
156 attr
= axiom_attribute_create(this->env
, "ifmap-publisher-id",
157 this->ifmap_publisher_id
, NULL
);
158 axiom_element_add_attribute(el
, this->env
, attr
, request
);
160 /* send purgePublisher request */
161 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
167 /* process purgePublisherReceived */
168 node
= axiom_node_get_first_child(result
, this->env
);
169 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
171 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
172 qname
= axiom_element_get_qname(el
, this->env
, node
);
173 success
= streq("purgePublisherReceived",
174 axutil_qname_to_string(qname
, this->env
));
177 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
180 axiom_node_free_tree(result
, this->env
);
185 METHOD(tnc_ifmap_soap_t
, publish
, bool,
186 private_tnc_ifmap_soap_t
*this, u_int32_t ike_sa_id
, identification_t
*id
,
187 host_t
*host
, bool up
)
189 axiom_node_t
*request
, *result
, *node
, *node2
, *node3
, *node4
;
191 axiom_namespace_t
*ns
, *ns_meta
;
192 axiom_attribute_t
*attr
;
194 axutil_qname_t
*qname
;
195 char buf
[BUF_LEN
], *id_type
;
196 bool success
= FALSE
;
198 /* build publish request */
199 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
200 el
= axiom_element_create(this->env
, NULL
, "publish", ns
, &request
);
201 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
202 axiom_element_declare_namespace(el
, this->env
, request
, ns_meta
);
203 attr
= axiom_attribute_create(this->env
, "session-id", this->session_id
,
205 axiom_element_add_attribute(el
, this->env
, attr
, request
);
208 * update or delete authenticated-as metadata
212 el
= axiom_element_create(this->env
, NULL
, "update", NULL
, &node
);
213 axiom_node_add_child(request
, this->env
, node
);
217 el
= axiom_element_create(this->env
, NULL
, "delete", NULL
, &node
);
218 axiom_node_add_child(request
, this->env
, node
);
221 snprintf(buf
, BUF_LEN
, "meta:authenticated-as[@ifmap-publisher-id='%s']",
222 this->ifmap_publisher_id
);
223 attr
= axiom_attribute_create(this->env
, "filter", buf
, NULL
);
224 axiom_element_add_attribute(el
, this->env
, attr
, node
);
227 /* add access-request */
228 el
= axiom_element_create(this->env
, NULL
, "access-request", NULL
, &node2
);
229 axiom_node_add_child(node
, this->env
, node2
);
231 snprintf(buf
, BUF_LEN
, "%s:%d", this->device_name
, ike_sa_id
);
232 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
233 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
236 el
= axiom_element_create(this->env
, NULL
, "identity", NULL
, &node2
);
237 axiom_node_add_child(node
, this->env
, node2
);
239 snprintf(buf
, BUF_LEN
, "%Y", id
);
240 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
241 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
243 switch (id
->get_type(id
))
246 id_type
= "dns-name";
249 id_type
= "email-address";
252 id_type
= "distinguished-name";
257 attr
= axiom_attribute_create(this->env
, "type", id_type
, NULL
);
258 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
263 el
= axiom_element_create(this->env
, NULL
, "metadata", NULL
, &node2
);
264 axiom_node_add_child(node
, this->env
, node2
);
266 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
268 el
= axiom_element_create(this->env
, NULL
, "authenticated-as", ns_meta
,
270 axiom_node_add_child(node2
, this->env
, node3
);
271 attr
= axiom_attribute_create(this->env
, "ifmap-cardinality",
272 "singleValue", NULL
);
273 axiom_element_add_attribute(el
, this->env
, attr
, node3
);
277 * update or delete access-request-ip metadata
281 el
= axiom_element_create(this->env
, NULL
, "update", NULL
, &node
);
282 axiom_node_add_child(request
, this->env
, node
);
286 el
= axiom_element_create(this->env
, NULL
, "delete", NULL
, &node
);
287 axiom_node_add_child(request
, this->env
, node
);
290 snprintf(buf
, BUF_LEN
, "meta:access-request-ip[@ifmap-publisher-id='%s']",
291 this->ifmap_publisher_id
);
292 attr
= axiom_attribute_create(this->env
, "filter", buf
, NULL
);
293 axiom_element_add_attribute(el
, this->env
, attr
, node
);
296 /* add access-request */
297 el
= axiom_element_create(this->env
, NULL
, "access-request", NULL
, &node2
);
298 axiom_node_add_child(node
, this->env
, node2
);
300 snprintf(buf
, BUF_LEN
, "%s:%d", this->device_name
, ike_sa_id
);
301 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
302 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
305 el
= axiom_element_create(this->env
, NULL
, "ip-address", NULL
, &node2
);
306 axiom_node_add_child(node
, this->env
, node2
);
308 snprintf(buf
, BUF_LEN
, "%H", host
);
309 attr
= axiom_attribute_create(this->env
, "value", buf
, NULL
);
310 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
312 attr
= axiom_attribute_create(this->env
, "type",
313 host
->get_family(host
) == AF_INET ?
"IPv4" : "IPv6", NULL
);
314 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
319 el
= axiom_element_create(this->env
, NULL
, "metadata", NULL
, &node2
);
320 axiom_node_add_child(node
, this->env
, node2
);
321 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
322 el
= axiom_element_create(this->env
, NULL
, "access-request-ip", ns_meta
,
324 axiom_node_add_child(node2
, this->env
, node3
);
325 attr
= axiom_attribute_create(this->env
, "ifmap-cardinality",
326 "singleValue", NULL
);
327 axiom_element_add_attribute(el
, this->env
, attr
, node3
);
331 * update or delete authenticated-by metadata
335 el
= axiom_element_create(this->env
, NULL
, "update", NULL
, &node
);
336 axiom_node_add_child(request
, this->env
, node
);
340 el
= axiom_element_create(this->env
, NULL
, "delete", NULL
, &node
);
341 axiom_node_add_child(request
, this->env
, node
);
344 snprintf(buf
, BUF_LEN
, "meta:authenticated-by[@ifmap-publisher-id='%s']",
345 this->ifmap_publisher_id
);
346 attr
= axiom_attribute_create(this->env
, "filter", buf
, NULL
);
347 axiom_element_add_attribute(el
, this->env
, attr
, node
);
350 /* add access-request */
351 el
= axiom_element_create(this->env
, NULL
, "access-request", NULL
, &node2
);
352 axiom_node_add_child(node
, this->env
, node2
);
354 snprintf(buf
, BUF_LEN
, "%s:%d", this->device_name
, ike_sa_id
);
355 attr
= axiom_attribute_create(this->env
, "name", buf
, NULL
);
356 axiom_element_add_attribute(el
, this->env
, attr
, node2
);
359 el
= axiom_element_create(this->env
, NULL
, "device", NULL
, &node2
);
360 axiom_node_add_child(node
, this->env
, node2
);
361 el
= axiom_element_create(this->env
, NULL
, "name", NULL
, &node3
);
362 axiom_node_add_child(node2
, this->env
, node3
);
363 text
= axiom_text_create(this->env
, node3
, this->device_name
, &node4
);
368 el
= axiom_element_create(this->env
, NULL
, "metadata", NULL
, &node2
);
369 axiom_node_add_child(node
, this->env
, node2
);
370 ns_meta
= axiom_namespace_create(this->env
, IFMAP_META_NS
, "meta");
371 el
= axiom_element_create(this->env
, NULL
, "authenticated-by", ns_meta
,
373 axiom_node_add_child(node2
, this->env
, node3
);
374 attr
= axiom_attribute_create(this->env
, "ifmap-cardinality",
375 "singleValue", NULL
);
376 axiom_element_add_attribute(el
, this->env
, attr
, node3
);
379 /* send publish request */
380 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
386 /* process publishReceived */
387 node
= axiom_node_get_first_child(result
, this->env
);
388 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
390 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
391 qname
= axiom_element_get_qname(el
, this->env
, node
);
392 success
= streq("publishReceived",
393 axutil_qname_to_string(qname
, this->env
));
396 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
399 axiom_node_free_tree(result
, this->env
);
404 METHOD(tnc_ifmap_soap_t
, endSession
, bool,
405 private_tnc_ifmap_soap_t
*this)
407 axiom_node_t
*request
, *result
, *node
;
409 axiom_namespace_t
*ns
;
410 axiom_attribute_t
*attr
;
411 axutil_qname_t
*qname
;
412 bool success
= FALSE
;
414 /* build endSession request */
415 ns
= axiom_namespace_create(this->env
, IFMAP_NS
, "ifmap");
416 el
= axiom_element_create(this->env
, NULL
, "endSession", ns
, &request
);
417 attr
= axiom_attribute_create(this->env
, "session-id", this->session_id
, NULL
);
418 axiom_element_add_attribute(el
, this->env
, attr
, request
);
420 /* send endSession request */
421 result
= axis2_svc_client_send_receive(this->svc_client
, this->env
, request
);
427 /* process endSessionResult */
428 node
= axiom_node_get_first_child(result
, this->env
);
429 if (node
&& axiom_node_get_node_type(node
, this->env
) == AXIOM_ELEMENT
)
431 el
= (axiom_element_t
*)axiom_node_get_data_element(node
, this->env
);
432 qname
= axiom_element_get_qname(el
, this->env
, node
);
433 success
= streq("endSessionResult",
434 axutil_qname_to_string(qname
, this->env
));
437 DBG1(DBG_TNC
, "%s", axiom_element_to_string(el
, this->env
, node
));
440 axiom_node_free_tree(result
, this->env
);
447 METHOD(tnc_ifmap_soap_t
, destroy
, void,
448 private_tnc_ifmap_soap_t
*this)
450 if (this->session_id
)
452 DBG2(DBG_TNC
, "sending ifmap->endSession");
453 if (!endSession(this))
455 DBG1(DBG_TNC
, "ifmap->endSession with MAP server failed");
457 free(this->session_id
);
458 free(this->ifmap_publisher_id
);
459 free(this->device_name
);
461 if (this->svc_client
)
463 axis2_svc_client_free(this->svc_client
, this->env
);
467 axutil_env_free(this->env
);
475 tnc_ifmap_soap_t
*tnc_ifmap_soap_create()
477 private_tnc_ifmap_soap_t
*this;
478 axis2_char_t
*server
, *client_home
, *username
, *password
, *auth_type
;
479 axis2_endpoint_ref_t
* endpoint_ref
= NULL
;
480 axis2_options_t
*options
= NULL
;
482 client_home
= lib
->settings
->get_str(lib
->settings
,
483 "charon.plugins.tnc-ifmap.client_home",
484 AXIS2_GETENV("AXIS2C_HOME"));
485 server
= lib
->settings
->get_str(lib
->settings
,
486 "charon.plugins.tnc-ifmap.server", IFMAP_SERVER
);
487 auth_type
= lib
->settings
->get_str(lib
->settings
,
488 "charon.plugins.tnc-ifmap.auth_type", "Basic");
489 username
= lib
->settings
->get_str(lib
->settings
,
490 "charon.plugins.tnc-ifmap.username", NULL
);
491 password
= lib
->settings
->get_str(lib
->settings
,
492 "charon.plugins.tnc-ifmap.password", NULL
);
494 if (!username
|| !password
)
496 DBG1(DBG_TNC
, "MAP client %s%s%s not defined",
497 (!username
) ?
"username" : "",
498 (!username
&& ! password
) ?
" and " : "",
499 (!password
) ?
"password" : "");
505 .newSession
= _newSession
,
506 .purgePublisher
= _purgePublisher
,
508 .endSession
= _endSession
,
513 /* Create Axis2/C environment and options */
514 this->env
= axutil_env_create_all(IFMAP_LOGFILE
, AXIS2_LOG_LEVEL_TRACE
);
515 options
= axis2_options_create(this->env
);
517 /* Define the IF-MAP server as the to endpoint reference */
518 endpoint_ref
= axis2_endpoint_ref_create(this->env
, server
);
519 axis2_options_set_to(options
, this->env
, endpoint_ref
);
521 /* Create the axis2 service client */
522 this->svc_client
= axis2_svc_client_create(this->env
, client_home
);
523 if (!this->svc_client
)
525 DBG1(DBG_TNC
, "could not create axis2 service client");
526 AXIS2_LOG_ERROR(this->env
->log
, AXIS2_LOG_SI
,
527 "Stub invoke FAILED: Error code: %d :: %s",
528 this->env
->error
->error_number
,
529 AXIS2_ERROR_GET_MESSAGE(this->env
->error
));
534 axis2_svc_client_set_options(this->svc_client
, this->env
, options
);
535 axis2_options_set_http_auth_info(options
, this->env
, username
, password
,
537 DBG1(DBG_TNC
, "connecting as MAP client '%s' to MAP server at '%s'",
540 return &this->public;