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