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