stroke: Configure proposal with AH protocol if 'ah' option set
[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 * Show memory usage
494 */
495 static void stroke_memusage(private_stroke_socket_t *this,
496 stroke_msg_t *msg, FILE *out)
497 {
498 if (lib->leak_detective)
499 {
500 lib->leak_detective->usage(lib->leak_detective, out);
501 }
502 }
503
504 /**
505 * Set username and password for a connection
506 */
507 static void stroke_user_creds(private_stroke_socket_t *this,
508 stroke_msg_t *msg, FILE *out)
509 {
510 pop_string(msg, &msg->user_creds.name);
511 pop_string(msg, &msg->user_creds.username);
512 pop_string(msg, &msg->user_creds.password);
513
514 DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name);
515
516 this->config->set_user_credentials(this->config, msg, out);
517 }
518
519 /**
520 * Print stroke counter values
521 */
522 static void stroke_counters(private_stroke_socket_t *this,
523 stroke_msg_t *msg, FILE *out)
524 {
525 pop_string(msg, &msg->counters.name);
526
527 if (msg->counters.reset)
528 {
529 this->counter->reset(this->counter, msg->counters.name);
530 }
531 else
532 {
533 this->counter->print(this->counter, out, msg->counters.name);
534 }
535 }
536
537 /**
538 * set the verbosity debug output
539 */
540 static void stroke_loglevel(private_stroke_socket_t *this,
541 stroke_msg_t *msg, FILE *out)
542 {
543 debug_t group;
544
545 pop_string(msg, &(msg->loglevel.type));
546 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
547 msg->loglevel.level, msg->loglevel.type);
548
549 if (strcaseeq(msg->loglevel.type, "any"))
550 {
551 group = DBG_ANY;
552 }
553 else
554 {
555 group = enum_from_name(debug_names, msg->loglevel.type);
556 if ((int)group < 0)
557 {
558 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
559 return;
560 }
561 }
562 charon->set_level(charon, group, msg->loglevel.level);
563 }
564
565 /**
566 * set various config options
567 */
568 static void stroke_config(private_stroke_socket_t *this,
569 stroke_msg_t *msg, FILE *out)
570 {
571 this->cred->cachecrl(this->cred, msg->config.cachecrl);
572 }
573
574 /**
575 * process a stroke request
576 */
577 static bool on_accept(private_stroke_socket_t *this, stream_t *stream)
578 {
579 stroke_msg_t *msg;
580 u_int16_t len;
581 FILE *out;
582
583 /* read length */
584 if (!stream->read_all(stream, &len, sizeof(len)))
585 {
586 if (errno != EWOULDBLOCK)
587 {
588 DBG1(DBG_CFG, "reading length of stroke message failed: %s",
589 strerror(errno));
590 }
591 return FALSE;
592 }
593
594 /* read message */
595 msg = malloc(len);
596 msg->length = len;
597 if (!stream->read_all(stream, (char*)msg + sizeof(len), len - sizeof(len)))
598 {
599 if (errno != EWOULDBLOCK)
600 {
601 DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
602 }
603 free(msg);
604 return FALSE;
605 }
606
607 DBG3(DBG_CFG, "stroke message %b", (void*)msg, len);
608
609 out = stream->get_file(stream);
610 if (!out)
611 {
612 DBG1(DBG_CFG, "creating stroke output stream failed");
613 free(msg);
614 return FALSE;
615 }
616 switch (msg->type)
617 {
618 case STR_INITIATE:
619 stroke_initiate(this, msg, out);
620 break;
621 case STR_ROUTE:
622 stroke_route(this, msg, out);
623 break;
624 case STR_UNROUTE:
625 stroke_unroute(this, msg, out);
626 break;
627 case STR_TERMINATE:
628 stroke_terminate(this, msg, out);
629 break;
630 case STR_TERMINATE_SRCIP:
631 stroke_terminate_srcip(this, msg, out);
632 break;
633 case STR_REKEY:
634 stroke_rekey(this, msg, out);
635 break;
636 case STR_STATUS:
637 stroke_status(this, msg, out, FALSE, TRUE);
638 break;
639 case STR_STATUS_ALL:
640 stroke_status(this, msg, out, TRUE, TRUE);
641 break;
642 case STR_STATUS_ALL_NOBLK:
643 stroke_status(this, msg, out, TRUE, FALSE);
644 break;
645 case STR_ADD_CONN:
646 stroke_add_conn(this, msg);
647 break;
648 case STR_DEL_CONN:
649 stroke_del_conn(this, msg);
650 break;
651 case STR_ADD_CA:
652 stroke_add_ca(this, msg, out);
653 break;
654 case STR_DEL_CA:
655 stroke_del_ca(this, msg, out);
656 break;
657 case STR_LOGLEVEL:
658 stroke_loglevel(this, msg, out);
659 break;
660 case STR_CONFIG:
661 stroke_config(this, msg, out);
662 break;
663 case STR_LIST:
664 stroke_list(this, msg, out);
665 break;
666 case STR_REREAD:
667 stroke_reread(this, msg, out);
668 break;
669 case STR_PURGE:
670 stroke_purge(this, msg, out);
671 break;
672 case STR_EXPORT:
673 stroke_export(this, msg, out);
674 break;
675 case STR_LEASES:
676 stroke_leases(this, msg, out);
677 break;
678 case STR_MEMUSAGE:
679 stroke_memusage(this, msg, out);
680 break;
681 case STR_USER_CREDS:
682 stroke_user_creds(this, msg, out);
683 break;
684 case STR_COUNTERS:
685 stroke_counters(this, msg, out);
686 break;
687 default:
688 DBG1(DBG_CFG, "received unknown stroke");
689 break;
690 }
691 free(msg);
692 fclose(out);
693 return FALSE;
694 }
695
696 METHOD(stroke_socket_t, destroy, void,
697 private_stroke_socket_t *this)
698 {
699 DESTROY_IF(this->service);
700 lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
701 lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
702 charon->backends->remove_backend(charon->backends, &this->config->backend);
703 hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
704 hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
705 charon->bus->remove_listener(charon->bus, &this->counter->listener);
706 this->cred->destroy(this->cred);
707 this->ca->destroy(this->ca);
708 this->config->destroy(this->config);
709 this->attribute->destroy(this->attribute);
710 this->handler->destroy(this->handler);
711 this->control->destroy(this->control);
712 this->list->destroy(this->list);
713 this->counter->destroy(this->counter);
714 free(this);
715 }
716
717 /*
718 * see header file
719 */
720 stroke_socket_t *stroke_socket_create()
721 {
722 private_stroke_socket_t *this;
723 int max_concurrent;
724 char *uri;
725
726 INIT(this,
727 .public = {
728 .destroy = _destroy,
729 },
730 );
731
732 this->cred = stroke_cred_create();
733 this->attribute = stroke_attribute_create();
734 this->handler = stroke_handler_create();
735 this->ca = stroke_ca_create(this->cred);
736 this->config = stroke_config_create(this->ca, this->cred, this->attribute);
737 this->control = stroke_control_create();
738 this->list = stroke_list_create(this->attribute);
739 this->counter = stroke_counter_create();
740
741 lib->credmgr->add_set(lib->credmgr, &this->ca->set);
742 lib->credmgr->add_set(lib->credmgr, &this->cred->set);
743 charon->backends->add_backend(charon->backends, &this->config->backend);
744 hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
745 hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
746 charon->bus->add_listener(charon->bus, &this->counter->listener);
747
748 max_concurrent = lib->settings->get_int(lib->settings,
749 "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT,
750 charon->name);
751 uri = lib->settings->get_str(lib->settings,
752 "%s.plugins.stroke.socket", "unix://" STROKE_SOCKET, charon->name);
753 this->service = lib->streams->create_service(lib->streams, uri, 10);
754 if (!this->service)
755 {
756 DBG1(DBG_CFG, "creating stroke socket failed");
757 destroy(this);
758 return NULL;
759 }
760 this->service->on_accept(this->service, (stream_service_cb_t)on_accept,
761 this, JOB_PRIO_CRITICAL, max_concurrent);
762
763 return &this->public;
764 }