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