7a14be0cf51d31add7af00a03b39c152033b24b5
[strongswan.git] / src / libcharon / plugins / stroke / stroke_socket.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * 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 "stroke_socket.h"
17
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <unistd.h>
24 #include <errno.h>
25
26 #include <hydra.h>
27 #include <daemon.h>
28 #include <threading/thread.h>
29 #include <processing/jobs/callback_job.h>
30
31 #include "stroke_config.h"
32 #include "stroke_control.h"
33 #include "stroke_cred.h"
34 #include "stroke_ca.h"
35 #include "stroke_attribute.h"
36 #include "stroke_list.h"
37
38 typedef struct stroke_job_context_t stroke_job_context_t;
39 typedef struct private_stroke_socket_t private_stroke_socket_t;
40
41 /**
42 * private data of stroke_socket
43 */
44 struct private_stroke_socket_t {
45
46 /**
47 * public functions
48 */
49 stroke_socket_t public;
50
51 /**
52 * Unix socket to listen for strokes
53 */
54 int socket;
55
56 /**
57 * job accepting stroke messages
58 */
59 callback_job_t *job;
60
61 /**
62 * configuration backend
63 */
64 stroke_config_t *config;
65
66 /**
67 * attribute provider
68 */
69 stroke_attribute_t *attribute;
70
71 /**
72 * controller to control daemon
73 */
74 stroke_control_t *control;
75
76 /**
77 * credential set
78 */
79 stroke_cred_t *cred;
80
81 /**
82 * CA sections
83 */
84 stroke_ca_t *ca;
85
86 /**
87 * Status information logging
88 */
89 stroke_list_t *list;
90 };
91
92 /**
93 * job context to pass to processing thread
94 */
95 struct stroke_job_context_t {
96
97 /**
98 * file descriptor to read from
99 */
100 int fd;
101
102 /**
103 * global stroke interface
104 */
105 private_stroke_socket_t *this;
106 };
107
108 /**
109 * Helper function which corrects the string pointers
110 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
111 * contains RELATIVE addresses (relative to the beginning of the
112 * stroke_msg). They must be corrected if they reach our address
113 * space...
114 */
115 static void pop_string(stroke_msg_t *msg, char **string)
116 {
117 if (*string == NULL)
118 {
119 return;
120 }
121
122 /* check for sanity of string pointer and string */
123 if (string < (char**)msg ||
124 string > (char**)((char*)msg + sizeof(stroke_msg_t)) ||
125 (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) ||
126 (unsigned long)*string > msg->length)
127 {
128 *string = "(invalid pointer in stroke msg)";
129 }
130 else
131 {
132 *string = (char*)msg + (unsigned long)*string;
133 }
134 }
135
136 /**
137 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
138 */
139 static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
140 {
141 pop_string(msg, &end->address);
142 pop_string(msg, &end->subnets);
143 pop_string(msg, &end->sourceip);
144 pop_string(msg, &end->auth);
145 pop_string(msg, &end->auth2);
146 pop_string(msg, &end->id);
147 pop_string(msg, &end->id2);
148 pop_string(msg, &end->cert);
149 pop_string(msg, &end->cert2);
150 pop_string(msg, &end->ca);
151 pop_string(msg, &end->ca2);
152 pop_string(msg, &end->groups);
153 pop_string(msg, &end->cert_policy);
154 pop_string(msg, &end->updown);
155
156 DBG2(DBG_CFG, " %s=%s", label, end->address);
157 DBG2(DBG_CFG, " %ssubnet=%s", label, end->subnets);
158 DBG2(DBG_CFG, " %ssourceip=%s", label, end->sourceip);
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, " %scert=%s", label, end->cert);
164 DBG2(DBG_CFG, " %scert2=%s", label, end->cert2);
165 DBG2(DBG_CFG, " %sca=%s", label, end->ca);
166 DBG2(DBG_CFG, " %sca2=%s", label, end->ca2);
167 DBG2(DBG_CFG, " %sgroups=%s", label, end->groups);
168 DBG2(DBG_CFG, " %supdown=%s", label, end->updown);
169 }
170
171 /**
172 * Add a connection to the configuration list
173 */
174 static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
175 {
176 pop_string(msg, &msg->add_conn.name);
177 DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
178
179 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
180 pop_end(msg, "left", &msg->add_conn.me);
181 pop_end(msg, "right", &msg->add_conn.other);
182 pop_string(msg, &msg->add_conn.eap_identity);
183 pop_string(msg, &msg->add_conn.aaa_identity);
184 pop_string(msg, &msg->add_conn.xauth_identity);
185 pop_string(msg, &msg->add_conn.algorithms.ike);
186 pop_string(msg, &msg->add_conn.algorithms.esp);
187 pop_string(msg, &msg->add_conn.ikeme.mediated_by);
188 pop_string(msg, &msg->add_conn.ikeme.peerid);
189 DBG2(DBG_CFG, " eap_identity=%s", msg->add_conn.eap_identity);
190 DBG2(DBG_CFG, " aaa_identity=%s", msg->add_conn.aaa_identity);
191 DBG2(DBG_CFG, " xauth_identity=%s", msg->add_conn.xauth_identity);
192 DBG2(DBG_CFG, " ike=%s", msg->add_conn.algorithms.ike);
193 DBG2(DBG_CFG, " esp=%s", msg->add_conn.algorithms.esp);
194 DBG2(DBG_CFG, " dpddelay=%d", msg->add_conn.dpd.delay);
195 DBG2(DBG_CFG, " dpdaction=%d", msg->add_conn.dpd.action);
196 DBG2(DBG_CFG, " closeaction=%d", msg->add_conn.close_action);
197 DBG2(DBG_CFG, " mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
198 DBG2(DBG_CFG, " mediated_by=%s", msg->add_conn.ikeme.mediated_by);
199 DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid);
200 DBG2(DBG_CFG, " keyexchange=%s", msg->add_conn.ikev2 ? "ikev2" : "ikev1");
201
202 this->config->add(this->config, msg);
203 this->attribute->add_pool(this->attribute, msg);
204 }
205
206 /**
207 * Delete a connection from the list
208 */
209 static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
210 {
211 pop_string(msg, &msg->del_conn.name);
212 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
213
214 this->config->del(this->config, msg);
215 this->attribute->del_pool(this->attribute, msg);
216 }
217
218 /**
219 * initiate a connection by name
220 */
221 static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
222 {
223 pop_string(msg, &msg->initiate.name);
224 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
225
226 this->control->initiate(this->control, msg, out);
227 }
228
229 /**
230 * terminate a connection by name
231 */
232 static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
233 {
234 pop_string(msg, &msg->terminate.name);
235 DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
236
237 this->control->terminate(this->control, msg, out);
238 }
239
240 /**
241 * terminate a connection by peers virtual IP
242 */
243 static void stroke_terminate_srcip(private_stroke_socket_t *this,
244 stroke_msg_t *msg, FILE *out)
245 {
246 pop_string(msg, &msg->terminate_srcip.start);
247 pop_string(msg, &msg->terminate_srcip.end);
248 DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s",
249 msg->terminate_srcip.start, msg->terminate_srcip.end);
250
251 this->control->terminate_srcip(this->control, msg, out);
252 }
253
254 /**
255 * rekey a connection by name/id
256 */
257 static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
258 {
259 pop_string(msg, &msg->terminate.name);
260 DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name);
261
262 this->control->rekey(this->control, msg, out);
263 }
264
265 /**
266 * route a policy (install SPD entries)
267 */
268 static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
269 {
270 pop_string(msg, &msg->route.name);
271 DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
272
273 this->control->route(this->control, msg, out);
274 }
275
276 /**
277 * unroute a policy
278 */
279 static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
280 {
281 pop_string(msg, &msg->terminate.name);
282 DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name);
283
284 this->control->unroute(this->control, msg, out);
285 }
286
287 /**
288 * Add a ca information record to the cainfo list
289 */
290 static void stroke_add_ca(private_stroke_socket_t *this,
291 stroke_msg_t *msg, FILE *out)
292 {
293 pop_string(msg, &msg->add_ca.name);
294 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
295
296 pop_string(msg, &msg->add_ca.cacert);
297 pop_string(msg, &msg->add_ca.crluri);
298 pop_string(msg, &msg->add_ca.crluri2);
299 pop_string(msg, &msg->add_ca.ocspuri);
300 pop_string(msg, &msg->add_ca.ocspuri2);
301 pop_string(msg, &msg->add_ca.certuribase);
302 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
303 DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert);
304 DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri);
305 DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2);
306 DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri);
307 DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2);
308 DBG2(DBG_CFG, " certuribase=%s", msg->add_ca.certuribase);
309
310 this->ca->add(this->ca, msg);
311 }
312
313 /**
314 * Delete a ca information record from the cainfo list
315 */
316 static void stroke_del_ca(private_stroke_socket_t *this,
317 stroke_msg_t *msg, FILE *out)
318 {
319 pop_string(msg, &msg->del_ca.name);
320 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
321
322 this->ca->del(this->ca, msg);
323 }
324
325
326 /**
327 * show status of daemon
328 */
329 static void stroke_status(private_stroke_socket_t *this,
330 stroke_msg_t *msg, FILE *out, bool all, bool wait)
331 {
332 pop_string(msg, &(msg->status.name));
333
334 this->list->status(this->list, msg, out, all, wait);
335 }
336
337 /**
338 * list various information
339 */
340 static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
341 {
342 if (msg->list.flags & LIST_CAINFOS)
343 {
344 this->ca->list(this->ca, msg, out);
345 }
346 this->list->list(this->list, msg, out);
347 }
348
349 /**
350 * reread various information
351 */
352 static void stroke_reread(private_stroke_socket_t *this,
353 stroke_msg_t *msg, FILE *out)
354 {
355 this->cred->reread(this->cred, msg, out);
356 }
357
358 /**
359 * purge various information
360 */
361 static void stroke_purge(private_stroke_socket_t *this,
362 stroke_msg_t *msg, FILE *out)
363 {
364 if (msg->purge.flags & PURGE_OCSP)
365 {
366 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE);
367 }
368 if (msg->purge.flags & PURGE_CRLS)
369 {
370 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_CRL);
371 }
372 if (msg->purge.flags & PURGE_CERTS)
373 {
374 lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
375 }
376 if (msg->purge.flags & PURGE_IKE)
377 {
378 this->control->purge_ike(this->control, msg, out);
379 }
380 }
381
382 /**
383 * Export in-memory credentials
384 */
385 static void stroke_export(private_stroke_socket_t *this,
386 stroke_msg_t *msg, FILE *out)
387 {
388 pop_string(msg, &msg->export.selector);
389
390 if (msg->purge.flags & EXPORT_X509)
391 {
392 enumerator_t *enumerator;
393 identification_t *id;
394 certificate_t *cert;
395 chunk_t encoded;
396
397 id = identification_create_from_string(msg->export.selector);
398 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
399 CERT_X509, KEY_ANY, id, FALSE);
400 while (enumerator->enumerate(enumerator, &cert))
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 enumerator->destroy(enumerator);
409 id->destroy(id);
410 }
411 }
412
413 /**
414 * list pool leases
415 */
416 static void stroke_leases(private_stroke_socket_t *this,
417 stroke_msg_t *msg, FILE *out)
418 {
419 pop_string(msg, &msg->leases.pool);
420 pop_string(msg, &msg->leases.address);
421
422 this->list->leases(this->list, msg, out);
423 }
424
425 /**
426 * Show memory usage
427 */
428 static void stroke_memusage(private_stroke_socket_t *this,
429 stroke_msg_t *msg, FILE *out)
430 {
431 if (lib->leak_detective)
432 {
433 lib->leak_detective->usage(lib->leak_detective, out);
434 }
435 }
436
437 /**
438 * set the verbosity debug output
439 */
440 static void stroke_loglevel(private_stroke_socket_t *this,
441 stroke_msg_t *msg, FILE *out)
442 {
443 enumerator_t *enumerator;
444 sys_logger_t *sys_logger;
445 file_logger_t *file_logger;
446 debug_t group;
447
448 pop_string(msg, &(msg->loglevel.type));
449 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
450 msg->loglevel.level, msg->loglevel.type);
451
452 group = enum_from_name(debug_names, msg->loglevel.type);
453 if (group < 0)
454 {
455 fprintf(out, "invalid type (%s)!\n", msg->loglevel.type);
456 return;
457 }
458 /* we set the loglevel on ALL sys- and file-loggers */
459 enumerator = charon->sys_loggers->create_enumerator(charon->sys_loggers);
460 while (enumerator->enumerate(enumerator, &sys_logger))
461 {
462 sys_logger->set_level(sys_logger, group, msg->loglevel.level);
463 }
464 enumerator->destroy(enumerator);
465 enumerator = charon->file_loggers->create_enumerator(charon->file_loggers);
466 while (enumerator->enumerate(enumerator, &file_logger))
467 {
468 file_logger->set_level(file_logger, group, msg->loglevel.level);
469 }
470 enumerator->destroy(enumerator);
471 }
472
473 /**
474 * set various config options
475 */
476 static void stroke_config(private_stroke_socket_t *this,
477 stroke_msg_t *msg, FILE *out)
478 {
479 this->cred->cachecrl(this->cred, msg->config.cachecrl);
480 }
481
482 /**
483 * destroy a job context
484 */
485 static void stroke_job_context_destroy(stroke_job_context_t *this)
486 {
487 if (this->fd)
488 {
489 close(this->fd);
490 }
491 free(this);
492 }
493
494 /**
495 * process a stroke request from the socket pointed by "fd"
496 */
497 static job_requeue_t process(stroke_job_context_t *ctx)
498 {
499 stroke_msg_t *msg;
500 u_int16_t msg_length;
501 ssize_t bytes_read;
502 FILE *out;
503 private_stroke_socket_t *this = ctx->this;
504 int strokefd = ctx->fd;
505
506 /* peek the length */
507 bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
508 if (bytes_read != sizeof(msg_length))
509 {
510 DBG1(DBG_CFG, "reading length of stroke message failed: %s",
511 strerror(errno));
512 return JOB_REQUEUE_NONE;
513 }
514
515 /* read message */
516 msg = alloca(msg_length);
517 bytes_read = recv(strokefd, msg, msg_length, 0);
518 if (bytes_read != msg_length)
519 {
520 DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
521 return JOB_REQUEUE_NONE;
522 }
523
524 out = fdopen(strokefd, "w+");
525 if (out == NULL)
526 {
527 DBG1(DBG_CFG, "opening stroke output channel failed: %s", strerror(errno));
528 return JOB_REQUEUE_NONE;
529 }
530
531 DBG3(DBG_CFG, "stroke message %b", (void*)msg, msg_length);
532
533 switch (msg->type)
534 {
535 case STR_INITIATE:
536 stroke_initiate(this, msg, out);
537 break;
538 case STR_ROUTE:
539 stroke_route(this, msg, out);
540 break;
541 case STR_UNROUTE:
542 stroke_unroute(this, msg, out);
543 break;
544 case STR_TERMINATE:
545 stroke_terminate(this, msg, out);
546 break;
547 case STR_TERMINATE_SRCIP:
548 stroke_terminate_srcip(this, msg, out);
549 break;
550 case STR_REKEY:
551 stroke_rekey(this, msg, out);
552 break;
553 case STR_STATUS:
554 stroke_status(this, msg, out, FALSE, TRUE);
555 break;
556 case STR_STATUS_ALL:
557 stroke_status(this, msg, out, TRUE, TRUE);
558 break;
559 case STR_STATUS_ALL_NOBLK:
560 stroke_status(this, msg, out, TRUE, FALSE);
561 break;
562 case STR_ADD_CONN:
563 stroke_add_conn(this, msg);
564 break;
565 case STR_DEL_CONN:
566 stroke_del_conn(this, msg);
567 break;
568 case STR_ADD_CA:
569 stroke_add_ca(this, msg, out);
570 break;
571 case STR_DEL_CA:
572 stroke_del_ca(this, msg, out);
573 break;
574 case STR_LOGLEVEL:
575 stroke_loglevel(this, msg, out);
576 break;
577 case STR_CONFIG:
578 stroke_config(this, msg, out);
579 break;
580 case STR_LIST:
581 stroke_list(this, msg, out);
582 break;
583 case STR_REREAD:
584 stroke_reread(this, msg, out);
585 break;
586 case STR_PURGE:
587 stroke_purge(this, msg, out);
588 break;
589 case STR_EXPORT:
590 stroke_export(this, msg, out);
591 break;
592 case STR_LEASES:
593 stroke_leases(this, msg, out);
594 break;
595 case STR_MEMUSAGE:
596 stroke_memusage(this, msg, out);
597 break;
598 default:
599 DBG1(DBG_CFG, "received unknown stroke");
600 break;
601 }
602 fclose(out);
603 /* fclose() closes underlying FD */
604 ctx->fd = 0;
605 return JOB_REQUEUE_NONE;
606 }
607
608 /**
609 * Implementation of private_stroke_socket_t.stroke_receive.
610 */
611 static job_requeue_t receive(private_stroke_socket_t *this)
612 {
613 struct sockaddr_un strokeaddr;
614 int strokeaddrlen = sizeof(strokeaddr);
615 int strokefd;
616 bool oldstate;
617 callback_job_t *job;
618 stroke_job_context_t *ctx;
619
620 oldstate = thread_cancelability(TRUE);
621 strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
622 thread_cancelability(oldstate);
623
624 if (strokefd < 0)
625 {
626 DBG1(DBG_CFG, "accepting stroke connection failed: %s", strerror(errno));
627 return JOB_REQUEUE_FAIR;
628 }
629
630 ctx = malloc_thing(stroke_job_context_t);
631 ctx->fd = strokefd;
632 ctx->this = this;
633 job = callback_job_create_with_prio((callback_job_cb_t)process,
634 ctx, (void*)stroke_job_context_destroy, this->job, JOB_PRIO_HIGH);
635 lib->processor->queue_job(lib->processor, (job_t*)job);
636
637 return JOB_REQUEUE_FAIR;
638 }
639
640
641 /**
642 * initialize and open stroke socket
643 */
644 static bool open_socket(private_stroke_socket_t *this)
645 {
646 struct sockaddr_un socket_addr;
647 mode_t old;
648
649 socket_addr.sun_family = AF_UNIX;
650 strcpy(socket_addr.sun_path, STROKE_SOCKET);
651
652 /* set up unix socket */
653 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
654 if (this->socket == -1)
655 {
656 DBG1(DBG_CFG, "could not create stroke socket");
657 return FALSE;
658 }
659
660 unlink(socket_addr.sun_path);
661 old = umask(~(S_IRWXU | S_IRWXG));
662 if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
663 {
664 DBG1(DBG_CFG, "could not bind stroke socket: %s", strerror(errno));
665 close(this->socket);
666 return FALSE;
667 }
668 umask(old);
669 if (chown(socket_addr.sun_path, charon->uid, charon->gid) != 0)
670 {
671 DBG1(DBG_CFG, "changing stroke socket permissions failed: %s",
672 strerror(errno));
673 }
674
675 if (listen(this->socket, 10) < 0)
676 {
677 DBG1(DBG_CFG, "could not listen on stroke socket: %s", strerror(errno));
678 close(this->socket);
679 unlink(socket_addr.sun_path);
680 return FALSE;
681 }
682 return TRUE;
683 }
684
685 METHOD(stroke_socket_t, destroy, void,
686 private_stroke_socket_t *this)
687 {
688 this->job->cancel(this->job);
689 lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
690 lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
691 charon->backends->remove_backend(charon->backends, &this->config->backend);
692 hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
693 this->cred->destroy(this->cred);
694 this->ca->destroy(this->ca);
695 this->config->destroy(this->config);
696 this->attribute->destroy(this->attribute);
697 this->control->destroy(this->control);
698 this->list->destroy(this->list);
699 free(this);
700 }
701
702 /*
703 * see header file
704 */
705 stroke_socket_t *stroke_socket_create()
706 {
707 private_stroke_socket_t *this;
708
709 INIT(this,
710 .public = {
711 .destroy = _destroy,
712 },
713 );
714
715 if (!open_socket(this))
716 {
717 free(this);
718 return NULL;
719 }
720
721 this->cred = stroke_cred_create();
722 this->attribute = stroke_attribute_create();
723 this->ca = stroke_ca_create(this->cred);
724 this->config = stroke_config_create(this->ca, this->cred);
725 this->control = stroke_control_create();
726 this->list = stroke_list_create(this->attribute);
727
728 lib->credmgr->add_set(lib->credmgr, &this->ca->set);
729 lib->credmgr->add_set(lib->credmgr, &this->cred->set);
730 charon->backends->add_backend(charon->backends, &this->config->backend);
731 hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
732
733 this->job = callback_job_create_with_prio((callback_job_cb_t)receive,
734 this, NULL, NULL, JOB_PRIO_CRITICAL);
735 lib->processor->queue_job(lib->processor, (job_t*)this->job);
736
737 return &this->public;
738 }
739