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