added some XML syntax checking
[strongswan.git] / src / libcharon / plugins / tnc_ifmap / tnc_ifmap_listener.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_listener.h"
17
18 #include <daemon.h>
19 #include <config/child_cfg.h>
20
21 #include <axis2_util.h>
22 #include <axis2_client.h>
23 #include <axiom_soap.h>
24
25 #define IFMAP_NAMESPACE "http://www.trustedcomputinggroup.org/2010/IFMAP/2"
26 #define IFMAP_LOGFILE "strongswan_ifmap.log"
27 #define IFMAP_SERVER "https://localhost:8443/"
28
29 typedef struct private_tnc_ifmap_listener_t private_tnc_ifmap_listener_t;
30
31 /**
32 * Private data of an tnc_ifmap_listener_t object.
33 */
34 struct private_tnc_ifmap_listener_t {
35
36 /**
37 * Public tnc_ifmap_listener_t interface.
38 */
39 tnc_ifmap_listener_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
63 static bool newSession(private_tnc_ifmap_listener_t *this)
64 {
65 axiom_node_t *request, *result, *node;
66 axiom_element_t *el;
67 axiom_namespace_t *ns;
68 axiom_attribute_t *attr;
69 axis2_char_t *value;
70 axutil_qname_t *qname;
71
72 bool success = FALSE;
73
74 /* build newSession request */
75 ns = axiom_namespace_create(this->env, IFMAP_NAMESPACE, "ifmap");
76 el = axiom_element_create(this->env, NULL, "newSession", ns, &request);
77 attr = axiom_attribute_create(this->env, "max-poll-result-size", "1000000", NULL);
78 axiom_element_add_attribute(el, this->env, attr, request);
79
80 /* send newSession request */
81 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
82 if (!result)
83 {
84 return FALSE;
85 }
86
87 /* process newSessionResult */
88 node = axiom_node_get_first_child(result, this->env);
89 if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
90 {
91 el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
92 qname = axiom_element_get_qname(el, this->env, node);
93 success = streq("newSessionResult",
94 axutil_qname_to_string(qname, this->env));
95
96 /* process the attributes */
97 if (success)
98 {
99 value = axiom_element_get_attribute_value_by_name(el, this->env,
100 "session-id");
101 this->session_id = strdup(value);
102 value = axiom_element_get_attribute_value_by_name(el, this->env,
103 "ifmap-publisher-id");
104 this->ifmap_publisher_id = strdup(value);
105
106 DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s",
107 this->session_id, this->ifmap_publisher_id);
108 success = this->session_id && this->ifmap_publisher_id;
109
110 value = axiom_element_get_attribute_value_by_name(el, this->env,
111 "max-poll-result-size");
112 if (value)
113 {
114 DBG1(DBG_TNC, "max-poll-result-size: %s", value);
115 }
116 }
117 else
118 {
119 DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
120 }
121 }
122 axiom_node_free_tree(result, this->env);
123
124 return success;
125 }
126
127 static bool purgePublisher(private_tnc_ifmap_listener_t *this)
128 {
129 axiom_node_t *request, *result, *node;
130 axiom_element_t *el;
131 axiom_namespace_t *ns;
132 axiom_attribute_t *attr;
133 axutil_qname_t *qname;
134 bool success = FALSE;
135
136 /* build purgePublisher request */
137 ns = axiom_namespace_create(this->env, IFMAP_NAMESPACE, "ifmap");
138 el = axiom_element_create(this->env, NULL, "purgePublisher", ns,
139 &request);
140 attr = axiom_attribute_create(this->env, "session-id",
141 this->session_id, NULL);
142 axiom_element_add_attribute(el, this->env, attr, request);
143 attr = axiom_attribute_create(this->env, "ifmap-publisher-id",
144 this->ifmap_publisher_id, NULL);
145 axiom_element_add_attribute(el, this->env, attr, request);
146
147 /* send purgePublisher request */
148 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
149 if (!result)
150 {
151 return FALSE;
152 }
153
154 /* process purgePublisherReceived */
155 node = axiom_node_get_first_child(result, this->env);
156 if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
157 {
158 el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
159 qname = axiom_element_get_qname(el, this->env, node);
160 success = streq("purgePublisherReceived",
161 axutil_qname_to_string(qname, this->env));
162 if (!success)
163 {
164 DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
165 }
166 }
167 axiom_node_free_tree(result, this->env);
168
169 return success;
170 }
171
172 static bool publish(private_tnc_ifmap_listener_t *this)
173 {
174 axiom_node_t *request, *result, *node;
175 axiom_element_t *el;
176 axiom_namespace_t *ns;
177 axiom_attribute_t *attr;
178
179 /* build publish request */
180 ns = axiom_namespace_create(this->env, IFMAP_NAMESPACE, "ifmap");
181 el = axiom_element_create(this->env, NULL, "publish", ns, &request);
182 attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL);
183 axiom_element_add_attribute(el, this->env, attr, request);
184
185 /* send publish request */
186 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
187 if (!result)
188 {
189 return FALSE;
190 }
191
192 /* process publishReceived */
193 node = axiom_node_get_first_child(result, this->env);
194 axiom_node_free_tree(result, this->env);
195
196 return TRUE;
197 }
198
199 static bool endSession(private_tnc_ifmap_listener_t *this)
200 {
201 axiom_node_t *request, *result, *node;
202 axiom_element_t *el;
203 axiom_namespace_t *ns;
204 axiom_attribute_t *attr;
205 axutil_qname_t *qname;
206 bool success = FALSE;
207
208 /* build endSession request */
209 ns = axiom_namespace_create(this->env, IFMAP_NAMESPACE, "ifmap");
210 el = axiom_element_create(this->env, NULL, "endSession", ns, &request);
211 attr = axiom_attribute_create(this->env, "session-id", this->session_id, NULL);
212 axiom_element_add_attribute(el, this->env, attr, request);
213
214 /* send endSession request */
215 result = axis2_svc_client_send_receive(this->svc_client, this->env, request);
216 if (!result)
217 {
218 return FALSE;
219 }
220
221 /* process endSessionResult */
222 node = axiom_node_get_first_child(result, this->env);
223 if (node && axiom_node_get_node_type(node, this->env) == AXIOM_ELEMENT)
224 {
225 el = (axiom_element_t *)axiom_node_get_data_element(node, this->env);
226 qname = axiom_element_get_qname(el, this->env, node);
227 success = streq("endSessionResult",
228 axutil_qname_to_string(qname, this->env));
229 if (!success)
230 {
231 DBG1(DBG_TNC, "%s", axiom_element_to_string(el, this->env, node));
232 }
233 }
234 axiom_node_free_tree(result, this->env);
235
236 return success;
237
238 return TRUE;
239 }
240
241 METHOD(listener_t, child_updown, bool,
242 private_tnc_ifmap_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
243 bool up)
244 {
245 traffic_selector_t *my_ts, *other_ts;
246 enumerator_t *enumerator;
247 child_cfg_t *config;
248 host_t *vip, *me, *other;
249
250 config = child_sa->get_config(child_sa);
251 vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
252 me = ike_sa->get_my_host(ike_sa);
253 other = ike_sa->get_other_host(ike_sa);
254
255 DBG2(DBG_TNC, "sending publish");
256 if (!publish(this))
257 {
258 DBG1(DBG_TNC, "publish with MAP server failed");
259 }
260
261 return TRUE;
262 }
263
264 METHOD(tnc_ifmap_listener_t, destroy, void,
265 private_tnc_ifmap_listener_t *this)
266 {
267 if (this->session_id)
268 {
269 DBG2(DBG_TNC, "sending endSession");
270 if (!endSession(this))
271 {
272 DBG1(DBG_TNC, "endSession with MAP server failed");
273 }
274 free(this->session_id);
275 free(this->ifmap_publisher_id);
276 }
277 if (this->svc_client)
278 {
279 axis2_svc_client_free(this->svc_client, this->env);
280 }
281 if (this->env)
282 {
283 axutil_env_free(this->env);
284 }
285 free(this);
286 }
287
288 /**
289 * See header
290 */
291 tnc_ifmap_listener_t *tnc_ifmap_listener_create()
292 {
293 private_tnc_ifmap_listener_t *this;
294 axis2_char_t *server, *client_home, *username, *password, *auth_type;
295 axis2_endpoint_ref_t* endpoint_ref = NULL;
296 axis2_options_t *options = NULL;
297
298 client_home = lib->settings->get_str(lib->settings,
299 "charon.plugins.tnc-ifmap.client_home",
300 AXIS2_GETENV("AXIS2C_HOME"));
301 server = lib->settings->get_str(lib->settings,
302 "charon.plugins.tnc-ifmap.server", IFMAP_SERVER);
303 auth_type = lib->settings->get_str(lib->settings,
304 "charon.plugins.tnc-ifmap.auth_type", "Basic");
305 username = lib->settings->get_str(lib->settings,
306 "charon.plugins.tnc-ifmap.username", NULL);
307 password = lib->settings->get_str(lib->settings,
308 "charon.plugins.tnc-ifmap.password", NULL);
309
310 if (!username || !password)
311 {
312 DBG1(DBG_TNC, "MAP client %s%s%s not defined",
313 (!username) ? "username" : "",
314 (!username && ! password) ? " and " : "",
315 (!password) ? "password" : "");
316 }
317
318 INIT(this,
319 .public = {
320 .listener = {
321 .child_updown = _child_updown,
322 },
323 .destroy = _destroy,
324 },
325 );
326
327 /* Create Axis2/C environment and options */
328 this->env = axutil_env_create_all(IFMAP_LOGFILE, AXIS2_LOG_LEVEL_TRACE);
329 options = axis2_options_create(this->env);
330
331 /* Define the IF-MAP server as the to endpoint reference */
332 endpoint_ref = axis2_endpoint_ref_create(this->env, server);
333 axis2_options_set_to(options, this->env, endpoint_ref);
334
335 /* Create the axis2 service client */
336 this->svc_client = axis2_svc_client_create(this->env, client_home);
337 if (!this->svc_client)
338 {
339 DBG1(DBG_TNC, "Error creating axis2 service client");
340 AXIS2_LOG_ERROR(this->env->log, AXIS2_LOG_SI,
341 "Stub invoke FAILED: Error code: %d :: %s",
342 this->env->error->error_number,
343 AXIS2_ERROR_GET_MESSAGE(this->env->error));
344 destroy(this);
345 return NULL;
346 }
347
348 axis2_svc_client_set_options(this->svc_client, this->env, options);
349 axis2_options_set_http_auth_info(options, this->env, username, password,
350 auth_type);
351 DBG1(DBG_TNC, "connecting as MAP client '%s' to MAP server at '%s'",
352 username, server);
353
354 DBG2(DBG_TNC, "sending newSession");
355 if (!newSession(this))
356 {
357 DBG1(DBG_TNC, "newSession with MAP server failed");
358 destroy(this);
359 return NULL;
360 }
361 DBG2(DBG_TNC, "sending purgePublisher");
362 if (!purgePublisher(this))
363 {
364 DBG1(DBG_TNC, "purgePublisher with MAP server failed");
365 destroy(this);
366 return NULL;
367 }
368
369 return &this->public;
370 }
371