ifmap plugin subscribes to assing_vip bus signal
[strongswan.git] / src / libcharon / plugins / tnc_ifmap / tnc_ifmap_soap.c
1 /*
2 * Copyright (C) 2011-2013 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 #include "tnc_ifmap_soap_msg.h"
18
19 #include <utils/debug.h>
20 #include <credentials/sets/mem_cred.h>
21 #include <daemon.h>
22
23 #include <tls_socket.h>
24
25 #include <errno.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29
30 #define IFMAP_NS "http://www.trustedcomputinggroup.org/2010/IFMAP/2"
31 #define IFMAP_META_NS "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2"
32 #define IFMAP_URI "https://localhost:8444/imap"
33 #define IFMAP_NO_FD -1
34
35 typedef struct private_tnc_ifmap_soap_t private_tnc_ifmap_soap_t;
36
37 /**
38 * Private data of an tnc_ifmap_soap_t object.
39 */
40 struct private_tnc_ifmap_soap_t {
41
42 /**
43 * Public tnc_ifmap_soap_t interface.
44 */
45 tnc_ifmap_soap_t public;
46
47 /**
48 * SOAP Session ID
49 */
50 xmlChar *session_id;
51
52 /**
53 * IF-MAP Publisher ID
54 */
55 xmlChar *ifmap_publisher_id;
56
57 /**
58 * IF-MAP namespace
59 */
60 xmlNsPtr ns;
61
62 /**
63 * IF-MAP metadata namespace
64 */
65 xmlNsPtr ns_meta;
66
67 /**
68 * PEP and PDP device name
69 */
70 char *device_name;
71
72 /**
73 * HTTPS Server URI with https:// prefix removed
74 */
75 char *uri;
76
77 /**
78 * Optional base64-encoded username:password for HTTP Basic Authentication
79 */
80 chunk_t user_pass;
81
82 /**
83 * IF-MAP Server (IP address and port)
84 */
85 host_t *host;
86
87 /**
88 * TLS socket
89 */
90 tls_socket_t *tls;
91
92 /**
93 * File descriptor for secure TCP socket
94 */
95 int fd;
96
97 /**
98 * In memory credential set
99 */
100 mem_cred_t *creds;
101
102 /**
103 * reference count
104 */
105 refcount_t ref;
106
107 };
108
109 METHOD(tnc_ifmap_soap_t, newSession, bool,
110 private_tnc_ifmap_soap_t *this)
111 {
112 tnc_ifmap_soap_msg_t *soap_msg;
113 xmlNodePtr request, result;
114
115 /*build newSession request */
116 request = xmlNewNode(NULL, "newSession");
117 this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
118 xmlSetNs(request, this->ns);
119
120 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
121 if (!soap_msg->post(soap_msg, request, "newSessionResult", &result))
122 {
123 soap_msg->destroy(soap_msg);
124 return FALSE;
125 }
126
127 /* get session-id and ifmap-publisher-id properties */
128 this->session_id = xmlGetProp(result, "session-id");
129 this->ifmap_publisher_id = xmlGetProp(result, "ifmap-publisher-id");
130 soap_msg->destroy(soap_msg);
131
132 DBG1(DBG_TNC, "created ifmap session '%s' as publisher '%s'",
133 this->session_id, this->ifmap_publisher_id);
134
135 /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
136 this->device_name = lib->settings->get_str(lib->settings,
137 "%s.plugins.tnc-ifmap.device_name",
138 this->ifmap_publisher_id, charon->name);
139 this->device_name = strdup(this->device_name);
140
141 return this->session_id && this->ifmap_publisher_id;
142 }
143
144 METHOD(tnc_ifmap_soap_t, renewSession, bool,
145 private_tnc_ifmap_soap_t *this)
146 {
147 tnc_ifmap_soap_msg_t *soap_msg;
148 xmlNodePtr request;
149 bool success;
150
151 /* build renewSession request */
152 request = xmlNewNode(NULL, "renewSession");
153 this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
154 xmlSetNs(request, this->ns);
155 xmlNewProp(request, "session-id", this->session_id);
156
157 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
158 success = soap_msg->post(soap_msg, request, "renewSessionResult", NULL);
159 soap_msg->destroy(soap_msg);
160
161 return success;
162 }
163
164 METHOD(tnc_ifmap_soap_t, purgePublisher, bool,
165 private_tnc_ifmap_soap_t *this)
166 {
167 tnc_ifmap_soap_msg_t *soap_msg;
168 xmlNodePtr request;
169 bool success;
170
171 /* build purgePublisher request */
172 request = xmlNewNode(NULL, "purgePublisher");
173 this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
174 xmlSetNs(request, this->ns);
175 xmlNewProp(request, "session-id", this->session_id);
176 xmlNewProp(request, "ifmap-publisher-id", this->ifmap_publisher_id);
177
178 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
179 success = soap_msg->post(soap_msg, request, "purgePublisherReceived", NULL);
180 soap_msg->destroy(soap_msg);
181
182 return success;
183 }
184
185 /**
186 * Create an access-request based on device_name and ike_sa_id
187 */
188 static xmlNodePtr create_access_request(private_tnc_ifmap_soap_t *this,
189 u_int32_t id)
190 {
191 xmlNodePtr node;
192 char buf[BUF_LEN];
193
194 node = xmlNewNode(NULL, "access-request");
195
196 snprintf(buf, BUF_LEN, "%s:%d", this->device_name, id);
197 xmlNewProp(node, "name", buf);
198
199 return node;
200 }
201
202 /**
203 * Create an identity
204 */
205 static xmlNodePtr create_identity(private_tnc_ifmap_soap_t *this,
206 identification_t *id, bool is_user)
207 {
208 xmlNodePtr node;
209 char buf[BUF_LEN], *id_type;
210
211 node = xmlNewNode(NULL, "identity");
212
213 snprintf(buf, BUF_LEN, "%Y", id);
214 xmlNewProp(node, "name", buf);
215
216 switch (id->get_type(id))
217 {
218 case ID_IPV4_ADDR:
219 id_type = "other";
220 xmlNewProp(node, "other-type-definition", "36906:ipv4-address");
221 break;
222 case ID_FQDN:
223 id_type = is_user ? "username" : "dns-name";
224 break;
225 case ID_RFC822_ADDR:
226 id_type = "email-address";
227 break;
228 case ID_IPV6_ADDR:
229 id_type = "other";
230 xmlNewProp(node, "other-type-definition", "36906:ipv6-address");
231 break;
232 case ID_DER_ASN1_DN:
233 id_type = "distinguished-name";
234 break;
235 case ID_KEY_ID:
236 id_type = "other";
237 xmlNewProp(node, "other-type-definition", "36906:key-id");
238 break;
239 default:
240 id_type = "other";
241 xmlNewProp(node, "other-type-definition", "36906:other");
242 }
243 xmlNewProp(node, "type", id_type);
244
245 return node;
246 }
247
248 /**
249 * Create enforcement-report metadata
250 */
251 static xmlNodePtr create_enforcement_report(private_tnc_ifmap_soap_t *this,
252 xmlChar *action, xmlChar *reason)
253 {
254 xmlNodePtr node, node2, node3;
255
256 node = xmlNewNode(NULL, "metadata");
257 node2 = xmlNewNode(this->ns_meta, "enforcement-report");
258 xmlAddChild(node, node2);
259 xmlNewProp(node2, "ifmap-cardinality", "multiValue");
260
261 node3 = xmlNewNode(NULL, "enforcement-action");
262 xmlAddChild(node2, node3);
263 xmlNodeAddContent(node3, action);
264
265 node3 = xmlNewNode(NULL, "enforcement-reason");
266 xmlAddChild(node2, node3);
267 xmlNodeAddContent(node3, reason);
268
269 return node;
270 }
271
272 /**
273 * Create delete filter
274 */
275 static xmlNodePtr create_delete_filter(private_tnc_ifmap_soap_t *this,
276 char *metadata)
277 {
278 xmlNodePtr node;
279 char buf[BUF_LEN];
280
281 node = xmlNewNode(NULL, "delete");
282
283 snprintf(buf, BUF_LEN, "meta:%s[@ifmap-publisher-id='%s']",
284 metadata, this->ifmap_publisher_id);
285 xmlNewProp(node, "filter", buf);
286
287 return node;
288 }
289
290 /**
291 * Create a publish request
292 */
293 static xmlNodePtr create_publish_request(private_tnc_ifmap_soap_t *this)
294 {
295 xmlNodePtr request;
296
297 request = xmlNewNode(NULL, "publish");
298 this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
299 xmlSetNs(request, this->ns);
300 this->ns_meta = xmlNewNs(request, IFMAP_META_NS, "meta");
301 xmlNewProp(request, "session-id", this->session_id);
302
303 return request;
304 }
305
306 /**
307 * Create a device
308 */
309 static xmlNodePtr create_device(private_tnc_ifmap_soap_t *this)
310 {
311 xmlNodePtr node, node2;
312
313 node = xmlNewNode(NULL, "device");
314 node2 = xmlNewNode(NULL, "name");
315 xmlAddChild(node, node2);
316 xmlNodeAddContent(node2, this->device_name);
317
318 return node;
319 }
320
321 /**
322 * Create an ip-address
323 */
324 static xmlNodePtr create_ip_address(private_tnc_ifmap_soap_t *this,
325 host_t *host)
326 {
327 xmlNodePtr node;
328 char buf[BUF_LEN];
329
330 node = xmlNewNode(NULL, "ip-address");
331
332 if (host->get_family(host) == AF_INET6)
333 {
334 chunk_t address;
335 int len, written, i;
336 char *pos;
337 bool first = TRUE;
338
339 /* output IPv6 address in canonical IF-MAP 2.0 format */
340 address = host->get_address(host);
341 pos = buf;
342 len = sizeof(buf);
343
344 for (i = 0; i < address.len; i = i + 2)
345 {
346 written = snprintf(pos, len, "%s%x", first ? "" : ":",
347 256*address.ptr[i] + address.ptr[i+1]);
348 if (written < 0 || written >= len)
349 {
350 break;
351 }
352 pos += written;
353 len -= written;
354 first = FALSE;
355 }
356 }
357 else
358 {
359 snprintf(buf, BUF_LEN, "%H", host);
360 }
361
362 xmlNewProp(node, "value", buf);
363 xmlNewProp(node, "type", host->get_family(host) == AF_INET ? "IPv4" : "IPv6");
364
365 return node;
366 }
367
368 /**
369 * Create metadata
370 */
371 static xmlNodePtr create_metadata(private_tnc_ifmap_soap_t *this,
372 xmlChar *metadata)
373 {
374 xmlNodePtr node, node2;
375
376 node = xmlNewNode(NULL, "metadata");
377 node2 = xmlNewNode(this->ns_meta, metadata);
378 xmlAddChild(node, node2);
379 xmlNewProp(node2, "ifmap-cardinality", "singleValue");
380
381 return node;
382 }
383
384 /**
385 * Create capability metadata
386 */
387 static xmlNodePtr create_capability(private_tnc_ifmap_soap_t *this,
388 identification_t *name)
389 {
390 xmlNodePtr node, node2;
391 char buf[BUF_LEN];
392
393 node = xmlNewNode(this->ns_meta, "capability");
394 xmlNewProp(node, "ifmap-cardinality", "multiValue");
395
396 node2 = xmlNewNode(NULL, "name");
397 xmlAddChild(node, node2);
398 snprintf(buf, BUF_LEN, "%Y", name);
399 xmlNodeAddContent(node2, buf);
400
401 node2 = xmlNewNode(NULL, "administrative-domain");
402 xmlAddChild(node, node2);
403 xmlNodeAddContent(node2, "strongswan");
404
405 return node;
406 }
407
408 METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
409 private_tnc_ifmap_soap_t *this, ike_sa_t *ike_sa, bool up)
410 {
411 tnc_ifmap_soap_msg_t *soap_msg;
412 xmlNodePtr request, node, node2 = NULL;
413 enumerator_t *e1, *e2;
414 auth_rule_t type;
415 identification_t *id, *eap_id, *group;
416 host_t *host;
417 auth_cfg_t *auth;
418 u_int32_t ike_sa_id;
419 bool is_user = FALSE, first = TRUE, success;
420
421 /* extract relevant data from IKE_SA*/
422 ike_sa_id = ike_sa->get_unique_id(ike_sa);
423 host = ike_sa->get_other_host(ike_sa);
424 id = ike_sa->get_other_id(ike_sa);
425 eap_id = ike_sa->get_other_eap_id(ike_sa);
426
427 /* in the presence of an EAP Identity, treat it as a username */
428 if (!id->equals(id, eap_id))
429 {
430 is_user = TRUE;
431 id = eap_id;
432 }
433
434 /* build publish request */
435 request = create_publish_request(this);
436
437 /* delete any existing enforcement reports */
438 if (up)
439 {
440 node = create_delete_filter(this, "enforcement-report");
441 xmlAddChild(request, node);
442 xmlAddChild(node, create_ip_address(this, host));
443 xmlAddChild(node, create_device(this));
444 }
445
446 /**
447 * update or delete authenticated-as metadata
448 */
449 if (up)
450 {
451 node = xmlNewNode(NULL, "update");
452 }
453 else
454 {
455 node = create_delete_filter(this, "authenticated-as");
456 }
457 xmlAddChild(request, node);
458
459 /* add access-request, identity and [if up] metadata */
460 xmlAddChild(node, create_access_request(this, ike_sa_id));
461 xmlAddChild(node, create_identity(this, id, is_user));
462 if (up)
463 {
464 xmlAddChild(node, create_metadata(this, "authenticated-as"));
465 }
466
467 /**
468 * update or delete access-request-ip metadata for physical IP address
469 */
470 if (up)
471 {
472 node = xmlNewNode(NULL, "update");
473 }
474 else
475 {
476 node = create_delete_filter(this, "access-request-ip");
477 }
478 xmlAddChild(request, node);
479
480 /* add access-request, ip-address and [if up] metadata */
481 xmlAddChild(node, create_access_request(this, ike_sa_id));
482 xmlAddChild(node, create_ip_address(this, host));
483 if (up)
484 {
485 xmlAddChild(node, create_metadata(this, "access-request-ip"));
486 }
487
488 /**
489 * update or delete authenticated-by metadata
490 */
491 if (up)
492 {
493 node = xmlNewNode(NULL, "update");
494 }
495 else
496 {
497 node = create_delete_filter(this, "authenticated-by");
498 }
499 xmlAddChild(request, node);
500
501 /* add access-request, device and [if up] metadata */
502 xmlAddChild(node, create_access_request(this, ike_sa_id));
503 xmlAddChild(node, create_device(this));
504 if (up)
505 {
506 xmlAddChild(node, create_metadata(this, "authenticated-by"));
507 }
508
509 /**
510 * update or delete capability metadata
511 */
512 e1 = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
513 while (e1->enumerate(e1, &auth) && (first || up))
514 {
515 e2 = auth->create_enumerator(auth);
516 while (e2->enumerate(e2, &type, &group))
517 {
518 /* look for group memberships */
519 if (type == AUTH_RULE_GROUP)
520 {
521 if (first)
522 {
523 first = FALSE;
524
525 if (up)
526 {
527 node = xmlNewNode(NULL, "update");
528 }
529 else
530 {
531 node = create_delete_filter(this, "capability");
532 }
533 xmlAddChild(request, node);
534
535 /* add access-request */
536 xmlAddChild(node, create_access_request(this, ike_sa_id));
537 if (!up)
538 {
539 break;
540 }
541 node2 = xmlNewNode(NULL, "metadata");
542 xmlAddChild(node, node2);
543 }
544 xmlAddChild(node2, create_capability(this, group));
545 }
546 }
547 e2->destroy(e2);
548 }
549 e1->destroy(e1);
550
551 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
552 success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
553 soap_msg->destroy(soap_msg);
554
555 return success;
556 }
557
558 METHOD(tnc_ifmap_soap_t, publish_device_ip, bool,
559 private_tnc_ifmap_soap_t *this, host_t *host)
560 {
561 tnc_ifmap_soap_msg_t *soap_msg;
562 xmlNodePtr request, update;
563 bool success;
564
565 /* build publish update request */
566 request = create_publish_request(this);
567 update = xmlNewNode(NULL, "update");
568 xmlAddChild(request, update);
569
570 /* add device, ip-address and metadata */
571 xmlAddChild(update, create_device(this));
572 xmlAddChild(update, create_ip_address(this, host));
573 xmlAddChild(update, create_metadata(this, "device-ip"));
574
575 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
576 success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
577 soap_msg->destroy(soap_msg);
578
579 return success;
580 }
581
582 METHOD(tnc_ifmap_soap_t, publish_virtual_ip, bool,
583 private_tnc_ifmap_soap_t *this, ike_sa_t *ike_sa, host_t *vip, bool assign)
584 {
585 tnc_ifmap_soap_msg_t *soap_msg;
586 xmlNodePtr request, node;
587 u_int32_t ike_sa_id;
588 bool success;
589
590 /* extract relevant data from IKE_SA*/
591 ike_sa_id = ike_sa->get_unique_id(ike_sa);
592
593 /* build publish request */
594 request = create_publish_request(this);
595
596 /**
597 * update or delete access-request-ip metadata for a virtual IP address
598 */
599 if (assign)
600 {
601 node = xmlNewNode(NULL, "update");
602 }
603 else
604 {
605 node = create_delete_filter(this, "access-request-ip");
606 }
607 xmlAddChild(request, node);
608
609 /* add access-request, virtual ip-address and [if assign] metadata */
610 xmlAddChild(node, create_access_request(this, ike_sa_id));
611 xmlAddChild(node, create_ip_address(this, vip));
612 if (assign)
613 {
614 xmlAddChild(node, create_metadata(this, "access-request-ip"));
615 }
616
617 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
618 success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
619 soap_msg->destroy(soap_msg);
620
621 return success;
622 }
623
624 METHOD(tnc_ifmap_soap_t, publish_enforcement_report, bool,
625 private_tnc_ifmap_soap_t *this, host_t *host, char *action, char *reason)
626 {
627 tnc_ifmap_soap_msg_t *soap_msg;
628 xmlNodePtr request, update;
629 bool success;
630
631 /* build publish update request */
632 request = create_publish_request(this);
633 update = xmlNewNode(NULL, "update");
634 xmlAddChild(request, update);
635
636 /* add ip-address and metadata */
637 xmlAddChild(update, create_ip_address(this, host));
638 xmlAddChild(update, create_device(this));
639 xmlAddChild(update, create_enforcement_report(this, action, reason));
640
641 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
642 success = soap_msg->post(soap_msg, request, "publishReceived", NULL);
643 soap_msg->destroy(soap_msg);
644
645 return success;
646 }
647
648 METHOD(tnc_ifmap_soap_t, endSession, bool,
649 private_tnc_ifmap_soap_t *this)
650 {
651 tnc_ifmap_soap_msg_t *soap_msg;
652 xmlNodePtr request;
653 bool success;
654
655 /* build endSession request */
656 request = xmlNewNode(NULL, "endSession");
657 this->ns = xmlNewNs(request, IFMAP_NS, "ifmap");
658 xmlSetNs(request, this->ns);
659 xmlNewProp(request, "session-id", this->session_id);
660
661 soap_msg = tnc_ifmap_soap_msg_create(this->uri, this->user_pass, this->tls);
662 success = soap_msg->post(soap_msg, request, "endSessionResult", NULL);
663 soap_msg->destroy(soap_msg);
664
665 DBG1(DBG_TNC, "ended ifmap session '%s' as publisher '%s'",
666 this->session_id, this->ifmap_publisher_id);
667
668 return success;
669 }
670
671 METHOD(tnc_ifmap_soap_t, get_session_id, char*,
672 private_tnc_ifmap_soap_t *this)
673 {
674 return this->session_id;
675 }
676
677 METHOD(tnc_ifmap_soap_t, orphaned, bool,
678 private_tnc_ifmap_soap_t *this)
679 {
680 return this->ref == 1;
681 }
682
683 METHOD(tnc_ifmap_soap_t, get_ref, tnc_ifmap_soap_t*,
684 private_tnc_ifmap_soap_t *this)
685 {
686 ref_get(&this->ref);
687 return &this->public;
688 }
689
690 METHOD(tnc_ifmap_soap_t, destroy, void,
691 private_tnc_ifmap_soap_t *this)
692 {
693 if (ref_put(&this->ref))
694 {
695 if (this->session_id)
696 {
697 xmlFree(this->session_id);
698 xmlFree(this->ifmap_publisher_id);
699 free(this->device_name);
700 }
701 DESTROY_IF(this->tls);
702 DESTROY_IF(this->host);
703
704 if (this->fd != IFMAP_NO_FD)
705 {
706 close(this->fd);
707 }
708 lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
709 this->creds->destroy(this->creds);
710 free(this->user_pass.ptr);
711 free(this);
712 }
713 }
714
715 static bool soap_init(private_tnc_ifmap_soap_t *this)
716 {
717 char *server_uri, *server_str, *port_str, *uri_str;
718 char *server_cert, *client_cert, *client_key, *user_pass;
719 int port;
720 auth_cfg_t *auth;
721 certificate_t *cert;
722 private_key_t *key;
723 identification_t *server_id, *client_id = NULL;
724
725 /* getting configuration parameters from strongswan.conf */
726 server_uri = lib->settings->get_str(lib->settings,
727 "%s.plugins.tnc-ifmap.server_uri", IFMAP_URI, charon->name);
728 server_cert = lib->settings->get_str(lib->settings,
729 "%s.plugins.tnc-ifmap.server_cert", NULL, charon->name);
730 client_cert = lib->settings->get_str(lib->settings,
731 "%s.plugins.tnc-ifmap.client_cert", NULL, charon->name);
732 client_key = lib->settings->get_str(lib->settings,
733 "%s.plugins.tnc-ifmap.client_key", NULL, charon->name);
734 user_pass = lib->settings->get_str(lib->settings,
735 "%s.plugins.tnc-ifmap.username_password", NULL, charon->name);
736
737 /* load [self-signed] MAP server certificate */
738 if (!server_cert)
739 {
740 DBG1(DBG_TNC, "MAP server certificate not defined");
741 return FALSE;
742 }
743 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
744 BUILD_FROM_FILE, server_cert, BUILD_END);
745 if (!cert)
746 {
747 DBG1(DBG_TNC, "loading MAP server certificate from '%s' failed",
748 server_cert);
749 return FALSE;
750 }
751 DBG1(DBG_TNC, "loaded MAP server certificate from '%s'", server_cert);
752 server_id = cert->get_subject(cert);
753 this->creds->add_cert(this->creds, TRUE, cert);
754
755 /* check availability of client credentials */
756 if (!client_cert && !user_pass)
757 {
758 DBG1(DBG_TNC, "neither MAP client certificate "
759 "nor username:password defined");
760 return FALSE;
761 }
762
763 if (client_cert)
764 {
765 /* load MAP client certificate */
766 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
767 BUILD_FROM_FILE, client_cert, BUILD_END);
768 if (!cert)
769 {
770 DBG1(DBG_TNC, "loading MAP client certificate from '%s' failed",
771 client_cert);
772 return FALSE;
773 }
774 DBG1(DBG_TNC, "loaded MAP client certificate from '%s'", client_cert);
775 this->creds->add_cert(this->creds, TRUE, cert);
776
777 /* load MAP client private key */
778 if (client_key)
779 {
780 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
781 BUILD_FROM_FILE, client_key, BUILD_END);
782 if (!key)
783 {
784 DBG1(DBG_TNC, "loading MAP client private key from '%s' failed",
785 client_key);
786 return FALSE;
787 }
788 DBG1(DBG_TNC, "loaded MAP client RSA private key from '%s'",
789 client_key);
790 this->creds->add_key(this->creds, key);
791 }
792
793 /* set client ID to certificate distinguished name */
794 client_id = cert->get_subject(cert);
795
796 /* check if we have a private key matching the certificate */
797 auth = auth_cfg_create();
798 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
799 key = lib->credmgr->get_private(lib->credmgr, KEY_RSA, client_id, auth);
800 auth->destroy(auth);
801 if (!key)
802 {
803 DBG1(DBG_TNC, "no RSA private key matching MAP client certificate");
804 return FALSE;
805 }
806 }
807 else
808 {
809 /* set base64-encoded username:password for HTTP Basic Authentication */
810 this->user_pass = chunk_to_base64(chunk_from_str(user_pass), NULL);
811 }
812
813 /* remove HTTPS prefix if any */
814 if (strlen(server_uri) >= 8 && strncaseeq(server_uri, "https://", 8))
815 {
816 server_uri += 8;
817 }
818 this->uri = server_uri;
819
820 /* duplicate server string since we are going to manipulate it */
821 server_str = strdup(server_uri);
822
823 /* extract server name and port from server URI */
824 port_str = strchr(server_str, ':');
825 if (port_str)
826 {
827 *port_str++ = '\0';
828 if (sscanf(port_str, "%d", &port) != 1)
829 {
830 DBG1(DBG_TNC, "parsing server port %s failed", port_str);
831 free(server_str);
832 return FALSE;
833 }
834 }
835 else
836 {
837 /* use default https port */
838 port = 443;
839 uri_str = strchr(server_str, '/');
840 if (uri_str)
841 {
842 *uri_str = '\0';
843 }
844 }
845
846 /* open TCP socket and connect to MAP server */
847 this->host = host_create_from_dns(server_str, 0, port);
848 if (!this->host)
849 {
850 DBG1(DBG_TNC, "resolving hostname %s failed", server_str);
851 free(server_str);
852 return FALSE;
853 }
854 free(server_str);
855
856 this->fd = socket(this->host->get_family(this->host), SOCK_STREAM, 0);
857 if (this->fd == IFMAP_NO_FD)
858 {
859 DBG1(DBG_TNC, "opening socket failed: %s", strerror(errno));
860 return FALSE;
861 }
862
863 if (connect(this->fd, this->host->get_sockaddr(this->host),
864 *this->host->get_sockaddr_len(this->host)) == -1)
865 {
866 DBG1(DBG_TNC, "connecting to %#H failed: %s",
867 this->host, strerror(errno));
868 return FALSE;
869 }
870
871 /* open TLS socket */
872 this->tls = tls_socket_create(FALSE, server_id, client_id, this->fd, NULL);
873 if (!this->tls)
874 {
875 DBG1(DBG_TNC, "creating TLS socket failed");
876 return FALSE;
877 }
878
879 return TRUE;
880 }
881
882 /**
883 * See header
884 */
885 tnc_ifmap_soap_t *tnc_ifmap_soap_create()
886 {
887 private_tnc_ifmap_soap_t *this;
888
889 INIT(this,
890 .public = {
891 .newSession = _newSession,
892 .renewSession = _renewSession,
893 .purgePublisher = _purgePublisher,
894 .publish_ike_sa = _publish_ike_sa,
895 .publish_device_ip = _publish_device_ip,
896 .publish_virtual_ip = _publish_virtual_ip,
897 .publish_enforcement_report = _publish_enforcement_report,
898 .endSession = _endSession,
899 .get_session_id = _get_session_id,
900 .orphaned = _orphaned,
901 .get_ref = _get_ref,
902 .destroy = _destroy,
903 },
904 .fd = IFMAP_NO_FD,
905 .creds = mem_cred_create(),
906 .ref = 1,
907 );
908
909 lib->credmgr->add_set(lib->credmgr, &this->creds->set);
910
911 if (!soap_init(this))
912 {
913 destroy(this);
914 return NULL;
915 }
916
917 return &this->public;
918 }
919