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