cf7ec369cf6cc2986a5c9b050738de6de4b74e0a
[strongswan.git] / src / libcharon / plugins / stroke / stroke_socket.c
1 /*
2 * Copyright (C) 2011-2012 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "stroke_socket.h"
18
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <unistd.h>
25 #include <errno.h>
26
27 #include <hydra.h>
28 #include <daemon.h>
29
30 #include "stroke_config.h"
31 #include "stroke_control.h"
32 #include "stroke_cred.h"
33 #include "stroke_ca.h"
34 #include "stroke_attribute.h"
35 #include "stroke_handler.h"
36 #include "stroke_list.h"
37 #include "stroke_counter.h"
38
39 /**
40 * To avoid clogging the thread pool with (blocking) jobs, we limit the number
41 * of concurrently handled stroke commands.
42 */
43 #define MAX_CONCURRENT_DEFAULT 4
44
45 typedef struct stroke_job_context_t stroke_job_context_t;
46 typedef struct private_stroke_socket_t private_stroke_socket_t;
47
48 /**
49 * private data of stroke_socket
50 */
51 struct private_stroke_socket_t {
52
53 /**
54 * public functions
55 */
56 stroke_socket_t public;
57
58 /**
59 * Service accepting stroke connections
60 */
61 stream_service_t *service;
62
63 /**
64 * configuration backend
65 */
66 stroke_config_t *config;
67
68 /**
69 * attribute provider
70 */
71 stroke_attribute_t *attribute;
72
73 /**
74 * attribute handler (requests only)
75 */
76 stroke_handler_t *handler;
77
78 /**
79 * controller to control daemon
80 */
81 stroke_control_t *control;
82
83 /**
84 * credential set
85 */
86 stroke_cred_t *cred;
87
88 /**
89 * CA sections
90 */
91 stroke_ca_t *ca;
92
93 /**
94 * status information logging
95 */
96 stroke_list_t *list;
97
98 /**
99 * Counter values for IKE events
100 */
101 stroke_counter_t *counter;
102 };
103
104 /**
105 * Helper function which corrects the string pointers
106 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
107 * contains RELATIVE addresses (relative to the beginning of the
108 * stroke_msg). They must be corrected if they reach our address
109 * space...
110 */
111 static void pop_string(stroke_msg_t *msg, char **string)
112 {
113 if (*string == NULL)
114 {
115 return;
116 }
117
118 /* check for sanity of string pointer and string */
119 if (string < (char**)msg ||
120 string > (char**)((char*)msg + sizeof(stroke_msg_t)) ||
121 (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) ||
122 (unsigned long)*string > msg->length)
123 {
124 *string = "(invalid pointer in stroke msg)";
125 }
126 else
127 {
128 *string = (char*)msg + (unsigned long)*string;
129 }
130 }
131
132 /**
133 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
134 */
135 static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
136 {
137 pop_string(msg, &end->address);
138 pop_string(msg, &end->subnets);
139 pop_string(msg, &end->sourceip);
140 pop_string(msg, &end->dns);
141 pop_string(msg, &end->auth);
142 pop_string(msg, &end->auth2);
143 pop_string(msg, &end->id);
144 pop_string(msg, &end->id2);
145 pop_string(msg, &end->rsakey);
146 pop_string(msg, &end->cert);
147 pop_string(msg, &end->cert2);
148 pop_string(msg, &end->ca);
149 pop_string(msg, &end->ca2);
150 pop_string(msg, &end->groups);
151 pop_string(msg, &end->groups2);
152 pop_string(msg, &end->cert_policy);
153 pop_string(msg, &end->updown);
154
155 DBG2(DBG_CFG, " %s=%s", label, end->address);
156 DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
157 DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
158 DBG2(DBG_CFG, " %sdns=%s", label, end->dns);
159 DBG2(DBG_CFG, " %sauth=%s", label, end->auth);
160 DBG2(DBG_CFG, " %sauth2=%s", label, end->auth2);
161 DBG2(DBG_CFG, " %sid=%s", label, end->id);
162 DBG2(DBG_CFG, " %sid2=%s", label, end->id2);
163 DBG2(DBG_CFG, " %srsakey=%s", label, end->rsakey);
164 DBG2(DBG_CFG, " %scert=%s", label, end->cert);
165 DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
166 DBG2(DBG_CFG, " %sca=%s", label, end->ca);
167 DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
168 DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
169 DBG2(DBG_CFG, " %sgroups2=%s", label, end->groups2);
170 DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
171 }
172
173 /**
174 * Add a connection to the configuration list
175 */
176 static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
177 {
178 pop_string(msg, &msg->add_conn.name);
179 DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
180
181 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
182 pop_end(msg, "left", &msg->add_conn.me);
183 pop_end(msg, "right", &msg->add_conn.other);
184 pop_string(msg, &msg->add_conn.eap_identity);
185 pop_string(msg, &msg->add_conn.aaa_identity);
186 pop_string(msg, &msg->add_conn.xauth_identity);
187 pop_string(msg, &msg->add_conn.algorithms.ike);
188 pop_string(msg, &msg->add_conn.algorithms.esp);
189 pop_string(msg, &msg->add_conn.algorithms.ah);
190 pop_string(msg, &msg->add_conn.ikeme.mediated_by);
191 pop_string(msg, &msg->add_conn.ikeme.peerid);
192 DBG2(DBG_CFG, " eap_identity=%s", msg->add_conn.eap_identity);
193 DBG2(DBG_CFG, " aaa_identity=%s", msg->add_conn.aaa_identity);
194 DBG2(DBG_CFG, " xauth_identity=%s", msg->add_conn.xauth_identity);
195 DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
196 DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
197 DBG2(DBG_CFG, " ah=%s", msg->add_conn.algorithms.ah);
198 DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay);
199 DBG2(DBG_CFG, " dpdtimeout=%d", msg->add_conn.dpd.timeout);
200 DBG2(DBG_CFG, " dpdaction=%d", msg->add_conn.dpd.action);
201 DBG2(DBG_CFG, " closeaction=%d", msg->add_conn.close_action);
202 DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
203 DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by);
204 DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid);
205 DBG2(DBG_CFG, " keyexchange=ikev%u", msg->add_conn.version);
206
207 this->config->add(this->config, msg);
208 this->attribute->add_dns(this->attribute, msg);
209 this->handler->add_attributes(this->handler, msg);
210 }
211
212 /**
213 * Delete a connection from the list
214 */
215 static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
216 {
217 pop_string(msg, &msg->del_conn.name);
218 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
219
220 this->config->del(this->config, msg);
221 this->attribute->del_dns(this->attribute, msg);
222 this->handler->del_attributes(this->handler, msg);
223 }
224
225 /**
226 * initiate a connection by name
227 */
228 static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
229 {
230 pop_string(msg, &msg->initiate.name);
231 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
232
233 this->control->initiate(this->control, msg, out);
234 }
235
236 /**
237 * terminate a connection by name
238 */
239 static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
240 {
241 pop_string(msg, &msg->terminate.name);
242 DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
243
244 this->control->terminate(this->control, msg, out);
245 }
246
247 /**
248 * terminate a connection by peers virtual IP
249 */
250 static void stroke_terminate_srcip(private_stroke_socket_t *this,
251 stroke_msg_t *msg, FILE *out)
252 {
253 pop_string(msg, &msg->terminate_srcip.start);
254 pop_string(msg, &msg->terminate_srcip.end);
255 DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s",
256 msg->terminate_srcip.start, msg->terminate_srcip.end);
257
258 this->control->terminate_srcip(this->control, msg, out);
259 }
260
261 /**
262 * rekey a connection by name/id
263 */
264 static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
265 {
266 pop_string(msg, &msg->terminate.name);
267 DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name);
268
269 this->control->rekey(this->control, msg, out);
270 }
271
272 /**
273 * route a policy (install SPD entries)
274 */
275 static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
276 {
277 pop_string(msg, &msg->route.name);
278 DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
279
280 this->control->route(this->control, msg, out);
281 }
282
283 /**
284 * unroute a policy
285 */
286 static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
287 {
288 pop_string(msg, &msg->terminate.name);
289 DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name);
290
291 this->control->unroute(this->control, msg, out);
292 }
293
294 /**
295 * Add a ca information record to the cainfo list
296 */
297 static void stroke_add_ca(private_stroke_socket_t *this,
298 stroke_msg_t *msg, FILE *out)
299 {
300 pop_string(msg, &msg->add_ca.name);
301 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
302
303 pop_string(msg, &msg->add_ca.cacert);
304 pop_string(msg, &msg->add_ca.crluri);
305 pop_string(msg, &msg->add_ca.crluri2);
306 pop_string(msg, &msg->add_ca.ocspuri);
307 pop_string(msg, &msg->add_ca.ocspuri2);
308 pop_string(msg, &msg->add_ca.certuribase);
309 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
310 DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
311 DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
312 DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
313 DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
314 DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
315 DBG2(DBG_CFG, " certuribase=%s", msg->add_ca.certuribase);
316
317 this->ca->add(this->ca, msg);
318 }
319
320 /**
321 * Delete a ca information record from the cainfo list
322 */
323 static void stroke_del_ca(private_stroke_socket_t *this,
324 stroke_msg_t *msg, FILE *out)
325 {
326 pop_string(msg, &msg->del_ca.name);
327 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
328
329 this->ca->del(this->ca, msg);
330 }
331
332
333 /**
334 * show status of daemon
335 */
336 static void stroke_status(private_stroke_socket_t *this,
337 stroke_msg_t *msg, FILE *out, bool all, bool wait)
338 {
339 pop_string(msg, &(msg->status.name));
340
341 this->list->status(this->list, msg, out, all, wait);
342 }
343
344 /**
345 * list various information
346 */
347 static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg,
348 FILE *out)
349 {
350 if (msg->list.flags & LIST_CAINFOS)
351 {
352 this->ca->list(this->ca, msg, out);
353 }
354 this->list->list(this->list, msg, out);
355 }
356
357 /**
358 * reread various information
359 */
360 static void stroke_reread(private_stroke_socket_t *this,
361 stroke_msg_t *msg, FILE *out)
362 {
363 this->cred->reread(this->cred, msg, out);
364 }
365
366 /**
367 * purge various information
368 */
369 static void stroke_purge(private_stroke_socket_t *this,
370 stroke_msg_t *msg, FILE *out)
371 {
372 if (msg->purge.flags & PURGE_OCSP)
373 {
374 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE);
375 }
376 if (msg->purge.flags & PURGE_CRLS)
377 {
378 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_CRL);
379 }
380 if (msg->purge.flags & PURGE_CERTS)
381 {
382 lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
383 }
384 if (msg->purge.flags & PURGE_IKE)
385 {
386 this->control->purge_ike(this->control, msg, out);
387 }
388 }
389
390 /**
391 * Print a certificate in PEM to out
392 */
393 static void print_pem_cert(FILE *out, certificate_t *cert)
394 {
395 chunk_t encoded;
396
397 if (cert->get_encoding(cert, CERT_PEM, &encoded))
398 {
399 fprintf(out, "%.*s", (int)encoded.len, encoded.ptr);
400 free(encoded.ptr);
401 }
402 }
403
404 /**
405 * Export in-memory credentials
406 */
407 static void stroke_export(private_stroke_socket_t *this,
408 stroke_msg_t *msg, FILE *out)
409 {
410 pop_string(msg, &msg->export.selector);
411
412 if (msg->export.flags & EXPORT_X509)
413 {
414 enumerator_t *enumerator;
415 identification_t *id;
416 certificate_t *cert;
417
418 id = identification_create_from_string(msg->export.selector);
419 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
420 CERT_X509, KEY_ANY, id, FALSE);
421 while (enumerator->enumerate(enumerator, &cert))
422 {
423 print_pem_cert(out, cert);
424 }
425 enumerator->destroy(enumerator);
426 id->destroy(id);
427 }
428
429 if (msg->export.flags & (EXPORT_CONN_CERT | EXPORT_CONN_CHAIN))
430 {
431 enumerator_t *sas, *auths, *certs;
432 ike_sa_t *ike_sa;
433 auth_cfg_t *auth;
434 certificate_t *cert;
435 auth_rule_t rule;
436
437 sas = charon->ike_sa_manager->create_enumerator(
438 charon->ike_sa_manager, TRUE);
439 while (sas->enumerate(sas, &ike_sa))
440 {
441 if (streq(msg->export.selector, ike_sa->get_name(ike_sa)))
442 {
443 auths = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
444 while (auths->enumerate(auths, &auth))
445 {
446 bool got_subject = FALSE;
447
448 certs = auth->create_enumerator(auth);
449 while (certs->enumerate(certs, &rule, &cert))
450 {
451 switch (rule)
452 {
453 case AUTH_RULE_CA_CERT:
454 case AUTH_RULE_IM_CERT:
455 if (msg->export.flags & EXPORT_CONN_CHAIN)
456 {
457 print_pem_cert(out, cert);
458 }
459 break;
460 case AUTH_RULE_SUBJECT_CERT:
461 if (!got_subject)
462 {
463 print_pem_cert(out, cert);
464 got_subject = TRUE;
465 }
466 break;
467 default:
468 break;
469 }
470 }
471 certs->destroy(certs);
472 }
473 auths->destroy(auths);
474 }
475 }
476 sas->destroy(sas);
477 }
478 }
479
480 /**
481 * list pool leases
482 */
483 static void stroke_leases(private_stroke_socket_t *this,
484 stroke_msg_t *msg, FILE *out)
485 {
486 pop_string(msg, &msg->leases.pool);
487 pop_string(msg, &msg->leases.address);
488
489 this->list->leases(this->list, msg, out);
490 }
491
492 /**
493 * Callback function for usage report
494 */
495 static void report_usage(FILE *out, int count, size_t bytes,
496 backtrace_t *bt, bool detailed)
497 {
498 fprintf(out, "%d bytes total, %d allocations, %d bytes average:\n",
499 bytes, count, bytes / count);
500 bt->log(bt, out, detailed);
501 }
502
503 /**
504 * Callback function for memusage summary
505 */
506 static void sum_usage(FILE *out, int count, size_t bytes, int whitelisted)
507 {
508 fprintf(out, "Total memory usage: %zu\n", bytes);
509 }
510
511 /**
512 * Show memory usage
513 */
514 static void stroke_memusage(private_stroke_socket_t *this,
515 stroke_msg_t *msg, FILE *out)
516 {
517 if (lib->leak_detective)
518 {
519 lib->leak_detective->usage(lib->leak_detective,
520 (leak_detective_report_cb_t)report_usage,
521 (leak_detective_summary_cb_t)sum_usage, out);
522 }
523 }
524
525 /**
526 * Set username and password for a connection
527 */
528 static void stroke_user_creds(private_stroke_socket_t *this,
529 stroke_msg_t *msg, FILE *out)
530 {
531 pop_string(msg, &msg->user_creds.name);
532 pop_string(msg, &msg->user_creds.username);
533 pop_string(msg, &msg->user_creds.password);
534
535 DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name);
536
537 this->config->set_user_credentials(this->config, msg, out);
538 }
539
540 /**
541 * Print stroke counter values
542 */
543 static void stroke_counters(private_stroke_socket_t *this,
544 stroke_msg_t *msg, FILE *out)
545 {
546 pop_string(msg, &msg->counters.name);
547
548 if (msg->counters.reset)
549 {
550 this->counter->reset(this->counter, msg->counters.name);
551 }
552 else
553 {
554 this->counter->print(this->counter, out, msg->counters.name);
555 }
556 }
557
558 /**
559 * set the verbosity debug output
560 */
561 static void stroke_loglevel(private_stroke_socket_t *this,
562 stroke_msg_t *msg, FILE *out)
563 {
564 debug_t group;
565
566 pop_string(msg, &(msg->loglevel.type));
567 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
568 msg->loglevel.level, msg->loglevel.type);
569
570 if (strcaseeq(msg->loglevel.type, "any"))
571 {
572 group = DBG_ANY;
573 }
574 else
575 {
576 group = enum_from_name(debug_names, msg->loglevel.type);
577 if ((int)group < 0)
578 {
579 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
580 return;
581 }
582 }
583 charon->set_level(charon, group, msg->loglevel.level);
584 }
585
586 /**
587 * set various config options
588 */
589 static void stroke_config(private_stroke_socket_t *this,
590 stroke_msg_t *msg, FILE *out)
591 {
592 this->cred->cachecrl(this->cred, msg->config.cachecrl);
593 }
594
595 /**
596 * process a stroke request
597 */
598 static bool on_accept(private_stroke_socket_t *this, stream_t *stream)
599 {
600 stroke_msg_t *msg;
601 u_int16_t len;
602 FILE *out;
603
604 /* read length */
605 if (!stream->read_all(stream, &len, sizeof(len)))
606 {
607 if (errno != EWOULDBLOCK)
608 {
609 DBG1(DBG_CFG, "reading length of stroke message failed: %s",
610 strerror(errno));
611 }
612 return FALSE;
613 }
614
615 /* read message */
616 msg = malloc(len);
617 msg->length = len;
618 if (!stream->read_all(stream, (char*)msg + sizeof(len), len - sizeof(len)))
619 {
620 if (errno != EWOULDBLOCK)
621 {
622 DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
623 }
624 free(msg);
625 return FALSE;
626 }
627
628 DBG3(DBG_CFG, "stroke message %b", (void*)msg, len);
629
630 out = stream->get_file(stream);
631 if (!out)
632 {
633 DBG1(DBG_CFG, "creating stroke output stream failed");
634 free(msg);
635 return FALSE;
636 }
637 switch (msg->type)
638 {
639 case STR_INITIATE:
640 stroke_initiate(this, msg, out);
641 break;
642 case STR_ROUTE:
643 stroke_route(this, msg, out);
644 break;
645 case STR_UNROUTE:
646 stroke_unroute(this, msg, out);
647 break;
648 case STR_TERMINATE:
649 stroke_terminate(this, msg, out);
650 break;
651 case STR_TERMINATE_SRCIP:
652 stroke_terminate_srcip(this, msg, out);
653 break;
654 case STR_REKEY:
655 stroke_rekey(this, msg, out);
656 break;
657 case STR_STATUS:
658 stroke_status(this, msg, out, FALSE, TRUE);
659 break;
660 case STR_STATUS_ALL:
661 stroke_status(this, msg, out, TRUE, TRUE);
662 break;
663 case STR_STATUS_ALL_NOBLK:
664 stroke_status(this, msg, out, TRUE, FALSE);
665 break;
666 case STR_ADD_CONN:
667 stroke_add_conn(this, msg);
668 break;
669 case STR_DEL_CONN:
670 stroke_del_conn(this, msg);
671 break;
672 case STR_ADD_CA:
673 stroke_add_ca(this, msg, out);
674 break;
675 case STR_DEL_CA:
676 stroke_del_ca(this, msg, out);
677 break;
678 case STR_LOGLEVEL:
679 stroke_loglevel(this, msg, out);
680 break;
681 case STR_CONFIG:
682 stroke_config(this, msg, out);
683 break;
684 case STR_LIST:
685 stroke_list(this, msg, out);
686 break;
687 case STR_REREAD:
688 stroke_reread(this, msg, out);
689 break;
690 case STR_PURGE:
691 stroke_purge(this, msg, out);
692 break;
693 case STR_EXPORT:
694 stroke_export(this, msg, out);
695 break;
696 case STR_LEASES:
697 stroke_leases(this, msg, out);
698 break;
699 case STR_MEMUSAGE:
700 stroke_memusage(this, msg, out);
701 break;
702 case STR_USER_CREDS:
703 stroke_user_creds(this, msg, out);
704 break;
705 case STR_COUNTERS:
706 stroke_counters(this, msg, out);
707 break;
708 default:
709 DBG1(DBG_CFG, "received unknown stroke");
710 break;
711 }
712 free(msg);
713 fclose(out);
714 return FALSE;
715 }
716
717 METHOD(stroke_socket_t, destroy, void,
718 private_stroke_socket_t *this)
719 {
720 DESTROY_IF(this->service);
721 lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
722 lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
723 charon->backends->remove_backend(charon->backends, &this->config->backend);
724 hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
725 hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
726 charon->bus->remove_listener(charon->bus, &this->counter->listener);
727 this->cred->destroy(this->cred);
728 this->ca->destroy(this->ca);
729 this->config->destroy(this->config);
730 this->attribute->destroy(this->attribute);
731 this->handler->destroy(this->handler);
732 this->control->destroy(this->control);
733 this->list->destroy(this->list);
734 this->counter->destroy(this->counter);
735 free(this);
736 }
737
738 /*
739 * see header file
740 */
741 stroke_socket_t *stroke_socket_create()
742 {
743 private_stroke_socket_t *this;
744 int max_concurrent;
745 char *uri;
746
747 INIT(this,
748 .public = {
749 .destroy = _destroy,
750 },
751 );
752
753 this->cred = stroke_cred_create();
754 this->attribute = stroke_attribute_create();
755 this->handler = stroke_handler_create();
756 this->ca = stroke_ca_create(this->cred);
757 this->config = stroke_config_create(this->ca, this->cred, this->attribute);
758 this->control = stroke_control_create();
759 this->list = stroke_list_create(this->attribute);
760 this->counter = stroke_counter_create();
761
762 lib->credmgr->add_set(lib->credmgr, &this->ca->set);
763 lib->credmgr->add_set(lib->credmgr, &this->cred->set);
764 charon->backends->add_backend(charon->backends, &this->config->backend);
765 hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
766 hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
767 charon->bus->add_listener(charon->bus, &this->counter->listener);
768
769 max_concurrent = lib->settings->get_int(lib->settings,
770 "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT,
771 charon->name);
772 uri = lib->settings->get_str(lib->settings,
773 "%s.plugins.stroke.socket", "unix://" STROKE_SOCKET, charon->name);
774 this->service = lib->streams->create_service(lib->streams, uri, 10);
775 if (!this->service)
776 {
777 DBG1(DBG_CFG, "creating stroke socket failed");
778 destroy(this);
779 return NULL;
780 }
781 this->service->on_accept(this->service, (stream_service_cb_t)on_accept,
782 this, JOB_PRIO_CRITICAL, max_concurrent);
783
784 return &this->public;
785 }