]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/stroke/stroke_socket.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / plugins / stroke / stroke_socket.c
CommitLineData
0b14fdb9 1/*
5ab03863 2 * Copyright (C) 2011-2013 Tobias Brunner
0b14fdb9 3 * Copyright (C) 2008 Martin Willi
19ef2aec
TB
4 *
5 * Copyright (C) secunet Security Networks AG
0b14fdb9
MW
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
0b14fdb9
MW
16 */
17
18#include "stroke_socket.h"
19
20#include <stdlib.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <sys/socket.h>
24#include <sys/un.h>
0b14fdb9
MW
25#include <unistd.h>
26#include <errno.h>
27
0b14fdb9
MW
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"
ad81e51a 34#include "stroke_attribute.h"
63e46054 35#include "stroke_handler.h"
0b14fdb9 36#include "stroke_list.h"
8554895b 37#include "stroke_counter.h"
0b14fdb9 38
8ff513a8
TB
39/**
40 * To avoid clogging the thread pool with (blocking) jobs, we limit the number
41 * of concurrently handled stroke commands.
42 */
7c0c2349 43#define MAX_CONCURRENT_DEFAULT 4
8ff513a8 44
0b14fdb9
MW
45typedef struct stroke_job_context_t stroke_job_context_t;
46typedef struct private_stroke_socket_t private_stroke_socket_t;
47
48/**
49 * private data of stroke_socket
50 */
51struct private_stroke_socket_t {
52
53 /**
54 * public functions
55 */
56 stroke_socket_t public;
7daf5226 57
0b14fdb9 58 /**
065907b9 59 * Service accepting stroke connections
0b14fdb9 60 */
065907b9 61 stream_service_t *service;
7c0c2349 62
0b14fdb9
MW
63 /**
64 * configuration backend
65 */
66 stroke_config_t *config;
7daf5226 67
ad81e51a
MW
68 /**
69 * attribute provider
70 */
71 stroke_attribute_t *attribute;
7daf5226 72
63e46054
MW
73 /**
74 * attribute handler (requests only)
75 */
76 stroke_handler_t *handler;
77
0b14fdb9
MW
78 /**
79 * controller to control daemon
80 */
81 stroke_control_t *control;
7daf5226 82
0b14fdb9
MW
83 /**
84 * credential set
85 */
86 stroke_cred_t *cred;
7daf5226 87
0b14fdb9
MW
88 /**
89 * CA sections
90 */
91 stroke_ca_t *ca;
7daf5226 92
0b14fdb9 93 /**
8ff513a8 94 * status information logging
0b14fdb9
MW
95 */
96 stroke_list_t *list;
8554895b
MW
97
98 /**
99 * Counter values for IKE events
100 */
101 stroke_counter_t *counter;
5ab03863
TB
102
103 /**
104 * TRUE if log level changes are not allowed
105 */
106 bool prevent_loglevel_changes;
0b14fdb9
MW
107};
108
28a79e4e
TB
109/**
110 * Helper macro to log configuration options, but only if they are defined.
111 */
112#define DBG_OPT(...) VA_ARGS_DISPATCH(DBG_OPT, __VA_ARGS__)(__VA_ARGS__)
113#define DBG_OPT2(fmt, val) ({ \
114 typeof(val) _val = val; \
115 if (_val) { DBG2(DBG_CFG, fmt, _val); } \
116})
117#define DBG_OPT3(fmt, label, val) ({ \
118 typeof(val) _val = val; \
119 if (_val) { DBG2(DBG_CFG, fmt, label, _val); } \
120})
121
0b14fdb9
MW
122/**
123 * Helper function which corrects the string pointers
124 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
125 * contains RELATIVE addresses (relative to the beginning of the
126 * stroke_msg). They must be corrected if they reach our address
127 * space...
128 */
129static void pop_string(stroke_msg_t *msg, char **string)
130{
131 if (*string == NULL)
132 {
133 return;
134 }
135
136 /* check for sanity of string pointer and string */
137 if (string < (char**)msg ||
aee071ed 138 string > (char**)((char*)msg + sizeof(stroke_msg_t)) ||
0b14fdb9
MW
139 (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) ||
140 (unsigned long)*string > msg->length)
141 {
142 *string = "(invalid pointer in stroke msg)";
143 }
144 else
145 {
146 *string = (char*)msg + (unsigned long)*string;
147 }
148}
149
150/**
151 * Pop the strings of a stroke_end_t struct and log them for debugging purposes
152 */
153static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
154{
155 pop_string(msg, &end->address);
34443902 156 pop_string(msg, &end->subnets);
0b14fdb9 157 pop_string(msg, &end->sourceip);
17319aa2 158 pop_string(msg, &end->dns);
a44bb934
MW
159 pop_string(msg, &end->auth);
160 pop_string(msg, &end->auth2);
0b14fdb9 161 pop_string(msg, &end->id);
a44bb934 162 pop_string(msg, &end->id2);
5f1931ad 163 pop_string(msg, &end->rsakey);
0b14fdb9 164 pop_string(msg, &end->cert);
a44bb934 165 pop_string(msg, &end->cert2);
0b14fdb9 166 pop_string(msg, &end->ca);
a44bb934 167 pop_string(msg, &end->ca2);
0b14fdb9 168 pop_string(msg, &end->groups);
46df61df 169 pop_string(msg, &end->groups2);
6367de28 170 pop_string(msg, &end->cert_policy);
0b14fdb9 171 pop_string(msg, &end->updown);
7daf5226 172
28a79e4e
TB
173 DBG_OPT(" %s=%s", label, end->address);
174 DBG_OPT(" %ssubnet=%s", label, end->subnets);
175 DBG_OPT(" %ssourceip=%s", label, end->sourceip);
176 DBG_OPT(" %sdns=%s", label, end->dns);
177 DBG_OPT(" %sauth=%s", label, end->auth);
178 DBG_OPT(" %sauth2=%s", label, end->auth2);
179 DBG_OPT(" %sid=%s", label, end->id);
180 DBG_OPT(" %sid2=%s", label, end->id2);
181 DBG_OPT(" %srsakey=%s", label, end->rsakey);
182 DBG_OPT(" %scert=%s", label, end->cert);
183 DBG_OPT(" %scert2=%s", label, end->cert2);
184 DBG_OPT(" %sca=%s", label, end->ca);
185 DBG_OPT(" %sca2=%s", label, end->ca2);
186 DBG_OPT(" %sgroups=%s", label, end->groups);
187 DBG_OPT(" %sgroups2=%s", label, end->groups2);
188 DBG_OPT(" %supdown=%s", label, end->updown);
0b14fdb9
MW
189}
190
191/**
192 * Add a connection to the configuration list
193 */
194static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
195{
196 pop_string(msg, &msg->add_conn.name);
197 DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
7c8eff1e 198
0b14fdb9
MW
199 DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
200 pop_end(msg, "left", &msg->add_conn.me);
201 pop_end(msg, "right", &msg->add_conn.other);
82290106 202 pop_string(msg, &msg->add_conn.eap_identity);
64d7b073 203 pop_string(msg, &msg->add_conn.aaa_identity);
21a4fc83 204 pop_string(msg, &msg->add_conn.xauth_identity);
0b14fdb9
MW
205 pop_string(msg, &msg->add_conn.algorithms.ike);
206 pop_string(msg, &msg->add_conn.algorithms.esp);
05764129 207 pop_string(msg, &msg->add_conn.algorithms.ah);
dc04b7c7
TB
208 pop_string(msg, &msg->add_conn.ikeme.mediated_by);
209 pop_string(msg, &msg->add_conn.ikeme.peerid);
28a79e4e
TB
210 DBG_OPT(" eap_identity=%s", msg->add_conn.eap_identity);
211 DBG_OPT(" aaa_identity=%s", msg->add_conn.aaa_identity);
212 DBG_OPT(" xauth_identity=%s", msg->add_conn.xauth_identity);
213 DBG_OPT(" ike=%s", msg->add_conn.algorithms.ike);
214 DBG_OPT(" esp=%s", msg->add_conn.algorithms.esp);
215 DBG_OPT(" ah=%s", msg->add_conn.algorithms.ah);
216 DBG_OPT(" dpddelay=%d", msg->add_conn.dpd.delay);
217 DBG_OPT(" dpdtimeout=%d", msg->add_conn.dpd.timeout);
218 DBG_OPT(" dpdaction=%d", msg->add_conn.dpd.action);
219 DBG_OPT(" closeaction=%d", msg->add_conn.close_action);
4270c8fc 220 DBG_OPT(" sha256_96=%s", msg->add_conn.sha256_96 ? "yes" : "no");
28a79e4e
TB
221 DBG_OPT(" mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
222 DBG_OPT(" mediated_by=%s", msg->add_conn.ikeme.mediated_by);
223 DBG_OPT(" me_peerid=%s", msg->add_conn.ikeme.peerid);
224 DBG_OPT(" keyexchange=ikev%u", msg->add_conn.version);
0b14fdb9
MW
225
226 this->config->add(this->config, msg);
96c2b3cf 227 this->attribute->add_dns(this->attribute, msg);
63e46054 228 this->handler->add_attributes(this->handler, msg);
0b14fdb9
MW
229}
230
231/**
232 * Delete a connection from the list
233 */
234static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
235{
236 pop_string(msg, &msg->del_conn.name);
237 DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
7daf5226 238
0b14fdb9 239 this->config->del(this->config, msg);
96c2b3cf 240 this->attribute->del_dns(this->attribute, msg);
63e46054 241 this->handler->del_attributes(this->handler, msg);
0b14fdb9
MW
242}
243
244/**
245 * initiate a connection by name
246 */
247static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
248{
249 pop_string(msg, &msg->initiate.name);
250 DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
7daf5226 251
0b14fdb9
MW
252 this->control->initiate(this->control, msg, out);
253}
254
255/**
256 * terminate a connection by name
257 */
258static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
259{
260 pop_string(msg, &msg->terminate.name);
261 DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
262
263 this->control->terminate(this->control, msg, out);
7daf5226 264}
13106499
MW
265
266/**
267 * terminate a connection by peers virtual IP
268 */
269static void stroke_terminate_srcip(private_stroke_socket_t *this,
270 stroke_msg_t *msg, FILE *out)
271{
272 pop_string(msg, &msg->terminate_srcip.start);
273 pop_string(msg, &msg->terminate_srcip.end);
274 DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s",
275 msg->terminate_srcip.start, msg->terminate_srcip.end);
276
277 this->control->terminate_srcip(this->control, msg, out);
0b14fdb9
MW
278}
279
851d6048
MW
280/**
281 * rekey a connection by name/id
282 */
283static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
284{
285 pop_string(msg, &msg->terminate.name);
286 DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name);
287
288 this->control->rekey(this->control, msg, out);
289}
290
0b14fdb9
MW
291/**
292 * route a policy (install SPD entries)
293 */
294static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
295{
296 pop_string(msg, &msg->route.name);
297 DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
7daf5226 298
0b14fdb9
MW
299 this->control->route(this->control, msg, out);
300}
301
302/**
303 * unroute a policy
304 */
305static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
306{
307 pop_string(msg, &msg->terminate.name);
308 DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name);
7daf5226 309
0b14fdb9
MW
310 this->control->unroute(this->control, msg, out);
311}
312
313/**
314 * Add a ca information record to the cainfo list
315 */
316static void stroke_add_ca(private_stroke_socket_t *this,
317 stroke_msg_t *msg, FILE *out)
318{
319 pop_string(msg, &msg->add_ca.name);
7c8eff1e
AS
320 DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
321
0b14fdb9
MW
322 pop_string(msg, &msg->add_ca.cacert);
323 pop_string(msg, &msg->add_ca.crluri);
324 pop_string(msg, &msg->add_ca.crluri2);
325 pop_string(msg, &msg->add_ca.ocspuri);
326 pop_string(msg, &msg->add_ca.ocspuri2);
6439267a 327 pop_string(msg, &msg->add_ca.certuribase);
28a79e4e
TB
328 DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
329 DBG_OPT(" cacert=%s", msg->add_ca.cacert);
330 DBG_OPT(" crluri=%s", msg->add_ca.crluri);
331 DBG_OPT(" crluri2=%s", msg->add_ca.crluri2);
332 DBG_OPT(" ocspuri=%s", msg->add_ca.ocspuri);
333 DBG_OPT(" ocspuri2=%s", msg->add_ca.ocspuri2);
334 DBG_OPT(" certuribase=%s", msg->add_ca.certuribase);
7daf5226 335
0b14fdb9
MW
336 this->ca->add(this->ca, msg);
337}
338
339/**
340 * Delete a ca information record from the cainfo list
341 */
342static void stroke_del_ca(private_stroke_socket_t *this,
343 stroke_msg_t *msg, FILE *out)
344{
345 pop_string(msg, &msg->del_ca.name);
346 DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
7daf5226 347
0b14fdb9
MW
348 this->ca->del(this->ca, msg);
349}
350
351
352/**
353 * show status of daemon
354 */
f957f7df 355static void stroke_status(private_stroke_socket_t *this,
a694b481 356 stroke_msg_t *msg, FILE *out, bool all, bool wait)
0b14fdb9
MW
357{
358 pop_string(msg, &(msg->status.name));
7daf5226 359
a694b481 360 this->list->status(this->list, msg, out, all, wait);
0b14fdb9
MW
361}
362
363/**
364 * list various information
365 */
d022322b
MW
366static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg,
367 FILE *out)
0b14fdb9
MW
368{
369 if (msg->list.flags & LIST_CAINFOS)
370 {
371 this->ca->list(this->ca, msg, out);
372 }
373 this->list->list(this->list, msg, out);
374}
375
376/**
377 * reread various information
378 */
379static void stroke_reread(private_stroke_socket_t *this,
380 stroke_msg_t *msg, FILE *out)
381{
750bbcf9 382 this->cred->reread(this->cred, msg, out);
0b14fdb9
MW
383}
384
385/**
386 * purge various information
387 */
f957f7df
MW
388static void stroke_purge(private_stroke_socket_t *this,
389 stroke_msg_t *msg, FILE *out)
0b14fdb9 390{
83242706
MW
391 if (msg->purge.flags & PURGE_OCSP)
392 {
2ccc02a4 393 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE);
83242706 394 }
cf5866b9 395 if (msg->purge.flags & PURGE_CRLS)
6aa144dd
MW
396 {
397 lib->credmgr->flush_cache(lib->credmgr, CERT_X509_CRL);
398 }
cf5866b9 399 if (msg->purge.flags & PURGE_CERTS)
6aa144dd
MW
400 {
401 lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
402 }
83242706
MW
403 if (msg->purge.flags & PURGE_IKE)
404 {
405 this->control->purge_ike(this->control, msg, out);
406 }
0b14fdb9
MW
407}
408
de2debf8
MW
409/**
410 * Print a certificate in PEM to out
411 */
412static void print_pem_cert(FILE *out, certificate_t *cert)
413{
414 chunk_t encoded;
415
416 if (cert->get_encoding(cert, CERT_PEM, &encoded))
417 {
418 fprintf(out, "%.*s", (int)encoded.len, encoded.ptr);
419 free(encoded.ptr);
420 }
421}
422
3d711a68
MW
423/**
424 * Export in-memory credentials
425 */
426static void stroke_export(private_stroke_socket_t *this,
427 stroke_msg_t *msg, FILE *out)
428{
429 pop_string(msg, &msg->export.selector);
430
4c31657d 431 if (msg->export.flags & EXPORT_X509)
3d711a68
MW
432 {
433 enumerator_t *enumerator;
434 identification_t *id;
435 certificate_t *cert;
3d711a68
MW
436
437 id = identification_create_from_string(msg->export.selector);
438 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
439 CERT_X509, KEY_ANY, id, FALSE);
440 while (enumerator->enumerate(enumerator, &cert))
441 {
de2debf8 442 print_pem_cert(out, cert);
3d711a68
MW
443 }
444 enumerator->destroy(enumerator);
445 id->destroy(id);
446 }
de2debf8
MW
447
448 if (msg->export.flags & (EXPORT_CONN_CERT | EXPORT_CONN_CHAIN))
449 {
450 enumerator_t *sas, *auths, *certs;
451 ike_sa_t *ike_sa;
452 auth_cfg_t *auth;
453 certificate_t *cert;
454 auth_rule_t rule;
455
456 sas = charon->ike_sa_manager->create_enumerator(
457 charon->ike_sa_manager, TRUE);
458 while (sas->enumerate(sas, &ike_sa))
459 {
460 if (streq(msg->export.selector, ike_sa->get_name(ike_sa)))
461 {
462 auths = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
463 while (auths->enumerate(auths, &auth))
464 {
465 bool got_subject = FALSE;
466
467 certs = auth->create_enumerator(auth);
468 while (certs->enumerate(certs, &rule, &cert))
469 {
470 switch (rule)
471 {
472 case AUTH_RULE_CA_CERT:
473 case AUTH_RULE_IM_CERT:
474 if (msg->export.flags & EXPORT_CONN_CHAIN)
475 {
476 print_pem_cert(out, cert);
477 }
478 break;
479 case AUTH_RULE_SUBJECT_CERT:
480 if (!got_subject)
481 {
482 print_pem_cert(out, cert);
483 got_subject = TRUE;
484 }
485 break;
486 default:
487 break;
488 }
489 }
490 certs->destroy(certs);
491 }
492 auths->destroy(auths);
493 }
494 }
495 sas->destroy(sas);
496 }
3d711a68
MW
497}
498
6b83549d
MW
499/**
500 * list pool leases
501 */
502static void stroke_leases(private_stroke_socket_t *this,
503 stroke_msg_t *msg, FILE *out)
504{
505 pop_string(msg, &msg->leases.pool);
506 pop_string(msg, &msg->leases.address);
7daf5226 507
6b83549d
MW
508 this->list->leases(this->list, msg, out);
509}
510
a426851f
MW
511/**
512 * Callback function for usage report
513 */
514static void report_usage(FILE *out, int count, size_t bytes,
515 backtrace_t *bt, bool detailed)
516{
5a040562 517 fprintf(out, "%zu bytes total, %d allocations, %zu bytes average:\n",
a426851f
MW
518 bytes, count, bytes / count);
519 bt->log(bt, out, detailed);
520}
521
522/**
523 * Callback function for memusage summary
524 */
525static void sum_usage(FILE *out, int count, size_t bytes, int whitelisted)
526{
527 fprintf(out, "Total memory usage: %zu\n", bytes);
528}
529
dfe9bad9
MW
530/**
531 * Show memory usage
532 */
533static void stroke_memusage(private_stroke_socket_t *this,
534 stroke_msg_t *msg, FILE *out)
535{
536 if (lib->leak_detective)
537 {
a426851f
MW
538 lib->leak_detective->usage(lib->leak_detective,
539 (leak_detective_report_cb_t)report_usage,
540 (leak_detective_summary_cb_t)sum_usage, out);
dfe9bad9
MW
541 }
542}
543
9f1b303a
TB
544/**
545 * Set username and password for a connection
546 */
547static void stroke_user_creds(private_stroke_socket_t *this,
548 stroke_msg_t *msg, FILE *out)
549{
550 pop_string(msg, &msg->user_creds.name);
551 pop_string(msg, &msg->user_creds.username);
552 pop_string(msg, &msg->user_creds.password);
553
554 DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name);
555
556 this->config->set_user_credentials(this->config, msg, out);
557}
558
d022322b
MW
559/**
560 * Print stroke counter values
561 */
562static void stroke_counters(private_stroke_socket_t *this,
563 stroke_msg_t *msg, FILE *out)
564{
565 pop_string(msg, &msg->counters.name);
566
cf729248
MW
567 if (msg->counters.reset)
568 {
569 this->counter->reset(this->counter, msg->counters.name);
570 }
571 else
572 {
573 this->counter->print(this->counter, out, msg->counters.name);
574 }
d022322b
MW
575}
576
0b14fdb9
MW
577/**
578 * set the verbosity debug output
579 */
a985db3f
MW
580static void stroke_loglevel(private_stroke_socket_t *this,
581 stroke_msg_t *msg, FILE *out)
0b14fdb9 582{
a985db3f 583 debug_t group;
7daf5226 584
0b14fdb9
MW
585 pop_string(msg, &(msg->loglevel.type));
586 DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
587 msg->loglevel.level, msg->loglevel.type);
7daf5226 588
5ab03863
TB
589 if (this->prevent_loglevel_changes)
590 {
591 DBG1(DBG_CFG, "prevented log level change");
592 fprintf(out, "command not allowed!\n");
593 return;
594 }
10c5981d 595 if (!enum_from_name(debug_names, msg->loglevel.type, &group))
0b14fdb9 596 {
10c5981d
TB
597 fprintf(out, "unknown type '%s'!\n", msg->loglevel.type);
598 return;
0b14fdb9 599 }
3555baca 600 charon->set_level(charon, group, msg->loglevel.level);
0b14fdb9
MW
601}
602
b360e393
MW
603/**
604 * set various config options
605 */
a985db3f
MW
606static void stroke_config(private_stroke_socket_t *this,
607 stroke_msg_t *msg, FILE *out)
b360e393
MW
608{
609 this->cred->cachecrl(this->cred, msg->config.cachecrl);
610}
0b14fdb9
MW
611
612/**
065907b9 613 * process a stroke request
0b14fdb9 614 */
065907b9 615static bool on_accept(private_stroke_socket_t *this, stream_t *stream)
0b14fdb9
MW
616{
617 stroke_msg_t *msg;
b12c53ce 618 uint16_t len;
0b14fdb9 619 FILE *out;
7daf5226 620
065907b9
MW
621 /* read length */
622 if (!stream->read_all(stream, &len, sizeof(len)))
0b14fdb9 623 {
065907b9
MW
624 if (errno != EWOULDBLOCK)
625 {
626 DBG1(DBG_CFG, "reading length of stroke message failed: %s",
627 strerror(errno));
628 }
629 return FALSE;
0b14fdb9 630 }
0acd1ab4
TB
631 if (len < offsetof(stroke_msg_t, buffer))
632 {
633 DBG1(DBG_CFG, "invalid stroke message length %d", len);
634 return FALSE;
635 }
7daf5226 636
f44b1eb4
TB
637 /* read message (we need an additional byte to terminate the buffer) */
638 msg = malloc(len + 1);
065907b9
MW
639 msg->length = len;
640 if (!stream->read_all(stream, (char*)msg + sizeof(len), len - sizeof(len)))
0b14fdb9 641 {
065907b9
MW
642 if (errno != EWOULDBLOCK)
643 {
644 DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
645 }
646 free(msg);
647 return FALSE;
0b14fdb9 648 }
f44b1eb4
TB
649 /* make sure even incorrectly unterminated strings don't extend over the
650 * message boundaries */
651 ((char*)msg)[len] = '\0';
7daf5226 652
065907b9
MW
653 DBG3(DBG_CFG, "stroke message %b", (void*)msg, len);
654
655 out = stream->get_file(stream);
656 if (!out)
0b14fdb9 657 {
065907b9
MW
658 DBG1(DBG_CFG, "creating stroke output stream failed");
659 free(msg);
660 return FALSE;
0b14fdb9 661 }
0b14fdb9
MW
662 switch (msg->type)
663 {
664 case STR_INITIATE:
665 stroke_initiate(this, msg, out);
666 break;
667 case STR_ROUTE:
668 stroke_route(this, msg, out);
669 break;
670 case STR_UNROUTE:
671 stroke_unroute(this, msg, out);
672 break;
673 case STR_TERMINATE:
674 stroke_terminate(this, msg, out);
675 break;
13106499
MW
676 case STR_TERMINATE_SRCIP:
677 stroke_terminate_srcip(this, msg, out);
678 break;
851d6048
MW
679 case STR_REKEY:
680 stroke_rekey(this, msg, out);
681 break;
0b14fdb9 682 case STR_STATUS:
a694b481 683 stroke_status(this, msg, out, FALSE, TRUE);
0b14fdb9
MW
684 break;
685 case STR_STATUS_ALL:
a694b481
MW
686 stroke_status(this, msg, out, TRUE, TRUE);
687 break;
688 case STR_STATUS_ALL_NOBLK:
689 stroke_status(this, msg, out, TRUE, FALSE);
0b14fdb9
MW
690 break;
691 case STR_ADD_CONN:
692 stroke_add_conn(this, msg);
693 break;
694 case STR_DEL_CONN:
695 stroke_del_conn(this, msg);
696 break;
697 case STR_ADD_CA:
698 stroke_add_ca(this, msg, out);
699 break;
700 case STR_DEL_CA:
701 stroke_del_ca(this, msg, out);
702 break;
703 case STR_LOGLEVEL:
704 stroke_loglevel(this, msg, out);
705 break;
b360e393
MW
706 case STR_CONFIG:
707 stroke_config(this, msg, out);
708 break;
0b14fdb9
MW
709 case STR_LIST:
710 stroke_list(this, msg, out);
711 break;
712 case STR_REREAD:
713 stroke_reread(this, msg, out);
714 break;
715 case STR_PURGE:
716 stroke_purge(this, msg, out);
717 break;
3d711a68
MW
718 case STR_EXPORT:
719 stroke_export(this, msg, out);
720 break;
6b83549d
MW
721 case STR_LEASES:
722 stroke_leases(this, msg, out);
723 break;
dfe9bad9
MW
724 case STR_MEMUSAGE:
725 stroke_memusage(this, msg, out);
726 break;
9f1b303a
TB
727 case STR_USER_CREDS:
728 stroke_user_creds(this, msg, out);
729 break;
d022322b
MW
730 case STR_COUNTERS:
731 stroke_counters(this, msg, out);
cf729248 732 break;
0b14fdb9
MW
733 default:
734 DBG1(DBG_CFG, "received unknown stroke");
857ba357 735 break;
0b14fdb9 736 }
065907b9 737 free(msg);
857ba357 738 fclose(out);
065907b9 739 return FALSE;
0b14fdb9
MW
740}
741
0d430d4f
TB
742METHOD(stroke_socket_t, destroy, void,
743 private_stroke_socket_t *this)
0b14fdb9 744{
065907b9 745 DESTROY_IF(this->service);
2ccc02a4
MW
746 lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
747 lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
0b14fdb9 748 charon->backends->remove_backend(charon->backends, &this->config->backend);
75136327
MW
749 charon->attributes->remove_provider(charon->attributes,
750 &this->attribute->provider);
751 charon->attributes->remove_handler(charon->attributes,
752 &this->handler->handler);
0b14fdb9
MW
753 this->cred->destroy(this->cred);
754 this->ca->destroy(this->ca);
755 this->config->destroy(this->config);
ad81e51a 756 this->attribute->destroy(this->attribute);
63e46054 757 this->handler->destroy(this->handler);
0b14fdb9
MW
758 this->control->destroy(this->control);
759 this->list->destroy(this->list);
8554895b 760 this->counter->destroy(this->counter);
0b14fdb9
MW
761 free(this);
762}
763
764/*
765 * see header file
766 */
767stroke_socket_t *stroke_socket_create()
768{
0d430d4f 769 private_stroke_socket_t *this;
065907b9
MW
770 int max_concurrent;
771 char *uri;
7daf5226 772
0d430d4f
TB
773 INIT(this,
774 .public = {
775 .destroy = _destroy,
776 },
5ab03863 777 .prevent_loglevel_changes = lib->settings->get_bool(lib->settings,
d223fe80 778 "%s.plugins.stroke.prevent_loglevel_changes", FALSE, lib->ns),
0d430d4f 779 );
7daf5226 780
517cc501
TB
781 this->ca = stroke_ca_create();
782 this->cred = stroke_cred_create(this->ca);
ad81e51a 783 this->attribute = stroke_attribute_create();
63e46054 784 this->handler = stroke_handler_create();
96c2b3cf 785 this->config = stroke_config_create(this->ca, this->cred, this->attribute);
0b14fdb9 786 this->control = stroke_control_create();
2e031965 787 this->list = stroke_list_create(this->attribute);
8554895b 788 this->counter = stroke_counter_create();
7daf5226 789
2ccc02a4
MW
790 lib->credmgr->add_set(lib->credmgr, &this->ca->set);
791 lib->credmgr->add_set(lib->credmgr, &this->cred->set);
0b14fdb9 792 charon->backends->add_backend(charon->backends, &this->config->backend);
75136327
MW
793 charon->attributes->add_provider(charon->attributes,
794 &this->attribute->provider);
795 charon->attributes->add_handler(charon->attributes,
796 &this->handler->handler);
6f74b874 797
7daf5226 798
065907b9 799 max_concurrent = lib->settings->get_int(lib->settings,
d223fe80
TB
800 "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT,
801 lib->ns);
065907b9 802 uri = lib->settings->get_str(lib->settings,
d223fe80 803 "%s.plugins.stroke.socket", "unix://" STROKE_SOCKET, lib->ns);
065907b9
MW
804 this->service = lib->streams->create_service(lib->streams, uri, 10);
805 if (!this->service)
806 {
807 DBG1(DBG_CFG, "creating stroke socket failed");
808 destroy(this);
809 return NULL;
810 }
811 this->service->on_accept(this->service, (stream_service_cb_t)on_accept,
812 this, JOB_PRIO_CRITICAL, max_concurrent);
7daf5226 813
0b14fdb9
MW
814 return &this->public;
815}