Refactored certificate management for the vici and stroke interfaces
[strongswan.git] / src / libcharon / plugins / stroke / stroke_list.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2015 Andreas Steffen
6 * HSR Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "stroke_list.h"
20
21 #include <inttypes.h>
22 #include <time.h>
23 #include <sys/utsname.h>
24
25 #ifdef HAVE_MALLINFO
26 #include <malloc.h>
27 #endif /* HAVE_MALLINFO */
28
29 #include <hydra.h>
30 #include <daemon.h>
31 #include <collections/linked_list.h>
32 #include <plugins/plugin.h>
33 #include <credentials/certificates/x509.h>
34 #include <credentials/certificates/certificate_printer.h>
35 #include <config/peer_cfg.h>
36
37 typedef struct private_stroke_list_t private_stroke_list_t;
38
39 /**
40 * private data of stroke_list
41 */
42 struct private_stroke_list_t {
43
44 /**
45 * public functions
46 */
47 stroke_list_t public;
48
49 /**
50 * Kind of *swan we run
51 */
52 char *swan;
53
54 /**
55 * timestamp of daemon start
56 */
57 time_t uptime;
58
59 /**
60 * strokes attribute provider
61 */
62 stroke_attribute_t *attribute;
63 };
64
65 /**
66 * Static certificate printer object
67 */
68 static certificate_printer_t *cert_printer = NULL;
69
70 /**
71 * Log tasks of a specific queue to out
72 */
73 static void log_task_q(FILE *out, ike_sa_t *ike_sa, task_queue_t q, char *name)
74 {
75 enumerator_t *enumerator;
76 bool has = FALSE;
77 task_t *task;
78
79 enumerator = ike_sa->create_task_enumerator(ike_sa, q);
80 while (enumerator->enumerate(enumerator, &task))
81 {
82 if (!has)
83 {
84 fprintf(out, "%12s[%d]: Tasks %s: ", ike_sa->get_name(ike_sa),
85 ike_sa->get_unique_id(ike_sa), name);
86 has = TRUE;
87 }
88 fprintf(out, "%N ", task_type_names, task->get_type(task));
89 }
90 enumerator->destroy(enumerator);
91 if (has)
92 {
93 fprintf(out, "\n");
94 }
95 }
96
97 /**
98 * log an IKE_SA to out
99 */
100 static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
101 {
102 ike_sa_id_t *id = ike_sa->get_id(ike_sa);
103 time_t now = time_monotonic(NULL);
104
105 fprintf(out, "%12s[%d]: %N",
106 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
107 ike_sa_state_names, ike_sa->get_state(ike_sa));
108
109 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
110 {
111 time_t established;
112
113 established = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
114 fprintf(out, " %V ago", &now, &established);
115 }
116
117 fprintf(out, ", %H[%Y]...%H[%Y]\n",
118 ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
119 ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
120
121 if (all)
122 {
123 proposal_t *ike_proposal;
124 identification_t *eap_id;
125
126 eap_id = ike_sa->get_other_eap_id(ike_sa);
127
128 if (!eap_id->equals(eap_id, ike_sa->get_other_id(ike_sa)))
129 {
130 fprintf(out, "%12s[%d]: Remote %s identity: %Y\n",
131 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
132 ike_sa->get_version(ike_sa) == IKEV1 ? "XAuth" : "EAP",
133 eap_id);
134 }
135
136 ike_proposal = ike_sa->get_proposal(ike_sa);
137
138 fprintf(out, "%12s[%d]: %N SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
139 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
140 ike_version_names, ike_sa->get_version(ike_sa),
141 id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
142 id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
143
144
145 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
146 {
147 time_t rekey, reauth;
148 peer_cfg_t *peer_cfg;
149
150 rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY);
151 reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
152 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
153
154 if (rekey)
155 {
156 fprintf(out, ", rekeying in %V", &rekey, &now);
157 }
158 if (reauth)
159 {
160 bool first = TRUE;
161 enumerator_t *enumerator;
162 auth_cfg_t *auth;
163
164 fprintf(out, ", ");
165 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, TRUE);
166 while (enumerator->enumerate(enumerator, &auth))
167 {
168 if (!first)
169 {
170 fprintf(out, "+");
171 }
172 first = FALSE;
173 fprintf(out, "%N", auth_class_names,
174 auth->get(auth, AUTH_RULE_AUTH_CLASS));
175 }
176 enumerator->destroy(enumerator);
177 fprintf(out, " reauthentication in %V", &reauth, &now);
178 }
179 if (!rekey && !reauth)
180 {
181 fprintf(out, ", rekeying disabled");
182 }
183 }
184 fprintf(out, "\n");
185
186 if (ike_proposal)
187 {
188 char buf[BUF_LEN];
189
190 snprintf(buf, BUF_LEN, "%P", ike_proposal);
191 fprintf(out, "%12s[%d]: IKE proposal: %s\n",
192 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
193 buf+4);
194 }
195
196 log_task_q(out, ike_sa, TASK_QUEUE_QUEUED, "queued");
197 log_task_q(out, ike_sa, TASK_QUEUE_ACTIVE, "active");
198 log_task_q(out, ike_sa, TASK_QUEUE_PASSIVE, "passive");
199 }
200 }
201
202 /**
203 * log an CHILD_SA to out
204 */
205 static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
206 {
207 time_t use_in, use_out, rekey, now;
208 u_int64_t bytes_in, bytes_out, packets_in, packets_out;
209 proposal_t *proposal;
210 linked_list_t *my_ts, *other_ts;
211 child_cfg_t *config;
212
213 config = child_sa->get_config(child_sa);
214 now = time_monotonic(NULL);
215
216 fprintf(out, "%12s{%d}: %N, %N%s, reqid %u",
217 child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
218 child_sa_state_names, child_sa->get_state(child_sa),
219 ipsec_mode_names, child_sa->get_mode(child_sa),
220 config->use_proxy_mode(config) ? "_PROXY" : "",
221 child_sa->get_reqid(child_sa));
222
223 if (child_sa->get_state(child_sa) == CHILD_INSTALLED)
224 {
225 fprintf(out, ", %N%s SPIs: %.8x_i %.8x_o",
226 protocol_id_names, child_sa->get_protocol(child_sa),
227 child_sa->has_encap(child_sa) ? " in UDP" : "",
228 ntohl(child_sa->get_spi(child_sa, TRUE)),
229 ntohl(child_sa->get_spi(child_sa, FALSE)));
230
231 if (child_sa->get_ipcomp(child_sa) != IPCOMP_NONE)
232 {
233 fprintf(out, ", IPCOMP CPIs: %.4x_i %.4x_o",
234 ntohs(child_sa->get_cpi(child_sa, TRUE)),
235 ntohs(child_sa->get_cpi(child_sa, FALSE)));
236 }
237
238 if (all)
239 {
240 fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa),
241 child_sa->get_unique_id(child_sa));
242
243 proposal = child_sa->get_proposal(child_sa);
244 if (proposal)
245 {
246 u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED;
247 u_int16_t encr_size = 0, int_size = 0;
248 u_int16_t esn = NO_EXT_SEQ_NUMBERS;
249 bool first = TRUE;
250
251 proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
252 &encr_alg, &encr_size);
253 proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
254 &int_alg, &int_size);
255 proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
256 &esn, NULL);
257
258 if (encr_alg != ENCR_UNDEFINED)
259 {
260 fprintf(out, "%N", encryption_algorithm_names, encr_alg);
261 first = FALSE;
262 if (encr_size)
263 {
264 fprintf(out, "_%u", encr_size);
265 }
266 }
267 if (int_alg != AUTH_UNDEFINED)
268 {
269 if (!first)
270 {
271 fprintf(out, "/");
272 }
273 fprintf(out, "%N", integrity_algorithm_names, int_alg);
274 if (int_size)
275 {
276 fprintf(out, "_%u", int_size);
277 }
278 }
279 if (esn == EXT_SEQ_NUMBERS)
280 {
281 fprintf(out, "/ESN");
282 }
283 }
284
285 child_sa->get_usestats(child_sa, TRUE,
286 &use_in, &bytes_in, &packets_in);
287 fprintf(out, ", %" PRIu64 " bytes_i", bytes_in);
288 if (use_in)
289 {
290 fprintf(out, " (%" PRIu64 " pkt%s, %" PRIu64 "s ago)",
291 packets_in, (packets_in == 1) ? "": "s",
292 (u_int64_t)(now - use_in));
293 }
294
295 child_sa->get_usestats(child_sa, FALSE,
296 &use_out, &bytes_out, &packets_out);
297 fprintf(out, ", %" PRIu64 " bytes_o", bytes_out);
298 if (use_out)
299 {
300 fprintf(out, " (%" PRIu64 " pkt%s, %" PRIu64 "s ago)",
301 packets_out, (packets_out == 1) ? "": "s",
302 (u_int64_t)(now - use_out));
303 }
304 fprintf(out, ", rekeying ");
305
306 rekey = child_sa->get_lifetime(child_sa, FALSE);
307 if (rekey)
308 {
309 if (now > rekey)
310 {
311 fprintf(out, "active");
312 }
313 else
314 {
315 fprintf(out, "in %V", &now, &rekey);
316 }
317 }
318 else
319 {
320 fprintf(out, "disabled");
321 }
322
323 }
324 }
325 else if (child_sa->get_state(child_sa) == CHILD_REKEYING ||
326 child_sa->get_state(child_sa) == CHILD_REKEYED)
327 {
328 rekey = child_sa->get_lifetime(child_sa, TRUE);
329 fprintf(out, ", expires in %V", &now, &rekey);
330 }
331
332 my_ts = linked_list_create_from_enumerator(
333 child_sa->create_ts_enumerator(child_sa, TRUE));
334 other_ts = linked_list_create_from_enumerator(
335 child_sa->create_ts_enumerator(child_sa, FALSE));
336 fprintf(out, "\n%12s{%d}: %#R === %#R\n",
337 child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
338 my_ts, other_ts);
339 my_ts->destroy(my_ts);
340 other_ts->destroy(other_ts);
341 }
342
343 /**
344 * Log a configs local or remote authentication config to out
345 */
346 static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
347 {
348 enumerator_t *enumerator, *rules;
349 auth_rule_t rule;
350 auth_cfg_t *auth;
351 auth_class_t auth_class;
352 identification_t *id;
353 certificate_t *cert;
354 cert_validation_t valid;
355 char *name;
356
357 name = peer_cfg->get_name(peer_cfg);
358
359 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
360 while (enumerator->enumerate(enumerator, &auth))
361 {
362 fprintf(out, "%12s: %s", name, local ? "local: " : "remote:");
363 id = auth->get(auth, AUTH_RULE_IDENTITY);
364 if (id)
365 {
366 fprintf(out, " [%Y]", id);
367 }
368 fprintf(out, " uses ");
369
370 auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
371 if (auth_class == AUTH_CLASS_EAP)
372 {
373 if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
374 {
375 fprintf(out, "EAP authentication");
376 }
377 else
378 {
379 if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
380 {
381 fprintf(out, "EAP_%" PRIuPTR "-%" PRIuPTR " authentication",
382 (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
383 (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
384 }
385 else
386 {
387 fprintf(out, "%N authentication", eap_type_names,
388 (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE));
389 }
390 }
391 id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
392 if (id)
393 {
394 fprintf(out, " with EAP identity '%Y'", id);
395 }
396 fprintf(out, "\n");
397 }
398 else if (auth_class == AUTH_CLASS_XAUTH)
399 {
400 fprintf(out, "%N authentication: %s", auth_class_names, auth_class,
401 auth->get(auth, AUTH_RULE_XAUTH_BACKEND) ?: "any");
402 id = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
403 if (id)
404 {
405 fprintf(out, " with XAuth identity '%Y'", id);
406 }
407 fprintf(out, "\n");
408 }
409 else
410 {
411 fprintf(out, "%N authentication\n", auth_class_names, auth_class);
412 }
413
414 cert = auth->get(auth, AUTH_RULE_CA_CERT);
415 if (cert)
416 {
417 fprintf(out, "%12s: ca: \"%Y\"\n", name, cert->get_subject(cert));
418 }
419
420 cert = auth->get(auth, AUTH_RULE_IM_CERT);
421 if (cert)
422 {
423 fprintf(out, "%12s: im-ca: \"%Y\"\n", name, cert->get_subject(cert));
424 }
425
426 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
427 if (cert)
428 {
429 fprintf(out, "%12s: cert: \"%Y\"\n", name,
430 cert->get_subject(cert));
431 }
432
433 valid = (uintptr_t)auth->get(auth, AUTH_RULE_OCSP_VALIDATION);
434 if (valid != VALIDATION_FAILED)
435 {
436 fprintf(out, "%12s: ocsp: status must be GOOD%s\n", name,
437 (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
438 }
439
440 valid = (uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION);
441 if (valid != VALIDATION_FAILED)
442 {
443 fprintf(out, "%12s: crl: status must be GOOD%s\n", name,
444 (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
445 }
446
447 rules = auth->create_enumerator(auth);
448 while (rules->enumerate(rules, &rule, &id))
449 {
450 if (rule == AUTH_RULE_GROUP)
451 {
452 fprintf(out, "%12s: group: %Y\n", name, id);
453 }
454 }
455 rules->destroy(rules);
456 }
457 enumerator->destroy(enumerator);
458 }
459
460 METHOD(stroke_list_t, status, void,
461 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out,
462 bool all, bool wait)
463 {
464 enumerator_t *enumerator, *children;
465 ike_cfg_t *ike_cfg;
466 child_cfg_t *child_cfg;
467 child_sa_t *child_sa;
468 ike_sa_t *ike_sa;
469 linked_list_t *my_ts, *other_ts;
470 bool first, found = FALSE;
471 char *name = msg->status.name;
472 u_int half_open;
473
474 if (all)
475 {
476 peer_cfg_t *peer_cfg;
477 ike_version_t ike_version;
478 char *pool;
479 host_t *host;
480 u_int32_t dpd;
481 time_t since, now;
482 u_int size, online, offline, i;
483 struct utsname utsname;
484
485 now = time_monotonic(NULL);
486 since = time(NULL) - (now - this->uptime);
487
488 fprintf(out, "Status of IKE charon daemon (%sSwan "VERSION, this->swan);
489 if (uname(&utsname) == 0)
490 {
491 fprintf(out, ", %s %s, %s",
492 utsname.sysname, utsname.release, utsname.machine);
493 }
494 fprintf(out, "):\n uptime: %V, since %T\n", &now, &this->uptime, &since,
495 FALSE);
496 #ifdef HAVE_MALLINFO
497 {
498 struct mallinfo mi = mallinfo();
499
500 fprintf(out, " malloc: sbrk %u, mmap %u, used %u, free %u\n",
501 mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks);
502 }
503 #endif /* HAVE_MALLINFO */
504 fprintf(out, " worker threads: %d of %d idle, ",
505 lib->processor->get_idle_threads(lib->processor),
506 lib->processor->get_total_threads(lib->processor));
507 for (i = 0; i < JOB_PRIO_MAX; i++)
508 {
509 fprintf(out, "%s%d", i == 0 ? "" : "/",
510 lib->processor->get_working_threads(lib->processor, i));
511 }
512 fprintf(out, " working, job queue: ");
513 for (i = 0; i < JOB_PRIO_MAX; i++)
514 {
515 fprintf(out, "%s%d", i == 0 ? "" : "/",
516 lib->processor->get_job_load(lib->processor, i));
517 }
518 fprintf(out, ", scheduled: %d\n",
519 lib->scheduler->get_job_load(lib->scheduler));
520 fprintf(out, " loaded plugins: %s\n",
521 lib->plugins->loaded_plugins(lib->plugins));
522
523 first = TRUE;
524 enumerator = this->attribute->create_pool_enumerator(this->attribute);
525 while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
526 {
527 if (name && !streq(name, pool))
528 {
529 continue;
530 }
531 if (first)
532 {
533 first = FALSE;
534 fprintf(out, "Virtual IP pools (size/online/offline):\n");
535 }
536 fprintf(out, " %s: %u/%u/%u\n", pool, size, online, offline);
537 }
538 enumerator->destroy(enumerator);
539
540 enumerator = hydra->kernel_interface->create_address_enumerator(
541 hydra->kernel_interface, ADDR_TYPE_REGULAR);
542 fprintf(out, "Listening IP addresses:\n");
543 while (enumerator->enumerate(enumerator, (void**)&host))
544 {
545 fprintf(out, " %H\n", host);
546 }
547 enumerator->destroy(enumerator);
548
549 fprintf(out, "Connections:\n");
550 enumerator = charon->backends->create_peer_cfg_enumerator(
551 charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
552 while (enumerator->enumerate(enumerator, &peer_cfg))
553 {
554 char *my_addr, *other_addr;
555
556 if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
557 {
558 continue;
559 }
560
561 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
562 ike_version = peer_cfg->get_ike_version(peer_cfg);
563 my_addr = ike_cfg->get_my_addr(ike_cfg);
564 other_addr = ike_cfg->get_other_addr(ike_cfg);
565 fprintf(out, "%12s: %s...%s %N", peer_cfg->get_name(peer_cfg),
566 my_addr, other_addr, ike_version_names, ike_version);
567
568 if (ike_version == IKEV1 && peer_cfg->use_aggressive(peer_cfg))
569 {
570 fprintf(out, " Aggressive");
571 }
572
573 dpd = peer_cfg->get_dpd(peer_cfg);
574 if (dpd)
575 {
576 fprintf(out, ", dpddelay=%us", dpd);
577 }
578 fprintf(out, "\n");
579
580 log_auth_cfgs(out, peer_cfg, TRUE);
581 log_auth_cfgs(out, peer_cfg, FALSE);
582
583 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
584 while (children->enumerate(children, &child_cfg))
585 {
586 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
587 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
588 fprintf(out, "%12s: child: %#R === %#R %N",
589 child_cfg->get_name(child_cfg), my_ts, other_ts,
590 ipsec_mode_names, child_cfg->get_mode(child_cfg));
591 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
592 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
593
594 if (dpd)
595 {
596 fprintf(out, ", dpdaction=%N", action_names,
597 child_cfg->get_dpd_action(child_cfg));
598 }
599 fprintf(out, "\n");
600 }
601 children->destroy(children);
602 }
603 enumerator->destroy(enumerator);
604 }
605
606 /* Enumerate shunt policies */
607 first = TRUE;
608 enumerator = charon->shunts->create_enumerator(charon->shunts);
609 while (enumerator->enumerate(enumerator, &child_cfg))
610 {
611 if (name && !streq(name, child_cfg->get_name(child_cfg)))
612 {
613 continue;
614 }
615 if (first)
616 {
617 fprintf(out, "Shunted Connections:\n");
618 first = FALSE;
619 }
620 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
621 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
622 fprintf(out, "%12s: %#R === %#R %N\n",
623 child_cfg->get_name(child_cfg), my_ts, other_ts,
624 ipsec_mode_names, child_cfg->get_mode(child_cfg));
625 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
626 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
627 }
628 enumerator->destroy(enumerator);
629
630 /* Enumerate traps */
631 first = TRUE;
632 enumerator = charon->traps->create_enumerator(charon->traps);
633 while (enumerator->enumerate(enumerator, NULL, &child_sa))
634 {
635 if (name && !streq(name, child_sa->get_name(child_sa)))
636 {
637 continue;
638 }
639 if (first)
640 {
641 fprintf(out, "Routed Connections:\n");
642 first = FALSE;
643 }
644 log_child_sa(out, child_sa, all);
645 }
646 enumerator->destroy(enumerator);
647
648 half_open = charon->ike_sa_manager->get_half_open_count(
649 charon->ike_sa_manager, NULL, FALSE);
650 fprintf(out, "Security Associations (%u up, %u connecting):\n",
651 charon->ike_sa_manager->get_count(charon->ike_sa_manager) - half_open,
652 half_open);
653 enumerator = charon->controller->create_ike_sa_enumerator(
654 charon->controller, wait);
655 while (enumerator->enumerate(enumerator, &ike_sa) && ferror(out) == 0)
656 {
657 bool ike_printed = FALSE;
658 enumerator_t *children = ike_sa->create_child_sa_enumerator(ike_sa);
659
660 if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
661 {
662 log_ike_sa(out, ike_sa, all);
663 found = TRUE;
664 ike_printed = TRUE;
665 }
666
667 while (children->enumerate(children, (void**)&child_sa))
668 {
669 if (name == NULL || streq(name, child_sa->get_name(child_sa)))
670 {
671 if (!ike_printed)
672 {
673 log_ike_sa(out, ike_sa, all);
674 found = TRUE;
675 ike_printed = TRUE;
676 }
677 log_child_sa(out, child_sa, all);
678 }
679 }
680 children->destroy(children);
681 }
682 enumerator->destroy(enumerator);
683
684 if (!found)
685 {
686 if (name)
687 {
688 fprintf(out, " no match\n");
689 }
690 else
691 {
692 fprintf(out, " none\n");
693 }
694 }
695 }
696
697 /**
698 * create a unique certificate list without duplicates
699 * certicates having the same issuer are grouped together.
700 */
701 static linked_list_t* create_unique_cert_list(certificate_type_t type)
702 {
703 linked_list_t *list = linked_list_create();
704 enumerator_t *enumerator = lib->credmgr->create_cert_enumerator(
705 lib->credmgr, type, KEY_ANY, NULL, FALSE);
706 certificate_t *cert;
707
708 while (enumerator->enumerate(enumerator, (void**)&cert))
709 {
710 enumerator_t *added = list->create_enumerator(list);
711 identification_t *issuer = cert->get_issuer(cert);
712 bool previous_same, same = FALSE, found = FALSE;
713 certificate_t *list_cert;
714
715 while (added->enumerate(added, (void**)&list_cert))
716 {
717 if (list_cert->equals(list_cert, cert))
718 { /* stop if we found a duplicate*/
719 found = TRUE;
720 break;
721 }
722 previous_same = same;
723 same = list_cert->has_issuer(list_cert, issuer);
724 if (previous_same && !same)
725 { /* group certificates with same issuer */
726 break;
727 }
728 }
729 if (!found)
730 {
731 list->insert_before(list, added, cert->get_ref(cert));
732 }
733 added->destroy(added);
734 }
735 enumerator->destroy(enumerator);
736 return list;
737 }
738
739 /**
740 * Is there a matching private key?
741 */
742 static bool has_privkey(certificate_t *cert)
743 {
744 public_key_t *public;
745 private_key_t *private = NULL;
746 chunk_t keyid;
747 identification_t *id;
748
749 public = cert->get_public_key(cert);
750 if (!public)
751 {
752 return FALSE;
753 }
754 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
755 {
756 id = identification_create_from_encoding(ID_KEY_ID, keyid);
757 private = lib->credmgr->get_private(lib->credmgr,
758 public->get_type(public), id, NULL);
759 id->destroy(id);
760 }
761 public->destroy(public);
762 DESTROY_IF(private);
763
764 return (private != NULL);
765 }
766
767 /**
768 * list all X.509 certificates matching the flags
769 */
770 static void stroke_list_x509_certs(linked_list_t *list, x509_flag_t flag)
771 {
772 enumerator_t *enumerator;
773 certificate_t *cert;
774
775 enumerator = list->create_enumerator(list);
776 while (enumerator->enumerate(enumerator, (void**)&cert))
777 {
778 x509_t *x509 = (x509_t*)cert;
779 x509_flag_t flags = x509->get_flags(x509) & X509_ANY;
780
781 /* list only if flag is set or flag == 0 */
782 if ((flags & flag) || flags == flag)
783 {
784 cert_printer->print_caption(cert_printer, CERT_X509, flag);
785 cert_printer->print(cert_printer, cert, has_privkey(cert));
786 }
787 }
788 enumerator->destroy(enumerator);
789 }
790
791 /**
792 * list all other certificates types
793 */
794 static void stroke_list_other_certs(certificate_type_t type)
795 {
796 enumerator_t *enumerator;
797 certificate_t *cert;
798 linked_list_t *list;
799
800 list = create_unique_cert_list(type);
801
802 enumerator = list->create_enumerator(list);
803 while (enumerator->enumerate(enumerator, &cert))
804 {
805 cert_printer->print_caption(cert_printer, cert->get_type(cert), X509_NONE);
806 cert_printer->print(cert_printer, cert, has_privkey(cert));
807 }
808 enumerator->destroy(enumerator);
809
810 list->destroy_offset(list, offsetof(certificate_t, destroy));
811 }
812
813 /**
814 * Print the name of an algorithm plus the name of the plugin that registered it
815 */
816 static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type,
817 const char *plugin_name)
818 {
819 char alg_name[BUF_LEN];
820 int alg_name_len;
821
822 if (alg_names)
823 {
824 alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type,
825 plugin_name);
826 }
827 else
828 {
829 alg_name_len = sprintf(alg_name, " [%s]", plugin_name);
830 }
831 if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
832 {
833 fprintf(out, "\n ");
834 *len = 13;
835 }
836 fprintf(out, "%s", alg_name);
837 *len += alg_name_len;
838 }
839
840 /**
841 * List of registered cryptographical algorithms
842 */
843 static void list_algs(FILE *out)
844 {
845 enumerator_t *enumerator;
846 encryption_algorithm_t encryption;
847 integrity_algorithm_t integrity;
848 hash_algorithm_t hash;
849 pseudo_random_function_t prf;
850 diffie_hellman_group_t group;
851 rng_quality_t quality;
852 const char *plugin_name;
853 int len;
854
855 fprintf(out, "\n");
856 fprintf(out, "List of registered IKE algorithms:\n");
857 fprintf(out, "\n encryption:");
858 len = 13;
859 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
860 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
861 {
862 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
863 }
864 enumerator->destroy(enumerator);
865 fprintf(out, "\n integrity: ");
866 len = 13;
867 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
868 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
869 {
870 print_alg(out, &len, integrity_algorithm_names, integrity, plugin_name);
871 }
872 enumerator->destroy(enumerator);
873 fprintf(out, "\n aead: ");
874 len = 13;
875 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
876 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
877 {
878 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
879 }
880 enumerator->destroy(enumerator);
881 fprintf(out, "\n hasher: ");
882 len = 13;
883 enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
884 while (enumerator->enumerate(enumerator, &hash, &plugin_name))
885 {
886 print_alg(out, &len, hash_algorithm_names, hash, plugin_name);
887 }
888 enumerator->destroy(enumerator);
889 fprintf(out, "\n prf: ");
890 len = 13;
891 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
892 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
893 {
894 print_alg(out, &len, pseudo_random_function_names, prf, plugin_name);
895 }
896 enumerator->destroy(enumerator);
897 fprintf(out, "\n dh-group: ");
898 len = 13;
899 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
900 while (enumerator->enumerate(enumerator, &group, &plugin_name))
901 {
902 print_alg(out, &len, diffie_hellman_group_names, group, plugin_name);
903 }
904 enumerator->destroy(enumerator);
905 fprintf(out, "\n random-gen:");
906 len = 13;
907 enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
908 while (enumerator->enumerate(enumerator, &quality, &plugin_name))
909 {
910 print_alg(out, &len, rng_quality_names, quality, plugin_name);
911 }
912 enumerator->destroy(enumerator);
913 fprintf(out, "\n nonce-gen: ");
914 len = 13;
915 enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
916 while (enumerator->enumerate(enumerator, &plugin_name))
917 {
918 print_alg(out, &len, NULL, 0, plugin_name);
919 }
920 enumerator->destroy(enumerator);
921 fprintf(out, "\n");
922 }
923
924 /**
925 * List loaded plugin information
926 */
927 static void list_plugins(FILE *out)
928 {
929 plugin_feature_t *features, *fp;
930 enumerator_t *enumerator;
931 linked_list_t *list;
932 plugin_t *plugin;
933 int count, i;
934 bool loaded;
935 char *str;
936
937 fprintf(out, "\n");
938 fprintf(out, "List of loaded Plugins:\n");
939 fprintf(out, "\n");
940
941 enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
942 while (enumerator->enumerate(enumerator, &plugin, &list))
943 {
944 fprintf(out, "%s:\n", plugin->get_name(plugin));
945 if (plugin->get_features)
946 {
947 count = plugin->get_features(plugin, &features);
948 for (i = 0; i < count; i++)
949 {
950 str = plugin_feature_get_string(&features[i]);
951 switch (features[i].kind)
952 {
953 case FEATURE_PROVIDE:
954 fp = &features[i];
955 loaded = list->find_first(list, NULL,
956 (void**)&fp) == SUCCESS;
957 fprintf(out, " %s%s\n",
958 str, loaded ? "" : " (not loaded)");
959 break;
960 case FEATURE_DEPENDS:
961 fprintf(out, " %s\n", str);
962 break;
963 case FEATURE_SDEPEND:
964 fprintf(out, " %s (soft)\n", str);
965 break;
966 default:
967 break;
968 }
969 free(str);
970 }
971 }
972 list->destroy(list);
973 }
974 enumerator->destroy(enumerator);
975 }
976
977 METHOD(stroke_list_t, list, void,
978 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
979 {
980 linked_list_t *cert_list = NULL;
981
982 cert_printer = certificate_printer_create(out, TRUE, msg->list.utc);
983
984 if (msg->list.flags & LIST_PUBKEYS)
985 {
986 stroke_list_other_certs(CERT_TRUSTED_PUBKEY);
987 }
988 if (msg->list.flags & LIST_CERTS)
989 {
990 stroke_list_other_certs(CERT_GPG);
991 }
992 if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS))
993 {
994 cert_list = create_unique_cert_list(CERT_X509);
995 }
996 if (msg->list.flags & LIST_CERTS)
997 {
998 stroke_list_x509_certs(cert_list, X509_NONE);
999 }
1000 if (msg->list.flags & LIST_CACERTS)
1001 {
1002 stroke_list_x509_certs(cert_list, X509_CA);
1003 }
1004 if (msg->list.flags & LIST_OCSPCERTS)
1005 {
1006 stroke_list_x509_certs(cert_list, X509_OCSP_SIGNER);
1007 }
1008 if (msg->list.flags & LIST_AACERTS)
1009 {
1010 stroke_list_x509_certs(cert_list, X509_AA);
1011 }
1012 DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy));
1013
1014 if (msg->list.flags & LIST_ACERTS)
1015 {
1016 stroke_list_other_certs(CERT_X509_AC);
1017 }
1018 if (msg->list.flags & LIST_CRLS)
1019 {
1020 stroke_list_other_certs(CERT_X509_CRL);
1021 }
1022 if (msg->list.flags & LIST_OCSP)
1023 {
1024 stroke_list_other_certs(CERT_X509_OCSP_RESPONSE);
1025 }
1026 if (msg->list.flags & LIST_ALGS)
1027 {
1028 list_algs(out);
1029 }
1030 if (msg->list.flags & LIST_PLUGINS)
1031 {
1032 list_plugins(out);
1033 }
1034 cert_printer->destroy(cert_printer);
1035 cert_printer = NULL;
1036 }
1037
1038 /**
1039 * Print leases of a single pool
1040 */
1041 static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
1042 host_t *address, u_int size, u_int online, u_int offline)
1043 {
1044 enumerator_t *enumerator;
1045 identification_t *id;
1046 host_t *lease;
1047 bool on;
1048 int found = 0;
1049
1050 fprintf(out, "Leases in pool '%s', usage: %u/%u, %u online\n",
1051 pool, online + offline, size, online);
1052 enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
1053 while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
1054 {
1055 if (!address || address->ip_equals(address, lease))
1056 {
1057 fprintf(out, " %15H %s '%Y'\n",
1058 lease, on ? "online" : "offline", id);
1059 found++;
1060 }
1061 }
1062 enumerator->destroy(enumerator);
1063 if (!found)
1064 {
1065 fprintf(out, " no matching leases found\n");
1066 }
1067 }
1068
1069 METHOD(stroke_list_t, leases, void,
1070 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
1071 {
1072 enumerator_t *enumerator;
1073 u_int size, offline, online;
1074 host_t *address = NULL;
1075 char *pool;
1076 int found = 0;
1077
1078 if (msg->leases.address)
1079 {
1080 address = host_create_from_string(msg->leases.address, 0);
1081 }
1082
1083 enumerator = this->attribute->create_pool_enumerator(this->attribute);
1084 while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
1085 {
1086 if (!msg->leases.pool || streq(msg->leases.pool, pool))
1087 {
1088 pool_leases(this, out, pool, address, size, online, offline);
1089 found++;
1090 }
1091 }
1092 enumerator->destroy(enumerator);
1093 if (!found)
1094 {
1095 if (msg->leases.pool)
1096 {
1097 fprintf(out, "pool '%s' not found\n", msg->leases.pool);
1098 }
1099 else
1100 {
1101 fprintf(out, "no pools found\n");
1102 }
1103 }
1104 DESTROY_IF(address);
1105 }
1106
1107 METHOD(stroke_list_t, destroy, void,
1108 private_stroke_list_t *this)
1109 {
1110 free(this);
1111 }
1112
1113 /*
1114 * see header file
1115 */
1116 stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
1117 {
1118 private_stroke_list_t *this;
1119
1120 INIT(this,
1121 .public = {
1122 .list = _list,
1123 .status = _status,
1124 .leases = _leases,
1125 .destroy = _destroy,
1126 },
1127 .uptime = time_monotonic(NULL),
1128 .swan = "strong",
1129 .attribute = attribute,
1130 );
1131
1132 if (lib->settings->get_bool(lib->settings,
1133 "charon.i_dont_care_about_security_and_use_aggressive_mode_psk", FALSE))
1134 {
1135 this->swan = "weak";
1136 }
1137
1138 return &this->public;
1139 }