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