Processor job scheduling respects job priority classes
[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, bool all)
393 {
394 enumerator_t *enumerator, *children;
395 ike_cfg_t *ike_cfg;
396 child_cfg_t *child_cfg;
397 child_sa_t *child_sa;
398 ike_sa_t *ike_sa;
399 bool first, found = FALSE;
400 char *name = msg->status.name;
401
402 if (all)
403 {
404 peer_cfg_t *peer_cfg;
405 plugin_t *plugin;
406 char *pool;
407 host_t *host;
408 u_int32_t dpd;
409 time_t since, now;
410 u_int size, online, offline, i;
411 now = time_monotonic(NULL);
412 since = time(NULL) - (now - this->uptime);
413
414 fprintf(out, "Status of IKEv2 charon daemon (strongSwan "VERSION"):\n");
415 fprintf(out, " uptime: %V, since %T\n", &now, &this->uptime, &since, FALSE);
416 #ifdef HAVE_MALLINFO
417 {
418 struct mallinfo mi = mallinfo();
419
420 fprintf(out, " malloc: sbrk %d, mmap %d, used %d, free %d\n",
421 mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks);
422 }
423 #endif /* HAVE_MALLINFO */
424 fprintf(out, " worker threads: %d idle of %d,",
425 lib->processor->get_idle_threads(lib->processor),
426 lib->processor->get_total_threads(lib->processor));
427 fprintf(out, " job queue load: ");
428 for (i = 0; i < JOB_PRIO_MAX; i++)
429 {
430 fprintf(out, "%s%d", i == 0 ? "" : "/",
431 lib->processor->get_job_load(lib->processor, i));
432 }
433 fprintf(out, ", scheduled events: %d\n",
434 lib->scheduler->get_job_load(lib->scheduler));
435 fprintf(out, " loaded plugins: ");
436 enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
437 while (enumerator->enumerate(enumerator, &plugin))
438 {
439 fprintf(out, "%s ", plugin->get_name(plugin));
440 }
441 enumerator->destroy(enumerator);
442 fprintf(out, "\n");
443
444 first = TRUE;
445 enumerator = this->attribute->create_pool_enumerator(this->attribute);
446 while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
447 {
448 if (name && !streq(name, pool))
449 {
450 continue;
451 }
452 if (first)
453 {
454 first = FALSE;
455 fprintf(out, "Virtual IP pools (size/online/offline):\n");
456 }
457 fprintf(out, " %s: %u/%u/%u\n", pool, size, online, offline);
458 }
459 enumerator->destroy(enumerator);
460
461 enumerator = hydra->kernel_interface->create_address_enumerator(
462 hydra->kernel_interface, FALSE, FALSE);
463 fprintf(out, "Listening IP addresses:\n");
464 while (enumerator->enumerate(enumerator, (void**)&host))
465 {
466 fprintf(out, " %H\n", host);
467 }
468 enumerator->destroy(enumerator);
469
470 fprintf(out, "Connections:\n");
471 enumerator = charon->backends->create_peer_cfg_enumerator(
472 charon->backends, NULL, NULL, NULL, NULL);
473 while (enumerator->enumerate(enumerator, &peer_cfg))
474 {
475 if (peer_cfg->get_ike_version(peer_cfg) != 2 ||
476 (name && !streq(name, peer_cfg->get_name(peer_cfg))))
477 {
478 continue;
479 }
480
481 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
482 fprintf(out, "%12s: %s...%s", peer_cfg->get_name(peer_cfg),
483 ike_cfg->get_my_addr(ike_cfg), ike_cfg->get_other_addr(ike_cfg));
484
485 dpd = peer_cfg->get_dpd(peer_cfg);
486 if (dpd)
487 {
488 fprintf(out, ", dpddelay=%us", dpd);
489 }
490 fprintf(out, "\n");
491
492 log_auth_cfgs(out, peer_cfg, TRUE);
493 log_auth_cfgs(out, peer_cfg, FALSE);
494
495 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
496 while (children->enumerate(children, &child_cfg))
497 {
498 linked_list_t *my_ts, *other_ts;
499
500 my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
501 other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
502 fprintf(out, "%12s: child: %#R=== %#R", child_cfg->get_name(child_cfg),
503 my_ts, other_ts);
504 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
505 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
506
507 if (dpd)
508 {
509 fprintf(out, ", dpdaction=%N", action_names,
510 child_cfg->get_dpd_action(child_cfg));
511 }
512 fprintf(out, "\n");
513 }
514 children->destroy(children);
515 }
516 enumerator->destroy(enumerator);
517 }
518
519 first = TRUE;
520 enumerator = charon->traps->create_enumerator(charon->traps);
521 while (enumerator->enumerate(enumerator, NULL, &child_sa))
522 {
523 if (first)
524 {
525 fprintf(out, "Routed Connections:\n");
526 first = FALSE;
527 }
528 log_child_sa(out, child_sa, all);
529 }
530 enumerator->destroy(enumerator);
531
532 fprintf(out, "Security Associations:\n");
533 enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
534 while (enumerator->enumerate(enumerator, &ike_sa))
535 {
536 bool ike_printed = FALSE;
537 iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
538
539 if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
540 {
541 log_ike_sa(out, ike_sa, all);
542 found = TRUE;
543 ike_printed = TRUE;
544 }
545
546 while (children->iterate(children, (void**)&child_sa))
547 {
548 if (name == NULL || streq(name, child_sa->get_name(child_sa)))
549 {
550 if (!ike_printed)
551 {
552 log_ike_sa(out, ike_sa, all);
553 found = TRUE;
554 ike_printed = TRUE;
555 }
556 log_child_sa(out, child_sa, all);
557 }
558 }
559 children->destroy(children);
560 }
561 enumerator->destroy(enumerator);
562
563 if (!found)
564 {
565 if (name)
566 {
567 fprintf(out, " no match\n");
568 }
569 else
570 {
571 fprintf(out, " none\n");
572 }
573 }
574 }
575
576 /**
577 * create a unique certificate list without duplicates
578 * certicates having the same issuer are grouped together.
579 */
580 static linked_list_t* create_unique_cert_list(certificate_type_t type)
581 {
582 linked_list_t *list = linked_list_create();
583 enumerator_t *enumerator = lib->credmgr->create_cert_enumerator(
584 lib->credmgr, type, KEY_ANY, NULL, FALSE);
585 certificate_t *cert;
586
587 while (enumerator->enumerate(enumerator, (void**)&cert))
588 {
589 iterator_t *iterator = list->create_iterator(list, TRUE);
590 identification_t *issuer = cert->get_issuer(cert);
591 bool previous_same, same = FALSE, last = TRUE;
592 certificate_t *list_cert;
593
594 while (iterator->iterate(iterator, (void**)&list_cert))
595 {
596 /* exit if we have a duplicate? */
597 if (list_cert->equals(list_cert, cert))
598 {
599 last = FALSE;
600 break;
601 }
602 /* group certificates with same issuer */
603 previous_same = same;
604 same = list_cert->has_issuer(list_cert, issuer);
605 if (previous_same && !same)
606 {
607 iterator->insert_before(iterator, (void *)cert->get_ref(cert));
608 last = FALSE;
609 break;
610 }
611 }
612 iterator->destroy(iterator);
613
614 if (last)
615 {
616 list->insert_last(list, (void *)cert->get_ref(cert));
617 }
618 }
619 enumerator->destroy(enumerator);
620 return list;
621 }
622
623 /**
624 * Print a single public key.
625 */
626 static void list_public_key(public_key_t *public, FILE *out)
627 {
628 private_key_t *private = NULL;
629 chunk_t keyid;
630 identification_t *id;
631 auth_cfg_t *auth;
632
633 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
634 {
635 id = identification_create_from_encoding(ID_KEY_ID, keyid);
636 auth = auth_cfg_create();
637 private = lib->credmgr->get_private(lib->credmgr,
638 public->get_type(public), id, auth);
639 auth->destroy(auth);
640 id->destroy(id);
641 }
642
643 fprintf(out, " pubkey: %N %d bits%s\n",
644 key_type_names, public->get_type(public),
645 public->get_keysize(public),
646 private ? ", has private key" : "");
647 if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
648 {
649 fprintf(out, " keyid: %#B\n", &keyid);
650 }
651 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
652 {
653 fprintf(out, " subjkey: %#B\n", &keyid);
654 }
655 DESTROY_IF(private);
656 }
657
658 /**
659 * list all raw public keys
660 */
661 static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
662 {
663 bool first = TRUE;
664
665 enumerator_t *enumerator = list->create_enumerator(list);
666 certificate_t *cert;
667
668 while (enumerator->enumerate(enumerator, (void**)&cert))
669 {
670 public_key_t *public = cert->get_public_key(cert);
671
672 if (public)
673 {
674 if (first)
675 {
676 fprintf(out, "\n");
677 fprintf(out, "List of Raw Public Keys:\n");
678 first = FALSE;
679 }
680 fprintf(out, "\n");
681
682 list_public_key(public, out);
683 public->destroy(public);
684 }
685 }
686 enumerator->destroy(enumerator);
687 }
688
689 /**
690 * list OpenPGP certificates
691 */
692 static void stroke_list_pgp(linked_list_t *list,bool utc, FILE *out)
693 {
694 bool first = TRUE;
695 time_t now = time(NULL);
696 enumerator_t *enumerator = list->create_enumerator(list);
697 certificate_t *cert;
698
699 while (enumerator->enumerate(enumerator, (void**)&cert))
700 {
701 time_t created, until;
702 public_key_t *public;
703 pgp_certificate_t *pgp_cert = (pgp_certificate_t*)cert;
704 chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
705
706 if (first)
707 {
708
709 fprintf(out, "\n");
710 fprintf(out, "List of PGP End Entity Certificates:\n");
711 first = FALSE;
712 }
713 fprintf(out, "\n");
714 fprintf(out, " userid: '%Y'\n", cert->get_subject(cert));
715
716 fprintf(out, " digest: %#B\n", &fingerprint);
717
718 /* list validity */
719 cert->get_validity(cert, &now, &created, &until);
720 fprintf(out, " created: %T\n", &created, utc);
721 fprintf(out, " until: %T%s\n", &until, utc,
722 (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
723
724 public = cert->get_public_key(cert);
725 if (public)
726 {
727 list_public_key(public, out);
728 public->destroy(public);
729 }
730 }
731 enumerator->destroy(enumerator);
732 }
733
734 /**
735 * list all X.509 certificates matching the flags
736 */
737 static void stroke_list_certs(linked_list_t *list, char *label,
738 x509_flag_t flags, bool utc, FILE *out)
739 {
740 bool first = TRUE;
741 time_t now = time(NULL);
742 enumerator_t *enumerator;
743 certificate_t *cert;
744 x509_flag_t flag_mask;
745
746 /* mask all auxiliary flags */
747 flag_mask = ~(X509_SERVER_AUTH | X509_CLIENT_AUTH |
748 X509_SELF_SIGNED | X509_IP_ADDR_BLOCKS );
749
750 enumerator = list->create_enumerator(list);
751 while (enumerator->enumerate(enumerator, (void**)&cert))
752 {
753 x509_t *x509 = (x509_t*)cert;
754 x509_flag_t x509_flags = x509->get_flags(x509) & flag_mask;
755
756 /* list only if flag is set or flag == 0 */
757 if ((x509_flags & flags) || (x509_flags == flags))
758 {
759 enumerator_t *enumerator;
760 identification_t *altName;
761 bool first_altName = TRUE;
762 u_int pathlen;
763 chunk_t serial, authkey;
764 time_t notBefore, notAfter;
765 public_key_t *public;
766
767 if (first)
768 {
769 fprintf(out, "\n");
770 fprintf(out, "List of %s:\n", label);
771 first = FALSE;
772 }
773 fprintf(out, "\n");
774
775 /* list subjectAltNames */
776 enumerator = x509->create_subjectAltName_enumerator(x509);
777 while (enumerator->enumerate(enumerator, (void**)&altName))
778 {
779 if (first_altName)
780 {
781 fprintf(out, " altNames: ");
782 first_altName = FALSE;
783 }
784 else
785 {
786 fprintf(out, ", ");
787 }
788 fprintf(out, "%Y", altName);
789 }
790 if (!first_altName)
791 {
792 fprintf(out, "\n");
793 }
794 enumerator->destroy(enumerator);
795
796 fprintf(out, " subject: \"%Y\"\n", cert->get_subject(cert));
797 fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
798 serial = x509->get_serial(x509);
799 fprintf(out, " serial: %#B\n", &serial);
800
801 /* list validity */
802 cert->get_validity(cert, &now, &notBefore, &notAfter);
803 fprintf(out, " validity: not before %T, ", &notBefore, utc);
804 if (now < notBefore)
805 {
806 fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
807 }
808 else
809 {
810 fprintf(out, "ok\n");
811 }
812 fprintf(out, " not after %T, ", &notAfter, utc);
813 if (now > notAfter)
814 {
815 fprintf(out, "expired (%V ago)\n", &now, &notAfter);
816 }
817 else
818 {
819 fprintf(out, "ok");
820 if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
821 {
822 fprintf(out, " (expires in %V)", &now, &notAfter);
823 }
824 fprintf(out, " \n");
825 }
826
827 public = cert->get_public_key(cert);
828 if (public)
829 {
830 list_public_key(public, out);
831 public->destroy(public);
832 }
833
834 /* list optional authorityKeyIdentifier */
835 authkey = x509->get_authKeyIdentifier(x509);
836 if (authkey.ptr)
837 {
838 fprintf(out, " authkey: %#B\n", &authkey);
839 }
840
841 /* list optional pathLenConstraint */
842 pathlen = x509->get_constraint(x509, X509_PATH_LEN);
843 if (pathlen != X509_NO_CONSTRAINT)
844 {
845 fprintf(out, " pathlen: %u\n", pathlen);
846 }
847
848 /* list optional ipAddrBlocks */
849 if (x509->get_flags(x509) & X509_IP_ADDR_BLOCKS)
850 {
851 traffic_selector_t *ipAddrBlock;
852 bool first_ipAddrBlock = TRUE;
853
854 fprintf(out, " addresses: ");
855 enumerator = x509->create_ipAddrBlock_enumerator(x509);
856 while (enumerator->enumerate(enumerator, &ipAddrBlock))
857 {
858 if (first_ipAddrBlock)
859 {
860 first_ipAddrBlock = FALSE;
861 }
862 else
863 {
864 fprintf(out, ", ");
865 }
866 fprintf(out, "%R", ipAddrBlock);
867 }
868 enumerator->destroy(enumerator);
869 fprintf(out, "\n");
870 }
871 }
872 }
873 enumerator->destroy(enumerator);
874 }
875
876 /**
877 * list all X.509 attribute certificates
878 */
879 static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
880 {
881 bool first = TRUE;
882 time_t thisUpdate, nextUpdate, now = time(NULL);
883 enumerator_t *enumerator = list->create_enumerator(list);
884 certificate_t *cert;
885
886 while (enumerator->enumerate(enumerator, (void**)&cert))
887 {
888 ac_t *ac = (ac_t*)cert;
889 identification_t *id;
890 ietf_attributes_t *groups;
891 chunk_t chunk;
892
893 if (first)
894 {
895 fprintf(out, "\n");
896 fprintf(out, "List of X.509 Attribute Certificates:\n");
897 first = FALSE;
898 }
899 fprintf(out, "\n");
900
901 id = cert->get_subject(cert);
902 if (id)
903 {
904 fprintf(out, " holder: \"%Y\"\n", id);
905 }
906 id = ac->get_holderIssuer(ac);
907 if (id)
908 {
909 fprintf(out, " hissuer: \"%Y\"\n", id);
910 }
911 chunk = ac->get_holderSerial(ac);
912 if (chunk.ptr)
913 {
914 fprintf(out, " hserial: %#B\n", &chunk);
915 }
916 groups = ac->get_groups(ac);
917 if (groups)
918 {
919 fprintf(out, " groups: %s\n", groups->get_string(groups));
920 groups->destroy(groups);
921 }
922 fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
923 chunk = ac->get_serial(ac);
924 fprintf(out, " serial: %#B\n", &chunk);
925
926 /* list validity */
927 cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
928 fprintf(out, " updates: this %T\n", &thisUpdate, utc);
929 fprintf(out, " next %T, ", &nextUpdate, utc);
930 if (now > nextUpdate)
931 {
932 fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
933 }
934 else
935 {
936 fprintf(out, "ok");
937 if (now > nextUpdate - AC_WARNING_INTERVAL * 60 * 60 * 24)
938 {
939 fprintf(out, " (expires in %V)", &now, &nextUpdate);
940 }
941 fprintf(out, " \n");
942 }
943
944 /* list optional authorityKeyIdentifier */
945 chunk = ac->get_authKeyIdentifier(ac);
946 if (chunk.ptr)
947 {
948 fprintf(out, " authkey: %#B\n", &chunk);
949 }
950 }
951 enumerator->destroy(enumerator);
952 }
953
954 /**
955 * list all X.509 CRLs
956 */
957 static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
958 {
959 bool first = TRUE;
960 time_t thisUpdate, nextUpdate, now = time(NULL);
961 enumerator_t *enumerator = list->create_enumerator(list);
962 certificate_t *cert;
963
964 while (enumerator->enumerate(enumerator, (void**)&cert))
965 {
966 crl_t *crl = (crl_t*)cert;
967 chunk_t chunk;
968
969 if (first)
970 {
971 fprintf(out, "\n");
972 fprintf(out, "List of X.509 CRLs:\n");
973 first = FALSE;
974 }
975 fprintf(out, "\n");
976
977 fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
978
979 /* list optional crlNumber */
980 chunk = crl->get_serial(crl);
981 if (chunk.ptr)
982 {
983 fprintf(out, " serial: %#B\n", &chunk);
984 }
985 if (crl->is_delta_crl(crl, &chunk))
986 {
987 fprintf(out, " delta for: %#B\n", &chunk);
988 }
989
990 /* count the number of revoked certificates */
991 {
992 int count = 0;
993 enumerator_t *enumerator = crl->create_enumerator(crl);
994
995 while (enumerator->enumerate(enumerator, NULL, NULL, NULL))
996 {
997 count++;
998 }
999 fprintf(out, " revoked: %d certificate%s\n", count,
1000 (count == 1)? "" : "s");
1001 enumerator->destroy(enumerator);
1002 }
1003
1004 /* list validity */
1005 cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
1006 fprintf(out, " updates: this %T\n", &thisUpdate, utc);
1007 fprintf(out, " next %T, ", &nextUpdate, utc);
1008 if (now > nextUpdate)
1009 {
1010 fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
1011 }
1012 else
1013 {
1014 fprintf(out, "ok");
1015 if (now > nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24)
1016 {
1017 fprintf(out, " (expires in %V)", &now, &nextUpdate);
1018 }
1019 fprintf(out, " \n");
1020 }
1021
1022 /* list optional authorityKeyIdentifier */
1023 chunk = crl->get_authKeyIdentifier(crl);
1024 if (chunk.ptr)
1025 {
1026 fprintf(out, " authkey: %#B\n", &chunk);
1027 }
1028 }
1029 enumerator->destroy(enumerator);
1030 }
1031
1032 /**
1033 * list all OCSP responses
1034 */
1035 static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
1036 {
1037 bool first = TRUE, ok;
1038 enumerator_t *enumerator = list->create_enumerator(list);
1039 certificate_t *cert;
1040 time_t produced, usable, now = time(NULL);
1041
1042 while (enumerator->enumerate(enumerator, (void**)&cert))
1043 {
1044 if (first)
1045 {
1046 fprintf(out, "\n");
1047 fprintf(out, "List of OCSP responses:\n");
1048 fprintf(out, "\n");
1049 first = FALSE;
1050 }
1051 fprintf(out, " signer: \"%Y\"\n", cert->get_issuer(cert));
1052
1053 /* check validity */
1054 ok = cert->get_validity(cert, &now, &produced, &usable);
1055 fprintf(out, " validity: produced at %T\n", &produced, utc);
1056 fprintf(out, " usable till %T, ", &usable, utc);
1057 if (ok)
1058 {
1059 fprintf(out, "ok\n");
1060 }
1061 else
1062 {
1063 fprintf(out, "expired (%V ago)\n", &now, &usable);
1064 }
1065 }
1066 enumerator->destroy(enumerator);
1067 }
1068
1069 /**
1070 * Print the name of an algorithm plus the name of the plugin that registered it
1071 */
1072 static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type,
1073 const char *plugin_name)
1074 {
1075 char alg_name[BUF_LEN];
1076 int alg_name_len;
1077
1078 alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type, plugin_name);
1079 if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
1080 {
1081 fprintf(out, "\n ");
1082 *len = 13;
1083 }
1084 fprintf(out, "%s", alg_name);
1085 *len += alg_name_len;
1086 }
1087
1088 /**
1089 * List of registered cryptographical algorithms
1090 */
1091 static void list_algs(FILE *out)
1092 {
1093 enumerator_t *enumerator;
1094 encryption_algorithm_t encryption;
1095 integrity_algorithm_t integrity;
1096 hash_algorithm_t hash;
1097 pseudo_random_function_t prf;
1098 diffie_hellman_group_t group;
1099 rng_quality_t quality;
1100 const char *plugin_name;
1101 int len;
1102
1103 fprintf(out, "\n");
1104 fprintf(out, "List of registered IKEv2 Algorithms:\n");
1105 fprintf(out, "\n encryption:");
1106 len = 13;
1107 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
1108 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1109 {
1110 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
1111 }
1112 enumerator->destroy(enumerator);
1113 fprintf(out, "\n integrity: ");
1114 len = 13;
1115 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
1116 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
1117 {
1118 print_alg(out, &len, integrity_algorithm_names, integrity, plugin_name);
1119 }
1120 enumerator->destroy(enumerator);
1121 fprintf(out, "\n aead: ");
1122 len = 13;
1123 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
1124 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1125 {
1126 print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
1127 }
1128 enumerator->destroy(enumerator);
1129 fprintf(out, "\n hasher: ");
1130 len = 13;
1131 enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
1132 while (enumerator->enumerate(enumerator, &hash, &plugin_name))
1133 {
1134 print_alg(out, &len, hash_algorithm_names, hash, plugin_name);
1135 }
1136 enumerator->destroy(enumerator);
1137 fprintf(out, "\n prf: ");
1138 len = 13;
1139 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
1140 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
1141 {
1142 print_alg(out, &len, pseudo_random_function_names, prf, plugin_name);
1143 }
1144 enumerator->destroy(enumerator);
1145 fprintf(out, "\n dh-group: ");
1146 len = 13;
1147 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
1148 while (enumerator->enumerate(enumerator, &group, &plugin_name))
1149 {
1150 print_alg(out, &len, diffie_hellman_group_names, group, plugin_name);
1151 }
1152 enumerator->destroy(enumerator);
1153 fprintf(out, "\n random-gen:");
1154 len = 13;
1155 enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
1156 while (enumerator->enumerate(enumerator, &quality, &plugin_name))
1157 {
1158 print_alg(out, &len, rng_quality_names, quality, plugin_name);
1159 }
1160 enumerator->destroy(enumerator);
1161 fprintf(out, "\n");
1162 }
1163
1164 METHOD(stroke_list_t, list, void,
1165 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
1166 {
1167 linked_list_t *cert_list = NULL;
1168
1169 if (msg->list.flags & LIST_PUBKEYS)
1170 {
1171 linked_list_t *pubkey_list = create_unique_cert_list(CERT_TRUSTED_PUBKEY);
1172
1173 stroke_list_pubkeys(pubkey_list, msg->list.utc, out);
1174 pubkey_list->destroy_offset(pubkey_list, offsetof(certificate_t, destroy));
1175 }
1176 if (msg->list.flags & LIST_CERTS)
1177 {
1178 linked_list_t *pgp_list = create_unique_cert_list(CERT_GPG);
1179
1180 stroke_list_pgp(pgp_list, msg->list.utc, out);
1181 pgp_list->destroy_offset(pgp_list, offsetof(certificate_t, destroy));
1182 }
1183 if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS))
1184 {
1185 cert_list = create_unique_cert_list(CERT_X509);
1186 }
1187 if (msg->list.flags & LIST_CERTS)
1188 {
1189 stroke_list_certs(cert_list, "X.509 End Entity Certificates",
1190 X509_NONE, msg->list.utc, out);
1191 }
1192 if (msg->list.flags & LIST_CACERTS)
1193 {
1194 stroke_list_certs(cert_list, "X.509 CA Certificates",
1195 X509_CA, msg->list.utc, out);
1196 }
1197 if (msg->list.flags & LIST_OCSPCERTS)
1198 {
1199 stroke_list_certs(cert_list, "X.509 OCSP Signer Certificates",
1200 X509_OCSP_SIGNER, msg->list.utc, out);
1201 }
1202 if (msg->list.flags & LIST_AACERTS)
1203 {
1204 stroke_list_certs(cert_list, "X.509 AA Certificates",
1205 X509_AA, msg->list.utc, out);
1206 }
1207 DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy));
1208
1209 if (msg->list.flags & LIST_ACERTS)
1210 {
1211 linked_list_t *ac_list = create_unique_cert_list(CERT_X509_AC);
1212
1213 stroke_list_acerts(ac_list, msg->list.utc, out);
1214 ac_list->destroy_offset(ac_list, offsetof(certificate_t, destroy));
1215 }
1216 if (msg->list.flags & LIST_CRLS)
1217 {
1218 linked_list_t *crl_list = create_unique_cert_list(CERT_X509_CRL);
1219
1220 stroke_list_crls(crl_list, msg->list.utc, out);
1221 crl_list->destroy_offset(crl_list, offsetof(certificate_t, destroy));
1222 }
1223 if (msg->list.flags & LIST_OCSP)
1224 {
1225 linked_list_t *ocsp_list = create_unique_cert_list(CERT_X509_OCSP_RESPONSE);
1226
1227 stroke_list_ocsp(ocsp_list, msg->list.utc, out);
1228
1229 ocsp_list->destroy_offset(ocsp_list, offsetof(certificate_t, destroy));
1230 }
1231 if (msg->list.flags & LIST_ALGS)
1232 {
1233 list_algs(out);
1234 }
1235 }
1236
1237 /**
1238 * Print leases of a single pool
1239 */
1240 static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
1241 host_t *address, u_int size, u_int online, u_int offline)
1242 {
1243 enumerator_t *enumerator;
1244 identification_t *id;
1245 host_t *lease;
1246 bool on;
1247 int found = 0;
1248
1249 fprintf(out, "Leases in pool '%s', usage: %u/%u, %u online\n",
1250 pool, online + offline, size, online);
1251 enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
1252 while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
1253 {
1254 if (!address || address->ip_equals(address, lease))
1255 {
1256 fprintf(out, " %15H %s '%Y'\n",
1257 lease, on ? "online" : "offline", id);
1258 found++;
1259 }
1260 }
1261 enumerator->destroy(enumerator);
1262 if (!found)
1263 {
1264 fprintf(out, " no matching leases found\n");
1265 }
1266 }
1267
1268 METHOD(stroke_list_t, leases, void,
1269 private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
1270 {
1271 enumerator_t *enumerator;
1272 u_int size, offline, online;
1273 host_t *address = NULL;
1274 char *pool;
1275 int found = 0;
1276
1277 if (msg->leases.address)
1278 {
1279 address = host_create_from_string(msg->leases.address, 0);
1280 }
1281
1282 enumerator = this->attribute->create_pool_enumerator(this->attribute);
1283 while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
1284 {
1285 if (!msg->leases.pool || streq(msg->leases.pool, pool))
1286 {
1287 pool_leases(this, out, pool, address, size, online, offline);
1288 found++;
1289 }
1290 }
1291 enumerator->destroy(enumerator);
1292 if (!found)
1293 {
1294 if (msg->leases.pool)
1295 {
1296 fprintf(out, "pool '%s' not found\n", msg->leases.pool);
1297 }
1298 else
1299 {
1300 fprintf(out, "no pools found\n");
1301 }
1302 }
1303 DESTROY_IF(address);
1304 }
1305
1306 METHOD(stroke_list_t, destroy, void,
1307 private_stroke_list_t *this)
1308 {
1309 free(this);
1310 }
1311
1312 /*
1313 * see header file
1314 */
1315 stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
1316 {
1317 private_stroke_list_t *this;
1318
1319 INIT(this,
1320 .public = {
1321
1322 .list = _list,
1323 .status = _status,
1324 .leases = _leases,
1325 .destroy = _destroy,
1326 },
1327 .uptime = time_monotonic(NULL),
1328 .attribute = attribute,
1329 );
1330
1331 return &this->public;
1332 }
1333