moved ifmap code into tnc_ifmap_soap
[strongswan.git] / src / libcharon / plugins / tnc_ifmap / tnc_ifmap_soap.c
1 /*
2 * Copyright (C) 2011 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "tnc_ifmap_soap.h"
17
18 #include <debug.h>
19
20 #include <axis2_util.h>
21 #include <axis2_client.h>
22 #include <axiom_soap.h>
23
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/"
28
29 typedef struct private_tnc_ifmap_soap_t private_tnc_ifmap_soap_t;
30
31 /**
32 * Private data of an tnc_ifmap_soap_t object.
33 */
34 struct private_tnc_ifmap_soap_t {
35
36 /**
37 * Public tnc_ifmap_soap_t interface.
38 */
39 tnc_ifmap_soap_t public;
40
41 /**
42 * Axis2/C environment
43 */
44 axutil_env_t *env;
45
46 /**
47 * Axis2 service client
48 */
49 axis2_svc_client_t* svc_client;
50
51 /**
52 * SOAP Session ID
53 */
54 char *session_id;
55
56 /**
57 * IF-MAP Publisher ID
58 */
59 char *ifmap_publisher_id;
60
61 /**
62 * PEP and PDP device name
63 */
64 char *device_name;
65
66 };
67
68 METHOD(tnc_ifmap_soap_t, newSession, bool,
69 private_tnc_ifmap_soap_t *this)
70 {
71 axiom_node_t *request, *result, *node;
72 axiom_element_t *el;
73 axiom_namespace_t *ns;
74 axiom_attribute_t *attr;
75 axis2_char_t *value;
76 axutil_qname_t *qname;
77
78 bool success = FALSE;
79
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);
85
86 /* send newSession request */
87 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
88 if (!result)
89 {
90 return FALSE;
91 }
92
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)
96 {
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));
101
102 /* process the attributes */
103 if (success)
104 {
105 value = axiom_element_get_attribute_value_by_name(el, this->env,
106 "session-id");
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);
111
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;
115
116 value = axiom_element_get_attribute_value_by_name(el, this->env,
117 "max-poll-result-size");
118 if (value)
119 {
120 DBG1(DBG_TNC, "max-poll-result-size: %s", value);
121 }
122
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);
128 }
129 else
130 {
131 DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
132 }
133 }
134 axiom_node_free_tree(result, this->env);
135
136 return success;
137 }
138
139 METHOD(tnc_ifmap_soap_t, purgePublisher, bool,
140 private_tnc_ifmap_soap_t *this)
141 {
142 axiom_node_t *request, *result, *node;
143 axiom_element_t *el;
144 axiom_namespace_t *ns;
145 axiom_attribute_t *attr;
146 axutil_qname_t *qname;
147 bool success = FALSE;
148
149 /* build purgePublisher request */
150 ns = axiom_namespace_create(this->env, IFMAP_NS, "ifmap");
151 el = axiom_element_create(this->env, NULL, "purgePublisher", ns,
152 &request);
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);
159
160 /* send purgePublisher request */
161 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
162 if (!result)
163 {
164 return FALSE;
165 }
166
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)
170 {
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));
175 if (!success)
176 {
177 DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
178 }
179 }
180 axiom_node_free_tree(result, this->env);
181
182 return success;
183 }
184
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)
188 {
189 axiom_node_t *request, *result, *node, *node2, *node3, *node4;
190 axiom_element_t *el;
191 axiom_namespace_t *ns, *ns_meta;
192 axiom_attribute_t *attr;
193 axiom_text_t *text;
194 axutil_qname_t *qname;
195 char buf[BUF_LEN], *id_type;
196 bool success = FALSE;
197
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,
204 NULL);
205 axiom_element_add_attribute(el, this->env, attr, request);
206
207 /**
208 * update or delete authenticated-as metadata
209 */
210 if (up)
211 {
212 el = axiom_element_create(this->env, NULL, "update", NULL, &node);
213 axiom_node_add_child(request, this->env, node);
214 }
215 else
216 {
217 el = axiom_element_create(this->env, NULL, "delete", NULL, &node);
218 axiom_node_add_child(request, this->env, node);
219
220 /* add filter */
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);
225 }
226
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);
230
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);
234
235 /* add identity */
236 el = axiom_element_create(this->env, NULL, "identity", NULL, &node2);
237 axiom_node_add_child(node, this->env, node2);
238
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);
242
243 switch (id->get_type(id))
244 {
245 case ID_FQDN:
246 id_type = "dns-name";
247 break;
248 case ID_RFC822_ADDR:
249 id_type = "email-address";
250 break;
251 case ID_DER_ASN1_DN:
252 id_type = "distinguished-name";
253 break;
254 default:
255 id_type = "other";
256 }
257 attr = axiom_attribute_create(this->env, "type", id_type, NULL);
258 axiom_element_add_attribute(el, this->env, attr, node2);
259
260 if (up)
261 {
262 /* add metadata */
263 el = axiom_element_create(this->env, NULL, "metadata", NULL, &node2);
264 axiom_node_add_child(node, this->env, node2);
265
266 ns_meta = axiom_namespace_create(this->env, IFMAP_META_NS, "meta");
267
268 el = axiom_element_create(this->env, NULL, "authenticated-as", ns_meta,
269 &node3);
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);
274 }
275
276 /**
277 * update or delete access-request-ip metadata
278 */
279 if (up)
280 {
281 el = axiom_element_create(this->env, NULL, "update", NULL, &node);
282 axiom_node_add_child(request, this->env, node);
283 }
284 else
285 {
286 el = axiom_element_create(this->env, NULL, "delete", NULL, &node);
287 axiom_node_add_child(request, this->env, node);
288
289 /* add filter */
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);
294 }
295
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);
299
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);
303
304 /* add ip-address */
305 el = axiom_element_create(this->env, NULL, "ip-address", NULL, &node2);
306 axiom_node_add_child(node, this->env, node2);
307
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);
311
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);
315
316 if (up)
317 {
318 /* add metadata */
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,
323 &node3);
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);
328 }
329
330 /**
331 * update or delete authenticated-by metadata
332 */
333 if (up)
334 {
335 el = axiom_element_create(this->env, NULL, "update", NULL, &node);
336 axiom_node_add_child(request, this->env, node);
337 }
338 else
339 {
340 el = axiom_element_create(this->env, NULL, "delete", NULL, &node);
341 axiom_node_add_child(request, this->env, node);
342
343 /* add filter */
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);
348 }
349
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);
353
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);
357
358 /* add device */
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);
364
365 if (up)
366 {
367 /* add metadata */
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,
372 &node3);
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);
377 }
378
379 /* send publish request */
380 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
381 if (!result)
382 {
383 return FALSE;
384 }
385
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)
389 {
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));
394 if (!success)
395 {
396 DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
397 }
398 }
399 axiom_node_free_tree(result, this->env);
400
401 return TRUE;
402 }
403
404 METHOD(tnc_ifmap_soap_t, endSession, bool,
405 private_tnc_ifmap_soap_t *this)
406 {
407 axiom_node_t *request, *result, *node;
408 axiom_element_t *el;
409 axiom_namespace_t *ns;
410 axiom_attribute_t *attr;
411 axutil_qname_t *qname;
412 bool success = FALSE;
413
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);
419
420 /* send endSession request */
421 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
422 if (!result)
423 {
424 return FALSE;
425 }
426
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)
430 {
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));
435 if (!success)
436 {
437 DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
438 }
439 }
440 axiom_node_free_tree(result, this->env);
441
442 return success;
443
444 return TRUE;
445 }
446
447 METHOD(tnc_ifmap_soap_t, destroy, void,
448 private_tnc_ifmap_soap_t *this)
449 {
450 if (this->session_id)
451 {
452 DBG2(DBG_TNC, "sending ifmap->endSession");
453 if (!endSession(this))
454 {
455 DBG1(DBG_TNC, "ifmap->endSession with MAP server failed");
456 }
457 free(this->session_id);
458 free(this->ifmap_publisher_id);
459 free(this->device_name);
460 }
461 if (this->svc_client)
462 {
463 axis2_svc_client_free(this->svc_client, this->env);
464 }
465 if (this->env)
466 {
467 axutil_env_free(this->env);
468 }
469 free(this);
470 }
471
472 /**
473 * See header
474 */
475 tnc_ifmap_soap_t *tnc_ifmap_soap_create()
476 {
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;
481
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);
493
494 if (!username || !password)
495 {
496 DBG1(DBG_TNC, "MAP client %s%s%s not defined",
497 (!username) ? "username" : "",
498 (!username && ! password) ? " and " : "",
499 (!password) ? "password" : "");
500 return NULL;
501 }
502
503 INIT(this,
504 .public = {
505 .newSession = _newSession,
506 .purgePublisher = _purgePublisher,
507 .publish = _publish,
508 .endSession = _endSession,
509 .destroy = _destroy,
510 },
511 );
512
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);
516
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);
520
521 /* Create the axis2 service client */
522 this->svc_client = axis2_svc_client_create(this->env, client_home);
523 if (!this->svc_client)
524 {
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));
530 destroy(this);
531 return NULL;
532 }
533
534 axis2_svc_client_set_options(this->svc_client, this->env, options);
535 axis2_options_set_http_auth_info(options, this->env, username, password,
536 auth_type);
537 DBG1(DBG_TNC, "connecting as MAP client '%s' to MAP server at '%s'",
538 username, server);
539
540 return &this->public;
541 }
542