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