stroke: Allow specifying the ipsec.secrets location in strongswan.conf
[strongswan.git] / src / libcharon / plugins / stroke / stroke_list.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "stroke_list.h"
17
18 #include <inttypes.h>
19 #include <time.h>
20 #include <sys/utsname.h>
21
22 #ifdef HAVE_MALLINFO
23 #include <malloc.h>
24 #endif /* HAVE_MALLINFO */
25
26 #include <hydra.h>
27 #include <daemon.h>
28 #include <collections/linked_list.h>
29 #include <plugins/plugin.h>
30 #include <credentials/certificates/x509.h>
31 #include <credentials/certificates/ac.h>
32 #include <credentials/certificates/crl.h>
33 #include <credentials/certificates/pgp_certificate.h>
34 #include <config/peer_cfg.h>
35 #include <asn1/asn1.h>
36 #include <asn1/oid.h>
37
38 /* warning intervals for list functions */
39 #define CERT_WARNING_INTERVAL 30 /* days */
40 #define CRL_WARNING_INTERVAL 7 /* days */
41 #define AC_WARNING_INTERVAL 1 /* day */
42
43 typedef struct private_stroke_list_t private_stroke_list_t;
44
45 /**
46 * private data of stroke_list
47 */
48 struct private_stroke_list_t {
49
50 /**
51 * public functions
52 */
53 stroke_list_t public;
54
55 /**
56 * Kind of *swan we run
57 */
58 char *swan;
59
60 /**
61 * timestamp of daemon start
62 */
63 time_t uptime;
64
65 /**
66 * strokes attribute provider
67 */
68 stroke_attribute_t *attribute;
69 };
70
71 /**
72 * Log tasks of a specific queue to out
73 */
74 static void log_task_q(FILE *out, ike_sa_t *ike_sa, task_queue_t q, char *name)
75 {
76 enumerator_t *enumerator;
77 bool has = FALSE;
78 task_t *task;
79
80 enumerator = ike_sa->create_task_enumerator(ike_sa, q);
81 while (enumerator->enumerate(enumerator, &task))
82 {
83 if (!has)
84 {
85 fprintf(out, "%12s[%d]: Tasks %s: ", ike_sa->get_name(ike_sa),
86 ike_sa->get_unique_id(ike_sa), name);
87 has = TRUE;
88 }
89 fprintf(out, "%N ", task_type_names, task->get_type(task));
90 }
91 enumerator->destroy(enumerator);
92 if (has)
93 {
94 fprintf(out, "\n");
95 }
96 }
97
98 /**
99 * log an IKE_SA to out
100 */
101 static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
102 {
103 ike_sa_id_t *id = ike_sa->get_id(ike_sa);
104 time_t now = time_monotonic(NULL);
105
106 fprintf(out, "%12s[%d]: %N",
107 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
108 ike_sa_state_names, ike_sa->get_state(ike_sa));
109
110 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
111 {
112 time_t established;
113
114 established = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
115 fprintf(out, " %V ago", &now, &established);
116 }
117
118 fprintf(out, ", %H[%Y]...%H[%Y]\n",
119 ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
120 ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
121
122 if (all)
123 {
124 proposal_t *ike_proposal;
125 identification_t *eap_id;
126
127 eap_id = ike_sa->get_other_eap_id(ike_sa);
128
129 if (!eap_id->equals(eap_id, ike_sa->get_other_id(ike_sa)))
130 {
131 fprintf(out, "%12s[%d]: Remote %s identity: %Y\n",
132 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
133 ike_sa->get_version(ike_sa) == IKEV1 ? "XAuth" : "EAP",
134 eap_id);
135 }
136
137 ike_proposal = ike_sa->get_proposal(ike_sa);
138
139 fprintf(out, "%12s[%d]: %N SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
140 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
141 ike_version_names, ike_sa->get_version(ike_sa),
142 id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
143 id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
144
145
146 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
147 {
148 time_t rekey, reauth;
149 peer_cfg_t *peer_cfg;
150
151 rekey = ike_sa->get_statistic(ike_sa, STAT_REKEY);
152 reauth = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
153 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
154
155 if (rekey)
156 {
157 fprintf(out, ", rekeying in %V", &rekey, &now);
158 }
159 if (reauth)
160 {
161 bool first = TRUE;
162 enumerator_t *enumerator;
163 auth_cfg_t *auth;
164
165 fprintf(out, ", ");
166 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, TRUE);
167 while (enumerator->enumerate(enumerator, &auth))
168 {
169 if (!first)
170 {
171 fprintf(out, "+");
172 }
173 first = FALSE;
174 fprintf(out, "%N", auth_class_names,
175 auth->get(auth, AUTH_RULE_AUTH_CLASS));
176 }
177 enumerator->destroy(enumerator);
178 fprintf(out, " reauthentication in %V", &reauth, &now);
179 }
180 if (!rekey && !reauth)
181 {
182 fprintf(out, ", rekeying disabled");
183 }
184 }
185 fprintf(out, "\n");
186
187 if (ike_proposal)
188 {
189 char buf[BUF_LEN];
190
191 snprintf(buf, BUF_LEN, "%P", ike_proposal);
192 fprintf(out, "%12s[%d]: IKE proposal: %s\n",
193 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
194 buf+4);
195 }
196
197 log_task_q(out, ike_sa, TASK_QUEUE_QUEUED, "queued");
198 log_task_q(out, ike_sa, TASK_QUEUE_ACTIVE, "active");
199 log_task_q(out, ike_sa, TASK_QUEUE_PASSIVE, "passive");
200 }
201 }
202
203 /**
204 * log an CHILD_SA to out
205 */
206 static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
207 {
208 time_t use_in, use_out, rekey, now;
209 u_int64_t bytes_in, bytes_out, packets_in, packets_out;
210 proposal_t *proposal;
211 linked_list_t *my_ts, *other_ts;
212 child_cfg_t *config;
213
214 config = child_sa->get_config(child_sa);
215 now = time_monotonic(NULL);
216
217 fprintf(out, "%12s{%d}: %N, %N%s",
218 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
219 child_sa_state_names, child_sa->get_state(child_sa),
220 ipsec_mode_names, child_sa->get_mode(child_sa),
221 config->use_proxy_mode(config) ? "_PROXY" : "");
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_reqid(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 {
327 rekey = child_sa->get_lifetime(child_sa, TRUE);
328 fprintf(out, ", expires in %V", &now, &rekey);
329 }
330
331 my_ts = linked_list_create_from_enumerator(
332 child_sa->create_ts_enumerator(child_sa, TRUE));
333 other_ts = linked_list_create_from_enumerator(
334 child_sa->create_ts_enumerator(child_sa, FALSE));
335 fprintf(out, "\n%12s{%d}: %#R=== %#R\n",
336 child_sa->get_name(child_sa), child_sa->get_reqid(child_sa),
337 my_ts, other_ts);
338 my_ts->destroy(my_ts);
339 other_ts->destroy(other_ts);
340 }
341
342 /**
343 * Log a configs local or remote authentication config to out
344 */
345 static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
346 {
347 enumerator_t *enumerator, *rules;
348 auth_rule_t rule;
349 auth_cfg_t *auth;
350 auth_class_t auth_class;
351 identification_t *id;
352 certificate_t *cert;
353 cert_validation_t valid;
354 char *name;
355
356 name = peer_cfg->get_name(peer_cfg);
357
358 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
359 while (enumerator->enumerate(enumerator, &auth))
360 {
361 fprintf(out, "%12s: %s", name, local ? "local: " : "remote:");
362 id = auth->get(auth, AUTH_RULE_IDENTITY);
363 if (id)
364 {
365 fprintf(out, " [%Y]", id);
366 }
367 fprintf(out, " uses ");
368
369 auth_class = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
370 if (auth_class == AUTH_CLASS_EAP)
371 {
372 if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE) == EAP_NAK)
373 {
374 fprintf(out, "EAP authentication");
375 }
376 else
377 {
378 if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
379 {
380 fprintf(out, "EAP_%" PRIuPTR "-%" PRIuPTR " authentication",
381 (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
382 (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
383 }
384 else
385 {
386 fprintf(out, "%N authentication", eap_type_names,
387 (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE));
388 }
389 }
390 id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
391 if (id)
392 {
393 fprintf(out, " with EAP identity '%Y'", id);
394 }
395 fprintf(out, "\n");
396 }
397 else if (auth_class == AUTH_CLASS_XAUTH)
398 {
399 fprintf(out, "%N authentication: %s", auth_class_names, auth_class,
400 auth->get(auth, AUTH_RULE_XAUTH_BACKEND) ?: "any");
401 id = auth->get(auth, AUTH_RULE_XAUTH_IDENTITY);
402 if (id)
403 {
404 fprintf(out, " with XAuth identity '%Y'", id);
405 }
406 fprintf(out, "\n");
407 }
408 else
409 {
410 fprintf(out, "%N authentication\n", auth_class_names, auth_class);
411 }
412
413 cert = auth->get(auth, AUTH_RULE_CA_CERT);
414 if (cert)
415 {
416 fprintf(out, "%12s: ca: \"%Y\"\n", name, cert->get_subject(cert));
417 }
418
419 cert = auth->get(auth, AUTH_RULE_IM_CERT);
420 if (cert)
421 {
422 fprintf(out, "%12s: im-ca: \"%Y\"\n", name, cert->get_subject(cert));
423 }
424
425 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
426 if (cert)
427 {
428 fprintf(out, "%12s: cert: \"%Y\"\n", name,
429 cert->get_subject(cert));
430 }
431
432 valid = (uintptr_t)auth->get(auth, AUTH_RULE_OCSP_VALIDATION);
433 if (valid != VALIDATION_FAILED)
434 {
435 fprintf(out, "%12s: ocsp: status must be GOOD%s\n", name,
436 (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
437 }
438
439 valid = (uintptr_t)auth->get(auth, AUTH_RULE_CRL_VALIDATION);
440 if (valid != VALIDATION_FAILED)
441 {
442 fprintf(out, "%12s: crl: status must be GOOD%s\n", name,
443 (valid == VALIDATION_SKIPPED) ? " or SKIPPED" : "");
444 }
445
446 rules = auth->create_enumerator(auth);
447 while (rules->enumerate(rules, &rule, &id))
448 {
449 if (rule == AUTH_RULE_GROUP)
450 {
451 fprintf(out, "%12s: group: %Y\n", name, id);
452 }
453 }
454 rules->destroy(rules);
455 }
456 enumerator->destroy(enumerator);
457 }
458
459 METHOD(stroke_list_t, status, void,
460 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out,
461 bool all, bool wait)
462 {
463 enumerator_t *enumerator, *children;
464 ike_cfg_t *ike_cfg;
465 child_cfg_t *child_cfg;
466 child_sa_t *child_sa;
467 ike_sa_t *ike_sa;
468 linked_list_t *my_ts, *other_ts;
469 bool first, found = FALSE;
470 char *name = msg->status.name;
471 u_int half_open;
472
473 if (all)
474 {
475 peer_cfg_t *peer_cfg;
476 ike_version_t ike_version;
477 char *pool;
478 host_t *host;
479 u_int32_t dpd;
480 time_t since, now;
481 u_int size, online, offline, i;
482 struct utsname utsname;
483
484 now = time_monotonic(NULL);
485 since = time(NULL) - (now - this->uptime);
486
487 fprintf(out, "Status of IKE charon daemon (%sSwan "VERSION, this->swan);
488 if (uname(&utsname) == 0)
489 {
490 fprintf(out, ", %s %s, %s",
491 utsname.sysname, utsname.release, utsname.machine);
492 }
493 fprintf(out, "):\n uptime: %V, since %T\n", &now, &this->uptime, &since,
494 FALSE);
495 #ifdef HAVE_MALLINFO
496 {
497 struct mallinfo mi = mallinfo();
498
499 fprintf(out, " malloc: sbrk %d, mmap %d, used %d, free %d\n",
500 mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks);
501 }
502 #endif /* HAVE_MALLINFO */
503 fprintf(out, " worker threads: %d of %d idle, ",
504 lib->processor->get_idle_threads(lib->processor),
505 lib->processor->get_total_threads(lib->processor));
506 for (i = 0; i < JOB_PRIO_MAX; i++)
507 {
508 fprintf(out, "%s%d", i == 0 ? "" : "/",
509 lib->processor->get_working_threads(lib->processor, i));
510 }
511 fprintf(out, " working, job queue: ");
512 for (i = 0; i < JOB_PRIO_MAX; i++)
513 {
514 fprintf(out, "%s%d", i == 0 ? "" : "/",
515 lib->processor->get_job_load(lib->processor, i));
516 }
517 fprintf(out, ", scheduled: %d\n",
518 lib->scheduler->get_job_load(lib->scheduler));
519 fprintf(out, " loaded plugins: %s\n",
520 lib->plugins->loaded_plugins(lib->plugins));
521
522 first = TRUE;
523 enumerator = this->attribute->create_pool_enumerator(this->attribute);
524 while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
525 {
526 if (name && !streq(name, pool))
527 {
528 continue;
529 }
530 if (first)
531 {
532 first = FALSE;
533 fprintf(out, "Virtual IP pools (size/online/offline):\n");
534 }
535 fprintf(out, " %s: %u/%u/%u\n", pool, size, online, offline);
536 }
537 enumerator->destroy(enumerator);
538
539 enumerator = hydra->kernel_interface->create_address_enumerator(
540 hydra->kernel_interface, ADDR_TYPE_REGULAR);
541 fprintf(out, "Listening IP addresses:\n");
542 while (enumerator->enumerate(enumerator, (void**)&host))
543 {
544 fprintf(out, " %H\n", host);
545 }
546 enumerator->destroy(enumerator);
547
548 fprintf(out, "Connections:\n");
549 enumerator = charon->backends->create_peer_cfg_enumerator(
550 charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
551 while (enumerator->enumerate(enumerator, &peer_cfg))
552 {
553 char *my_addr, *other_addr;
554
555 if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
556 {
557 continue;
558 }
559
560 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
561 ike_version = peer_cfg->get_ike_version(peer_cfg);
562 my_addr = ike_cfg->get_my_addr(ike_cfg);
563 other_addr = ike_cfg->get_other_addr(ike_cfg);
564 fprintf(out, "%12s: %s...%s %N", peer_cfg->get_name(peer_cfg),
565 my_addr, other_addr, ike_version_names, ike_version);
566
567 if (ike_version == IKEV1 && peer_cfg->use_aggressive(peer_cfg))
568 {
569 fprintf(out, " Aggressive");
570 }
571
572 dpd = peer_cfg->get_dpd(peer_cfg);
573 if (dpd)
574 {
575 fprintf(out, ", dpddelay=%us", dpd);
576 }
577 fprintf(out, "\n");
578
579 log_auth_cfgs(out, peer_cfg, TRUE);
580 log_auth_cfgs(out, peer_cfg, FALSE);
581
582 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
583 while (children->enumerate(children, &child_cfg))
584 {
585 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
586 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
587 fprintf(out, "%12s: child: %#R=== %#R%N",
588 child_cfg->get_name(child_cfg), my_ts, other_ts,
589 ipsec_mode_names, child_cfg->get_mode(child_cfg));
590 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
591 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
592
593 if (dpd)
594 {
595 fprintf(out, ", dpdaction=%N", action_names,
596 child_cfg->get_dpd_action(child_cfg));
597 }
598 fprintf(out, "\n");
599 }
600 children->destroy(children);
601 }
602 enumerator->destroy(enumerator);
603 }
604
605 /* Enumerate shunt policies */
606 first = TRUE;
607 enumerator = charon->shunts->create_enumerator(charon->shunts);
608 while (enumerator->enumerate(enumerator, &child_cfg))
609 {
610 if (name && !streq(name, child_cfg->get_name(child_cfg)))
611 {
612 continue;
613 }
614 if (first)
615 {
616 fprintf(out, "Shunted Connections:\n");
617 first = FALSE;
618 }
619 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
620 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
621 fprintf(out, "%12s: %#R=== %#R%N\n",
622 child_cfg->get_name(child_cfg), my_ts, other_ts,
623 ipsec_mode_names, child_cfg->get_mode(child_cfg));
624 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
625 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
626 }
627 enumerator->destroy(enumerator);
628
629 /* Enumerate traps */
630 first = TRUE;
631 enumerator = charon->traps->create_enumerator(charon->traps);
632 while (enumerator->enumerate(enumerator, NULL, &child_sa))
633 {
634 if (name && !streq(name, child_sa->get_name(child_sa)))
635 {
636 continue;
637 }
638 if (first)
639 {
640 fprintf(out, "Routed Connections:\n");
641 first = FALSE;
642 }
643 log_child_sa(out, child_sa, all);
644 }
645 enumerator->destroy(enumerator);
646
647 half_open = charon->ike_sa_manager->get_half_open_count(
648 charon->ike_sa_manager, NULL);
649 fprintf(out, "Security Associations (%u up, %u connecting):\n",
650 charon->ike_sa_manager->get_count(charon->ike_sa_manager) - half_open,
651 half_open);
652 enumerator = charon->controller->create_ike_sa_enumerator(
653 charon->controller, wait);
654 while (enumerator->enumerate(enumerator, &ike_sa) && ferror(out) == 0)
655 {
656 bool ike_printed = FALSE;
657 enumerator_t *children = ike_sa->create_child_sa_enumerator(ike_sa);
658
659 if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
660 {
661 log_ike_sa(out, ike_sa, all);
662 found = TRUE;
663 ike_printed = TRUE;
664 }
665
666 while (children->enumerate(children, (void**)&child_sa))
667 {
668 if (name == NULL || streq(name, child_sa->get_name(child_sa)))
669 {
670 if (!ike_printed)
671 {
672 log_ike_sa(out, ike_sa, all);
673 found = TRUE;
674 ike_printed = TRUE;
675 }
676 log_child_sa(out, child_sa, all);
677 }
678 }
679 children->destroy(children);
680 }
681 enumerator->destroy(enumerator);
682
683 if (!found)
684 {
685 if (name)
686 {
687 fprintf(out, " no match\n");
688 }
689 else
690 {
691 fprintf(out, " none\n");
692 }
693 }
694 }
695
696 /**
697 * create a unique certificate list without duplicates
698 * certicates having the same issuer are grouped together.
699 */
700 static linked_list_t* create_unique_cert_list(certificate_type_t type)
701 {
702 linked_list_t *list = linked_list_create();
703 enumerator_t *enumerator = lib->credmgr->create_cert_enumerator(
704 lib->credmgr, type, KEY_ANY, NULL, FALSE);
705 certificate_t *cert;
706
707 while (enumerator->enumerate(enumerator, (void**)&cert))
708 {
709 enumerator_t *added = list->create_enumerator(list);
710 identification_t *issuer = cert->get_issuer(cert);
711 bool previous_same, same = FALSE, found = FALSE;
712 certificate_t *list_cert;
713
714 while (added->enumerate(added, (void**)&list_cert))
715 {
716 if (list_cert->equals(list_cert, cert))
717 { /* stop if we found a duplicate*/
718 found = TRUE;
719 break;
720 }
721 previous_same = same;
722 same = list_cert->has_issuer(list_cert, issuer);
723 if (previous_same && !same)
724 { /* group certificates with same issuer */
725 break;
726 }
727 }
728 if (!found)
729 {
730 list->insert_before(list, added, cert->get_ref(cert));
731 }
732 added->destroy(added);
733 }
734 enumerator->destroy(enumerator);
735 return list;
736 }
737
738 /**
739 * Print a single public key.
740 */
741 static void list_public_key(public_key_t *public, FILE *out)
742 {
743 private_key_t *private = NULL;
744 chunk_t keyid;
745 identification_t *id;
746
747 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
748 {
749 id = identification_create_from_encoding(ID_KEY_ID, keyid);
750 private = lib->credmgr->get_private(lib->credmgr,
751 public->get_type(public), id, NULL);
752 id->destroy(id);
753 }
754
755 fprintf(out, " pubkey: %N %d bits%s\n",
756 key_type_names, public->get_type(public),
757 public->get_keysize(public),
758 private ? ", has private key" : "");
759 if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
760 {
761 fprintf(out, " keyid: %#B\n", &keyid);
762 }
763 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
764 {
765 fprintf(out, " subjkey: %#B\n", &keyid);
766 }
767 DESTROY_IF(private);
768 }
769
770 /**
771 * list all raw public keys
772 */
773 static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
774 {
775 bool first = TRUE;
776 time_t now = time(NULL), notBefore, notAfter;
777 enumerator_t *enumerator;
778 certificate_t *cert;
779
780 enumerator = list->create_enumerator(list);
781 while (enumerator->enumerate(enumerator, (void**)&cert))
782 {
783 identification_t *subject = cert->get_subject(cert);
784 public_key_t *public = cert->get_public_key(cert);
785
786 if (public)
787 {
788 if (first)
789 {
790 fprintf(out, "\n");
791 fprintf(out, "List of Raw Public Keys:\n");
792 first = FALSE;
793 }
794 fprintf(out, "\n");
795
796 /* list subject if available */
797 if (subject->get_type(subject) != ID_KEY_ID)
798 {
799 fprintf(out, " subject: %#Y\n", subject);
800 }
801
802 /* list validity if available*/
803 cert->get_validity(cert, &now, &notBefore, &notAfter);
804 if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
805 {
806 fprintf(out, " validity: not before %T, ", &notBefore, utc);
807 if (now < notBefore)
808 {
809 fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
810 }
811 else
812 {
813 fprintf(out, "ok\n");
814 }
815 fprintf(out, " not after %T, ", &notAfter, utc);
816 if (now > notAfter)
817 {
818 fprintf(out, "expired (%V ago)\n", &now, &notAfter);
819 }
820 else
821 {
822 fprintf(out, "ok");
823 if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
824 {
825 fprintf(out, " (expires in %V)", &now, &notAfter);
826 }
827 fprintf(out, " \n");
828 }
829 }
830
831 list_public_key(public, out);
832 public->destroy(public);
833 }
834 }
835 enumerator->destroy(enumerator);
836 }
837
838 /**
839 * list OpenPGP certificates
840 */
841 static void stroke_list_pgp(linked_list_t *list,bool utc, FILE *out)
842 {
843 bool first = TRUE;
844 time_t now = time(NULL);
845 enumerator_t *enumerator = list->create_enumerator(list);
846 certificate_t *cert;
847
848 while (enumerator->enumerate(enumerator, (void**)&cert))
849 {
850 time_t created, until;
851 public_key_t *public;
852 pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert;
853 chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
854
855 if (first)
856 {
857
858 fprintf(out, "\n");
859 fprintf(out, "List of PGP End Entity Certificates:\n");
860 first = FALSE;
861 }
862 fprintf(out, "\n");
863 fprintf(out, " userid: '%Y'\n", cert->get_subject(cert));
864
865 fprintf(out, " digest: %#B\n", &fingerprint);
866
867 /* list validity */
868 cert->get_validity(cert, &now, &created, &until);
869 fprintf(out, " created: %T\n", &created, utc);
870 fprintf(out, " until: %T%s\n", &until, utc,
871 (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
872
873 public = cert->get_public_key(cert);
874 if (public)
875 {
876 list_public_key(public, out);
877 public->destroy(public);
878 }
879 }
880 enumerator->destroy(enumerator);
881 }
882
883 /**
884 * list all X.509 certificates matching the flags
885 */
886 static void stroke_list_certs(linked_list_t *list, char *label,
887 x509_flag_t flags, bool utc, FILE *out)
888 {
889 bool first = TRUE;
890 time_t now = time(NULL);
891 enumerator_t *enumerator;
892 certificate_t *cert;
893 x509_flag_t flag_mask;
894
895 /* mask all auxiliary flags */
896 flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH | X509_IKE_INTERMEDIATE |
897 X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS);
898
899 enumerator = list->create_enumerator(list);
900 while (enumerator->enumerate(enumerator, (void**)&cert))
901 {
902 x509_t *x509 = (x509_t*)cert;
903 x509_flag_t x509_flags = x509->get_flags(x509) & flag_mask;
904
905 /* list only if flag is set or flag == 0 */
906 if ((x509_flags & flags) || (x509_flags == flags))
907 {
908 enumerator_t *enumerator;
909 identification_t *altName;
910 bool first_altName = TRUE;
911 u_int pathlen;
912 chunk_t serial, authkey;
913 time_t notBefore, notAfter;
914 public_key_t *public;
915
916 if (first)
917 {
918 fprintf(out, "\n");
919 fprintf(out, "List of %s:\n", label);
920 first = FALSE;
921 }
922 fprintf(out, "\n");
923
924 /* list subjectAltNames */
925 enumerator = x509->create_subjectAltName_enumerator(x509);
926 while (enumerator->enumerate(enumerator, (void**)&altName))
927 {
928 if (first_altName)
929 {
930 fprintf(out, " altNames: ");
931 first_altName = FALSE;
932 }
933 else
934 {
935 fprintf(out, ", ");
936 }
937 fprintf(out, "%Y", altName);
938 }
939 if (!first_altName)
940 {
941 fprintf(out, "\n");
942 }
943 enumerator->destroy(enumerator);
944
945 fprintf(out, " subject: \"%Y\"\n", cert->get_subject(cert));
946 fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
947 serial = chunk_skip_zero(x509->get_serial(x509));
948 fprintf(out, " serial: %#B\n", &serial);
949
950 /* list validity */
951 cert->get_validity(cert, &now, &notBefore, &notAfter);
952 fprintf(out, " validity: not before %T, ", &notBefore, utc);
953 if (now < notBefore)
954 {
955 fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
956 }
957 else
958 {
959 fprintf(out, "ok\n");
960 }
961 fprintf(out, " not after %T, ", &notAfter, utc);
962 if (now > notAfter)
963 {
964 fprintf(out, "expired (%V ago)\n", &now, &notAfter);
965 }
966 else
967 {
968 fprintf(out, "ok");
969 if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
970 {
971 fprintf(out, " (expires in %V)", &now, &notAfter);
972 }
973 fprintf(out, " \n");
974 }
975
976 public = cert->get_public_key(cert);
977 if (public)
978 {
979 list_public_key(public, out);
980 public->destroy(public);
981 }
982
983 /* list optional authorityKeyIdentifier */
984 authkey = x509->get_authKeyIdentifier(x509);
985 if (authkey.ptr)
986 {
987 fprintf(out, " authkey: %#B\n", &authkey);
988 }
989
990 /* list optional pathLenConstraint */
991 pathlen = x509->get_constraint(x509, X509_PATH_LEN);
992 if (pathlen != X509_NO_CONSTRAINT)
993 {
994 fprintf(out, " pathlen: %u\n", pathlen);
995 }
996
997 /* list optional ipAddrBlocks */
998 if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
999 {
1000 traffic_selector_t *ipAddrBlock;
1001 bool first_ipAddrBlock = TRUE;
1002
1003 fprintf(out, " addresses: ");
1004 enumerator = x509->create_ipAddrBlock_enumerator(x509);
1005 while (enumerator->enumerate(enumerator, &ipAddrBlock))
1006 {
1007 if (first_ipAddrBlock)
1008 {
1009 first_ipAddrBlock = FALSE;
1010 }
1011 else
1012 {
1013 fprintf(out, ", ");
1014 }
1015 fprintf(out, "%R", ipAddrBlock);
1016 }
1017 enumerator->destroy(enumerator);
1018 fprintf(out, "\n");
1019 }
1020 }
1021 }
1022 enumerator->destroy(enumerator);
1023 }
1024
1025 /**
1026 * list all X.509 attribute certificates
1027 */
1028 static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
1029 {
1030 bool first = TRUE;
1031 time_t notBefore, notAfter, now = time(NULL);
1032 enumerator_t *enumerator;
1033 certificate_t *cert;
1034
1035 enumerator = list->create_enumerator(list);
1036 while (enumerator->enumerate(enumerator, &cert))
1037 {
1038 ac_t *ac = (ac_t*)cert;
1039 ac_group_type_t type;
1040 identification_t *id;
1041 enumerator_t *groups;
1042 chunk_t chunk;
1043 bool firstgroup = TRUE;
1044
1045 if (first)
1046 {
1047 fprintf(out, "\n");
1048 fprintf(out, "List of X.509 Attribute Certificates:\n");
1049 first = FALSE;
1050 }
1051 fprintf(out, "\n");
1052
1053 id = cert->get_subject(cert);
1054 if (id)
1055 {
1056 fprintf(out, " holder: \"%Y\"\n", id);
1057 }
1058 id = ac->get_holderIssuer(ac);
1059 if (id)
1060 {
1061 fprintf(out, " hissuer: \"%Y\"\n", id);
1062 }
1063 chunk = chunk_skip_zero(ac->get_holderSerial(ac));
1064 if (chunk.ptr)
1065 {
1066 fprintf(out, " hserial: %#B\n", &chunk);
1067 }
1068 groups = ac->create_group_enumerator(ac);
1069 while (groups->enumerate(groups, &type, &chunk))
1070 {
1071 int oid;
1072 char *str;
1073
1074 if (firstgroup)
1075 {
1076 fprintf(out, " groups: ");
1077 firstgroup = FALSE;
1078 }
1079 else
1080 {
1081 fprintf(out, " ");
1082 }
1083 switch (type)
1084 {
1085 case AC_GROUP_TYPE_STRING:
1086 fprintf(out, "%.*s", (int)chunk.len, chunk.ptr);
1087 break;
1088 case AC_GROUP_TYPE_OID:
1089 oid = asn1_known_oid(chunk);
1090 if (oid == OID_UNKNOWN)
1091 {
1092 str = asn1_oid_to_string(chunk);
1093 if (str)
1094 {
1095 fprintf(out, "%s", str);
1096 free(str);
1097 }
1098 else
1099 {
1100 fprintf(out, "OID:%#B", &chunk);
1101 }
1102 }
1103 else
1104 {
1105 fprintf(out, "%s", oid_names[oid].name);
1106 }
1107 break;
1108 case AC_GROUP_TYPE_OCTETS:
1109 fprintf(out, "%#B", &chunk);
1110 break;
1111 }
1112 fprintf(out, "\n");
1113 }
1114 groups->destroy(groups);
1115 fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
1116 chunk = chunk_skip_zero(ac->get_serial(ac));
1117 fprintf(out, " serial: %#B\n", &chunk);
1118
1119 /* list validity */
1120 cert->get_validity(cert, &now, &notBefore, &notAfter);
1121 fprintf(out, " validity: not before %T, ", &notBefore, utc);
1122 if (now < notBefore)
1123 {
1124 fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
1125 }
1126 else
1127 {
1128 fprintf(out, "ok\n");
1129 }
1130 fprintf(out, " not after %T, ", &notAfter, utc);
1131 if (now > notAfter)
1132 {
1133 fprintf(out, "expired (%V ago)\n", &now, &notAfter);
1134 }
1135 else
1136 {
1137 fprintf(out, "ok");
1138 if (now > notAfter - AC_WARNING_INTERVAL * 60 * 60 * 24)
1139 {
1140 fprintf(out, " (expires in %V)", &now, &notAfter);
1141 }
1142 fprintf(out, " \n");
1143 }
1144
1145 /* list optional authorityKeyIdentifier */
1146 chunk = ac->get_authKeyIdentifier(ac);
1147 if (chunk.ptr)
1148 {
1149 fprintf(out, " authkey: %#B\n", &chunk);
1150 }
1151 }
1152 enumerator->destroy(enumerator);
1153 }
1154
1155 /**
1156 * list all X.509 CRLs
1157 */
1158 static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
1159 {
1160 bool first = TRUE;
1161 time_t thisUpdate, nextUpdate, now = time(NULL);
1162 enumerator_t *enumerator = list->create_enumerator(list);
1163 certificate_t *cert;
1164
1165 while (enumerator->enumerate(enumerator, (void**)&cert))
1166 {
1167 crl_t *crl = (crl_t*)cert;
1168 chunk_t chunk;
1169
1170 if (first)
1171 {
1172 fprintf(out, "\n");
1173 fprintf(out, "List of X.509 CRLs:\n");
1174 first = FALSE;
1175 }
1176 fprintf(out, "\n");
1177
1178 fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
1179
1180 /* list optional crlNumber */
1181 chunk = chunk_skip_zero(crl->get_serial(crl));
1182 if (chunk.ptr)
1183 {
1184 fprintf(out, " serial: %#B\n", &chunk);
1185 }
1186 if (crl->is_delta_crl(crl, &chunk))
1187 {
1188 chunk = chunk_skip_zero(chunk);
1189 fprintf(out, " delta for: %#B\n", &chunk);
1190 }
1191
1192 /* count the number of revoked certificates */
1193 {
1194 int count = 0;
1195 enumerator_t *enumerator = crl->create_enumerator(crl);
1196
1197 while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
1198 {
1199 count++;
1200 }
1201 fprintf(out, " revoked: %d certificate%s\n", count,
1202 (count == 1)? "" : "s");
1203 enumerator->destroy(enumerator);
1204 }
1205
1206 /* list validity */
1207 cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
1208 fprintf(out, " updates: this %T\n", &thisUpdate, utc);
1209 fprintf(out, " next %T, ", &nextUpdate, utc);
1210 if (now > nextUpdate)
1211 {
1212 fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
1213 }
1214 else
1215 {
1216 fprintf(out, "ok");
1217 if (now > nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24)
1218 {
1219 fprintf(out, " (expires in %V)", &now, &nextUpdate);
1220 }
1221 fprintf(out, " \n");
1222 }
1223
1224 /* list optional authorityKeyIdentifier */
1225 chunk = crl->get_authKeyIdentifier(crl);
1226 if (chunk.ptr)
1227 {
1228 fprintf(out, " authkey: %#B\n", &chunk);
1229 }
1230 }
1231 enumerator->destroy(enumerator);
1232 }
1233
1234 /**
1235 * list all OCSP responses
1236 */
1237 static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
1238 {
1239 bool first = TRUE, ok;
1240 enumerator_t *enumerator = list->create_enumerator(list);
1241 certificate_t *cert;
1242 time_t produced, usable, now = time(NULL);
1243
1244 while (enumerator->enumerate(enumerator, (void**)&cert))
1245 {
1246 if (first)
1247 {
1248 fprintf(out, "\n");
1249 fprintf(out, "List of OCSP responses:\n");
1250 fprintf(out, "\n");
1251 first = FALSE;
1252 }
1253 fprintf(out, " signer: \"%Y\"\n", cert->get_issuer(cert));
1254
1255 /* check validity */
1256 ok = cert->get_validity(cert, &now, &produced, &usable);
1257 fprintf(out, " validity: produced at %T\n", &produced, utc);
1258 fprintf(out, " usable till %T, ", &usable, utc);
1259 if (ok)
1260 {
1261 fprintf(out, "ok\n");
1262 }
1263 else
1264 {
1265 fprintf(out, "expired (%V ago)\n", &now, &usable);
1266 }
1267 }
1268 enumerator->destroy(enumerator);
1269 }
1270
1271 /**
1272 * Print the name of an algorithm plus the name of the plugin that registered it
1273 */
1274 static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type,
1275 const char *plugin_name)
1276 {
1277 char alg_name[BUF_LEN];
1278 int alg_name_len;
1279
1280 if (alg_names)
1281 {
1282 alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type,
1283 plugin_name);
1284 }
1285 else
1286 {
1287 alg_name_len = sprintf(alg_name, " [%s]", plugin_name);
1288 }
1289 if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
1290 {
1291 fprintf(out, "\n ");
1292 *len = 13;
1293 }
1294 fprintf(out, "%s", alg_name);
1295 *len += alg_name_len;
1296 }
1297
1298 /**
1299 * List of registered cryptographical algorithms
1300 */
1301 static void list_algs(FILE *out)
1302 {
1303 enumerator_t *enumerator;
1304 encryption_algorithm_t encryption;
1305 integrity_algorithm_t integrity;
1306 hash_algorithm_t hash;
1307 pseudo_random_function_t prf;
1308 diffie_hellman_group_t group;
1309 rng_quality_t quality;
1310 const char *plugin_name;
1311 int len;
1312
1313 fprintf(out, "\n");
1314 fprintf(out, "List of registered IKE algorithms:\n");
1315 fprintf(out, "\n encryption:");
1316 len = 13;
1317 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
1318 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1319 {
1320 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
1321 }
1322 enumerator->destroy(enumerator);
1323 fprintf(out, "\n integrity: ");
1324 len = 13;
1325 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
1326 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
1327 {
1328 print_alg(out, &len, integrity_algorithm_names, integrity, plugin_name);
1329 }
1330 enumerator->destroy(enumerator);
1331 fprintf(out, "\n aead: ");
1332 len = 13;
1333 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
1334 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1335 {
1336 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
1337 }
1338 enumerator->destroy(enumerator);
1339 fprintf(out, "\n hasher: ");
1340 len = 13;
1341 enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
1342 while (enumerator->enumerate(enumerator, &hash, &plugin_name))
1343 {
1344 print_alg(out, &len, hash_algorithm_names, hash, plugin_name);
1345 }
1346 enumerator->destroy(enumerator);
1347 fprintf(out, "\n prf: ");
1348 len = 13;
1349 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
1350 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
1351 {
1352 print_alg(out, &len, pseudo_random_function_names, prf, plugin_name);
1353 }
1354 enumerator->destroy(enumerator);
1355 fprintf(out, "\n dh-group: ");
1356 len = 13;
1357 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
1358 while (enumerator->enumerate(enumerator, &group, &plugin_name))
1359 {
1360 print_alg(out, &len, diffie_hellman_group_names, group, plugin_name);
1361 }
1362 enumerator->destroy(enumerator);
1363 fprintf(out, "\n random-gen:");
1364 len = 13;
1365 enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
1366 while (enumerator->enumerate(enumerator, &quality, &plugin_name))
1367 {
1368 print_alg(out, &len, rng_quality_names, quality, plugin_name);
1369 }
1370 enumerator->destroy(enumerator);
1371 fprintf(out, "\n nonce-gen: ");
1372 len = 13;
1373 enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
1374 while (enumerator->enumerate(enumerator, &plugin_name))
1375 {
1376 print_alg(out, &len, NULL, 0, plugin_name);
1377 }
1378 enumerator->destroy(enumerator);
1379 fprintf(out, "\n");
1380 }
1381
1382 /**
1383 * List loaded plugin information
1384 */
1385 static void list_plugins(FILE *out)
1386 {
1387 plugin_feature_t *features, *fp;
1388 enumerator_t *enumerator;
1389 linked_list_t *list;
1390 plugin_t *plugin;
1391 int count, i;
1392 bool loaded;
1393 char *str;
1394
1395 fprintf(out, "\n");
1396 fprintf(out, "List of loaded Plugins:\n");
1397 fprintf(out, "\n");
1398
1399 enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
1400 while (enumerator->enumerate(enumerator, &plugin, &list))
1401 {
1402 fprintf(out, "%s:\n", plugin->get_name(plugin));
1403 if (plugin->get_features)
1404 {
1405 count = plugin->get_features(plugin, &features);
1406 for (i = 0; i < count; i++)
1407 {
1408 str = plugin_feature_get_string(&features[i]);
1409 switch (features[i].kind)
1410 {
1411 case FEATURE_PROVIDE:
1412 fp = &features[i];
1413 loaded = list->find_first(list, NULL,
1414 (void**)&fp) == SUCCESS;
1415 fprintf(out, " %s%s\n",
1416 str, loaded ? "" : " (not loaded)");
1417 break;
1418 case FEATURE_DEPENDS:
1419 fprintf(out, " %s\n", str);
1420 break;
1421 case FEATURE_SDEPEND:
1422 fprintf(out, " %s (soft)\n", str);
1423 break;
1424 default:
1425 break;
1426 }
1427 free(str);
1428 }
1429 }
1430 list->destroy(list);
1431 }
1432 enumerator->destroy(enumerator);
1433 }
1434
1435 METHOD(stroke_list_t, list, void,
1436 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
1437 {
1438 linked_list_t *cert_list = NULL;
1439
1440 if (msg->list.flags & LIST_PUBKEYS)
1441 {
1442 linked_list_t *pubkey_list = create_unique_cert_list(CERT_TRUSTED_PUBKEY);
1443
1444 stroke_list_pubkeys(pubkey_list, msg->list.utc, out);
1445 pubkey_list->destroy_offset(pubkey_list, offsetof(certificate_t, destroy));
1446 }
1447 if (msg->list.flags & LIST_CERTS)
1448 {
1449 linked_list_t *pgp_list = create_unique_cert_list(CERT_GPG);
1450
1451 stroke_list_pgp(pgp_list, msg->list.utc, out);
1452 pgp_list->destroy_offset(pgp_list, offsetof(certificate_t, destroy));
1453 }
1454 if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS))
1455 {
1456 cert_list = create_unique_cert_list(CERT_X509);
1457 }
1458 if (msg->list.flags & LIST_CERTS)
1459 {
1460 stroke_list_certs(cert_list, "X.509 End Entity Certificates",
1461 X509_NONE, msg->list.utc, out);
1462 }
1463 if (msg->list.flags & LIST_CACERTS)
1464 {
1465 stroke_list_certs(cert_list, "X.509 CA Certificates",
1466 X509_CA, msg->list.utc, out);
1467 }
1468 if (msg->list.flags & LIST_OCSPCERTS)
1469 {
1470 stroke_list_certs(cert_list, "X.509 OCSP Signer Certificates",
1471 X509_OCSP_SIGNER, msg->list.utc, out);
1472 }
1473 if (msg->list.flags & LIST_AACERTS)
1474 {
1475 stroke_list_certs(cert_list, "X.509 AA Certificates",
1476 X509_AA, msg->list.utc, out);
1477 }
1478 DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy));
1479
1480 if (msg->list.flags & LIST_ACERTS)
1481 {
1482 linked_list_t *ac_list = create_unique_cert_list(CERT_X509_AC);
1483
1484 stroke_list_acerts(ac_list, msg->list.utc, out);
1485 ac_list->destroy_offset(ac_list, offsetof(certificate_t, destroy));
1486 }
1487 if (msg->list.flags & LIST_CRLS)
1488 {
1489 linked_list_t *crl_list = create_unique_cert_list(CERT_X509_CRL);
1490
1491 stroke_list_crls(crl_list, msg->list.utc, out);
1492 crl_list->destroy_offset(crl_list, offsetof(certificate_t, destroy));
1493 }
1494 if (msg->list.flags & LIST_OCSP)
1495 {
1496 linked_list_t *ocsp_list = create_unique_cert_list(CERT_X509_OCSP_RESPONSE);
1497
1498 stroke_list_ocsp(ocsp_list, msg->list.utc, out);
1499
1500 ocsp_list->destroy_offset(ocsp_list, offsetof(certificate_t, destroy));
1501 }
1502 if (msg->list.flags & LIST_ALGS)
1503 {
1504 list_algs(out);
1505 }
1506 if (msg->list.flags & LIST_PLUGINS)
1507 {
1508 list_plugins(out);
1509 }
1510 }
1511
1512 /**
1513 * Print leases of a single pool
1514 */
1515 static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
1516 host_t *address, u_int size, u_int online, u_int offline)
1517 {
1518 enumerator_t *enumerator;
1519 identification_t *id;
1520 host_t *lease;
1521 bool on;
1522 int found = 0;
1523
1524 fprintf(out, "Leases in pool '%s', usage: %u/%u, %u online\n",
1525 pool, online + offline, size, online);
1526 enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
1527 while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
1528 {
1529 if (!address || address->ip_equals(address, lease))
1530 {
1531 fprintf(out, " %15H %s '%Y'\n",
1532 lease, on ? "online" : "offline", id);
1533 found++;
1534 }
1535 }
1536 enumerator->destroy(enumerator);
1537 if (!found)
1538 {
1539 fprintf(out, " no matching leases found\n");
1540 }
1541 }
1542
1543 METHOD(stroke_list_t, leases, void,
1544 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
1545 {
1546 enumerator_t *enumerator;
1547 u_int size, offline, online;
1548 host_t *address = NULL;
1549 char *pool;
1550 int found = 0;
1551
1552 if (msg->leases.address)
1553 {
1554 address = host_create_from_string(msg->leases.address, 0);
1555 }
1556
1557 enumerator = this->attribute->create_pool_enumerator(this->attribute);
1558 while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
1559 {
1560 if (!msg->leases.pool || streq(msg->leases.pool, pool))
1561 {
1562 pool_leases(this, out, pool, address, size, online, offline);
1563 found++;
1564 }
1565 }
1566 enumerator->destroy(enumerator);
1567 if (!found)
1568 {
1569 if (msg->leases.pool)
1570 {
1571 fprintf(out, "pool '%s' not found\n", msg->leases.pool);
1572 }
1573 else
1574 {
1575 fprintf(out, "no pools found\n");
1576 }
1577 }
1578 DESTROY_IF(address);
1579 }
1580
1581 METHOD(stroke_list_t, destroy, void,
1582 private_stroke_list_t *this)
1583 {
1584 free(this);
1585 }
1586
1587 /*
1588 * see header file
1589 */
1590 stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
1591 {
1592 private_stroke_list_t *this;
1593
1594 INIT(this,
1595 .public = {
1596 .list = _list,
1597 .status = _status,
1598 .leases = _leases,
1599 .destroy = _destroy,
1600 },
1601 .uptime = time_monotonic(NULL),
1602 .swan = "strong",
1603 .attribute = attribute,
1604 );
1605
1606 if (lib->settings->get_bool(lib->settings,
1607 "charon.i_dont_care_about_security_and_use_aggressive_mode_psk", FALSE))
1608 {
1609 this->swan = "weak";
1610 }
1611
1612 return &this->public;
1613 }