14233c975682f0bc8dff2abf81f3862637f071cb
[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 alg, ks;
247 bool first = TRUE;
248
249 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
250 &alg, &ks) && alg != ENCR_UNDEFINED)
251 {
252 fprintf(out, "%N", encryption_algorithm_names, alg);
253 first = FALSE;
254 if (ks)
255 {
256 fprintf(out, "_%u", ks);
257 }
258 }
259 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
260 &alg, &ks) && alg != AUTH_UNDEFINED)
261 {
262 fprintf(out, "%s%N", first ? "" : "/",
263 integrity_algorithm_names, alg);
264 if (ks)
265 {
266 fprintf(out, "_%u", ks);
267 }
268 }
269 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
270 &alg, NULL))
271 {
272 fprintf(out, "/%N", diffie_hellman_group_names, alg);
273 }
274 if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
275 &alg, NULL) && alg == 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 all X.509 certificates matching the flags
765 */
766 static void stroke_list_x509_certs(linked_list_t *list, x509_flag_t flag)
767 {
768 enumerator_t *enumerator;
769 certificate_t *cert;
770
771 enumerator = list->create_enumerator(list);
772 while (enumerator->enumerate(enumerator, (void**)&cert))
773 {
774 x509_t *x509 = (x509_t*)cert;
775 x509_flag_t flags = x509->get_flags(x509) & X509_ANY;
776
777 /* list only if flag is set or flag == 0 */
778 if ((flags & flag) || flags == flag)
779 {
780 cert_printer->print_caption(cert_printer, CERT_X509, flag);
781 cert_printer->print(cert_printer, cert, has_privkey(cert));
782 }
783 }
784 enumerator->destroy(enumerator);
785 }
786
787 /**
788 * list all other certificates types
789 */
790 static void stroke_list_other_certs(certificate_type_t type)
791 {
792 enumerator_t *enumerator;
793 certificate_t *cert;
794 linked_list_t *list;
795
796 list = create_unique_cert_list(type);
797
798 enumerator = list->create_enumerator(list);
799 while (enumerator->enumerate(enumerator, &cert))
800 {
801 cert_printer->print_caption(cert_printer, cert->get_type(cert), X509_NONE);
802 cert_printer->print(cert_printer, cert, has_privkey(cert));
803 }
804 enumerator->destroy(enumerator);
805
806 list->destroy_offset(list, offsetof(certificate_t, destroy));
807 }
808
809 /**
810 * Print the name of an algorithm plus the name of the plugin that registered it
811 */
812 static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type,
813 const char *plugin_name)
814 {
815 char alg_name[BUF_LEN];
816 int alg_name_len;
817
818 if (alg_names)
819 {
820 alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type,
821 plugin_name);
822 }
823 else
824 {
825 alg_name_len = sprintf(alg_name, " [%s]", plugin_name);
826 }
827 if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
828 {
829 fprintf(out, "\n ");
830 *len = 13;
831 }
832 fprintf(out, "%s", alg_name);
833 *len += alg_name_len;
834 }
835
836 /**
837 * List of registered cryptographical algorithms
838 */
839 static void list_algs(FILE *out)
840 {
841 enumerator_t *enumerator;
842 encryption_algorithm_t encryption;
843 integrity_algorithm_t integrity;
844 hash_algorithm_t hash;
845 pseudo_random_function_t prf;
846 diffie_hellman_group_t group;
847 rng_quality_t quality;
848 const char *plugin_name;
849 int len;
850
851 fprintf(out, "\n");
852 fprintf(out, "List of registered IKE algorithms:\n");
853 fprintf(out, "\n encryption:");
854 len = 13;
855 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
856 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
857 {
858 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
859 }
860 enumerator->destroy(enumerator);
861 fprintf(out, "\n integrity: ");
862 len = 13;
863 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
864 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
865 {
866 print_alg(out, &len, integrity_algorithm_names, integrity, plugin_name);
867 }
868 enumerator->destroy(enumerator);
869 fprintf(out, "\n aead: ");
870 len = 13;
871 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
872 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
873 {
874 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
875 }
876 enumerator->destroy(enumerator);
877 fprintf(out, "\n hasher: ");
878 len = 13;
879 enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
880 while (enumerator->enumerate(enumerator, &hash, &plugin_name))
881 {
882 print_alg(out, &len, hash_algorithm_names, hash, plugin_name);
883 }
884 enumerator->destroy(enumerator);
885 fprintf(out, "\n prf: ");
886 len = 13;
887 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
888 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
889 {
890 print_alg(out, &len, pseudo_random_function_names, prf, plugin_name);
891 }
892 enumerator->destroy(enumerator);
893 fprintf(out, "\n dh-group: ");
894 len = 13;
895 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
896 while (enumerator->enumerate(enumerator, &group, &plugin_name))
897 {
898 print_alg(out, &len, diffie_hellman_group_names, group, plugin_name);
899 }
900 enumerator->destroy(enumerator);
901 fprintf(out, "\n random-gen:");
902 len = 13;
903 enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
904 while (enumerator->enumerate(enumerator, &quality, &plugin_name))
905 {
906 print_alg(out, &len, rng_quality_names, quality, plugin_name);
907 }
908 enumerator->destroy(enumerator);
909 fprintf(out, "\n nonce-gen: ");
910 len = 13;
911 enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
912 while (enumerator->enumerate(enumerator, &plugin_name))
913 {
914 print_alg(out, &len, NULL, 0, plugin_name);
915 }
916 enumerator->destroy(enumerator);
917 fprintf(out, "\n");
918 }
919
920 /**
921 * List loaded plugin information
922 */
923 static void list_plugins(FILE *out)
924 {
925 plugin_feature_t *features, *fp;
926 enumerator_t *enumerator;
927 linked_list_t *list;
928 plugin_t *plugin;
929 int count, i;
930 bool loaded;
931 char *str;
932
933 fprintf(out, "\n");
934 fprintf(out, "List of loaded Plugins:\n");
935 fprintf(out, "\n");
936
937 enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
938 while (enumerator->enumerate(enumerator, &plugin, &list))
939 {
940 fprintf(out, "%s:\n", plugin->get_name(plugin));
941 if (plugin->get_features)
942 {
943 count = plugin->get_features(plugin, &features);
944 for (i = 0; i < count; i++)
945 {
946 str = plugin_feature_get_string(&features[i]);
947 switch (features[i].kind)
948 {
949 case FEATURE_PROVIDE:
950 fp = &features[i];
951 loaded = list->find_first(list, NULL,
952 (void**)&fp) == SUCCESS;
953 fprintf(out, " %s%s\n",
954 str, loaded ? "" : " (not loaded)");
955 break;
956 case FEATURE_DEPENDS:
957 fprintf(out, " %s\n", str);
958 break;
959 case FEATURE_SDEPEND:
960 fprintf(out, " %s (soft)\n", str);
961 break;
962 default:
963 break;
964 }
965 free(str);
966 }
967 }
968 list->destroy(list);
969 }
970 enumerator->destroy(enumerator);
971 }
972
973 METHOD(stroke_list_t, list, void,
974 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
975 {
976 linked_list_t *cert_list = NULL;
977
978 cert_printer = certificate_printer_create(out, TRUE, msg->list.utc);
979
980 if (msg->list.flags & LIST_PUBKEYS)
981 {
982 stroke_list_other_certs(CERT_TRUSTED_PUBKEY);
983 }
984 if (msg->list.flags & LIST_CERTS)
985 {
986 stroke_list_other_certs(CERT_GPG);
987 }
988 if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS))
989 {
990 cert_list = create_unique_cert_list(CERT_X509);
991 }
992 if (msg->list.flags & LIST_CERTS)
993 {
994 stroke_list_x509_certs(cert_list, X509_NONE);
995 }
996 if (msg->list.flags & LIST_CACERTS)
997 {
998 stroke_list_x509_certs(cert_list, X509_CA);
999 }
1000 if (msg->list.flags & LIST_OCSPCERTS)
1001 {
1002 stroke_list_x509_certs(cert_list, X509_OCSP_SIGNER);
1003 }
1004 if (msg->list.flags & LIST_AACERTS)
1005 {
1006 stroke_list_x509_certs(cert_list, X509_AA);
1007 }
1008 DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy));
1009
1010 if (msg->list.flags & LIST_ACERTS)
1011 {
1012 stroke_list_other_certs(CERT_X509_AC);
1013 }
1014 if (msg->list.flags & LIST_CRLS)
1015 {
1016 stroke_list_other_certs(CERT_X509_CRL);
1017 }
1018 if (msg->list.flags & LIST_OCSP)
1019 {
1020 stroke_list_other_certs(CERT_X509_OCSP_RESPONSE);
1021 }
1022 if (msg->list.flags & LIST_ALGS)
1023 {
1024 list_algs(out);
1025 }
1026 if (msg->list.flags & LIST_PLUGINS)
1027 {
1028 list_plugins(out);
1029 }
1030 cert_printer->destroy(cert_printer);
1031 cert_printer = NULL;
1032 }
1033
1034 /**
1035 * Print leases of a single pool
1036 */
1037 static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
1038 host_t *address, u_int size, u_int online, u_int offline)
1039 {
1040 enumerator_t *enumerator;
1041 identification_t *id;
1042 host_t *lease;
1043 bool on;
1044 int found = 0;
1045
1046 fprintf(out, "Leases in pool '%s', usage: %u/%u, %u online\n",
1047 pool, online + offline, size, online);
1048 enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
1049 while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
1050 {
1051 if (!address || address->ip_equals(address, lease))
1052 {
1053 fprintf(out, " %15H %s '%Y'\n",
1054 lease, on ? "online" : "offline", id);
1055 found++;
1056 }
1057 }
1058 enumerator->destroy(enumerator);
1059 if (!found)
1060 {
1061 fprintf(out, " no matching leases found\n");
1062 }
1063 }
1064
1065 METHOD(stroke_list_t, leases, void,
1066 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
1067 {
1068 enumerator_t *enumerator;
1069 u_int size, offline, online;
1070 host_t *address = NULL;
1071 char *pool;
1072 int found = 0;
1073
1074 if (msg->leases.address)
1075 {
1076 address = host_create_from_string(msg->leases.address, 0);
1077 }
1078
1079 enumerator = this->attribute->create_pool_enumerator(this->attribute);
1080 while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
1081 {
1082 if (!msg->leases.pool || streq(msg->leases.pool, pool))
1083 {
1084 pool_leases(this, out, pool, address, size, online, offline);
1085 found++;
1086 }
1087 }
1088 enumerator->destroy(enumerator);
1089 if (!found)
1090 {
1091 if (msg->leases.pool)
1092 {
1093 fprintf(out, "pool '%s' not found\n", msg->leases.pool);
1094 }
1095 else
1096 {
1097 fprintf(out, "no pools found\n");
1098 }
1099 }
1100 DESTROY_IF(address);
1101 }
1102
1103 METHOD(stroke_list_t, destroy, void,
1104 private_stroke_list_t *this)
1105 {
1106 free(this);
1107 }
1108
1109 /*
1110 * see header file
1111 */
1112 stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
1113 {
1114 private_stroke_list_t *this;
1115
1116 INIT(this,
1117 .public = {
1118 .list = _list,
1119 .status = _status,
1120 .leases = _leases,
1121 .destroy = _destroy,
1122 },
1123 .uptime = time_monotonic(NULL),
1124 .swan = "strong",
1125 .attribute = attribute,
1126 );
1127
1128 if (lib->settings->get_bool(lib->settings,
1129 "charon.i_dont_care_about_security_and_use_aggressive_mode_psk", FALSE))
1130 {
1131 this->swan = "weak";
1132 }
1133
1134 return &this->public;
1135 }