vici: Don't compare unsigned certificate_type_t to -1
[strongswan.git] / src / libcharon / plugins / vici / vici_query.c
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
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 "vici_query.h"
17 #include "vici_builder.h"
18
19 #include <inttypes.h>
20 #include <sys/utsname.h>
21
22 #include <daemon.h>
23
24 typedef struct private_vici_query_t private_vici_query_t;
25
26 /**
27 * Private data of an vici_query_t object.
28 */
29 struct private_vici_query_t {
30
31 /**
32 * Public vici_query_t interface.
33 */
34 vici_query_t public;
35
36 /**
37 * Dispatcher
38 */
39 vici_dispatcher_t *dispatcher;
40 };
41
42 /**
43 * List details of a CHILD_SA
44 */
45 static void list_child(private_vici_query_t *this, vici_builder_t *b,
46 child_sa_t *child, time_t now)
47 {
48 time_t t;
49 u_int64_t bytes, packets;
50 u_int16_t alg, ks;
51 proposal_t *proposal;
52 enumerator_t *enumerator;
53 traffic_selector_t *ts;
54
55 b->add_kv(b, "reqid", "%u", child->get_reqid(child));
56 b->add_kv(b, "state", "%N", child_sa_state_names, child->get_state(child));
57 b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
58 if (child->get_state(child) == CHILD_INSTALLED ||
59 child->get_state(child) == CHILD_REKEYING)
60 {
61 b->add_kv(b, "protocol", "%N", protocol_id_names,
62 child->get_protocol(child));
63 if (child->has_encap(child))
64 {
65 b->add_kv(b, "encap", "yes");
66 }
67 b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
68 b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
69
70 if (child->get_ipcomp(child) != IPCOMP_NONE)
71 {
72 b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
73 b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
74 }
75 proposal = child->get_proposal(child);
76 if (proposal)
77 {
78 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
79 &alg, &ks) && alg != ENCR_UNDEFINED)
80 {
81 b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
82 if (ks)
83 {
84 b->add_kv(b, "encr-keysize", "%u", ks);
85 }
86 }
87 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
88 &alg, &ks) && alg != ENCR_UNDEFINED)
89 {
90 b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
91 if (ks)
92 {
93 b->add_kv(b, "integ-keysize", "%u", ks);
94 }
95 }
96 if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
97 &alg, NULL))
98 {
99 b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
100 }
101 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
102 &alg, NULL))
103 {
104 b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
105 }
106 if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
107 &alg, NULL) && alg == EXT_SEQ_NUMBERS)
108 {
109 b->add_kv(b, "esn", "1");
110 }
111 }
112
113 child->get_usestats(child, TRUE, &t, &bytes, &packets);
114 b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
115 b->add_kv(b, "packets-in", "%" PRIu64, packets);
116 if (t)
117 {
118 b->add_kv(b, "use-in", "%"PRIu64, (u_int64_t)(now - t));
119 }
120
121 child->get_usestats(child, FALSE, &t, &bytes, &packets);
122 b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
123 b->add_kv(b, "packets-out", "%"PRIu64, packets);
124 if (t)
125 {
126 b->add_kv(b, "use-out", "%"PRIu64, (u_int64_t)(now - t));
127 }
128
129 t = child->get_lifetime(child, FALSE);
130 if (t)
131 {
132 b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
133 }
134 t = child->get_lifetime(child, TRUE);
135 if (t)
136 {
137 b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
138 }
139 t = child->get_installtime(child);
140 b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
141 }
142
143 b->begin_list(b, "local-ts");
144 enumerator = child->create_ts_enumerator(child, TRUE);
145 while (enumerator->enumerate(enumerator, &ts))
146 {
147 b->add_li(b, "%R", ts);
148 }
149 enumerator->destroy(enumerator);
150 b->end_list(b /* local-ts */);
151
152 b->begin_list(b, "remote-ts");
153 enumerator = child->create_ts_enumerator(child, FALSE);
154 while (enumerator->enumerate(enumerator, &ts))
155 {
156 b->add_li(b, "%R", ts);
157 }
158 enumerator->destroy(enumerator);
159 b->end_list(b /* remote-ts */);
160 }
161
162 /**
163 * List tasks in a specific queue
164 */
165 static void list_task_queue(private_vici_query_t *this, vici_builder_t *b,
166 ike_sa_t *ike_sa, task_queue_t q, char *name)
167 {
168 enumerator_t *enumerator;
169 bool has = FALSE;
170 task_t *task;
171
172 enumerator = ike_sa->create_task_enumerator(ike_sa, q);
173 while (enumerator->enumerate(enumerator, &task))
174 {
175 if (!has)
176 {
177 b->begin_list(b, name);
178 has = TRUE;
179 }
180 b->add_li(b, "%N", task_type_names, task->get_type(task));
181 }
182 enumerator->destroy(enumerator);
183 if (has)
184 {
185 b->end_list(b);
186 }
187 }
188
189 /**
190 * List details of an IKE_SA
191 */
192 static void list_ike(private_vici_query_t *this, vici_builder_t *b,
193 ike_sa_t *ike_sa, time_t now)
194 {
195 time_t t;
196 ike_sa_id_t *id;
197 identification_t *eap;
198 proposal_t *proposal;
199 u_int16_t alg, ks;
200
201 b->add_kv(b, "uniqueid", "%u", ike_sa->get_unique_id(ike_sa));
202 b->add_kv(b, "version", "%u", ike_sa->get_version(ike_sa));
203 b->add_kv(b, "state", "%N", ike_sa_state_names, ike_sa->get_state(ike_sa));
204
205 b->add_kv(b, "local-host", "%H", ike_sa->get_my_host(ike_sa));
206 b->add_kv(b, "local-id", "%Y", ike_sa->get_my_id(ike_sa));
207
208 b->add_kv(b, "remote-host", "%H", ike_sa->get_other_host(ike_sa));
209 b->add_kv(b, "remote-id", "%Y", ike_sa->get_other_id(ike_sa));
210
211 eap = ike_sa->get_other_eap_id(ike_sa);
212
213 if (!eap->equals(eap, ike_sa->get_other_id(ike_sa)))
214 {
215 if (ike_sa->get_version(ike_sa) == IKEV1)
216 {
217 b->add_kv(b, "remote-xauth-id", "%Y", eap);
218 }
219 else
220 {
221 b->add_kv(b, "remote-eap-id", "%Y", eap);
222 }
223 }
224
225 id = ike_sa->get_id(ike_sa);
226 if (id->is_initiator(id))
227 {
228 b->add_kv(b, "initiator", "yes");
229 }
230 b->add_kv(b, "initiator-spi", "%.16"PRIx64, id->get_initiator_spi(id));
231 b->add_kv(b, "responder-spi", "%.16"PRIx64, id->get_responder_spi(id));
232
233 proposal = ike_sa->get_proposal(ike_sa);
234 if (proposal)
235 {
236 if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &ks))
237 {
238 b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
239 if (ks)
240 {
241 b->add_kv(b, "encr-keysize", "%u", ks);
242 }
243 }
244 if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, &ks))
245 {
246 b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
247 if (ks)
248 {
249 b->add_kv(b, "integ-keysize", "%u", ks);
250 }
251 }
252 if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
253 {
254 b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
255 }
256 if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &alg, NULL))
257 {
258 b->add_kv(b, "dh-group", "%N", diffie_hellman_group_names, alg);
259 }
260 }
261
262 if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
263 {
264 t = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
265 b->add_kv(b, "established", "%"PRId64, (int64_t)(now - t));
266 t = ike_sa->get_statistic(ike_sa, STAT_REKEY);
267 if (t)
268 {
269 b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
270 }
271 t = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
272 if (t)
273 {
274 b->add_kv(b, "reauth-time", "%"PRId64, (int64_t)(t - now));
275 }
276 }
277
278 list_task_queue(this, b, ike_sa, TASK_QUEUE_QUEUED, "tasks-queued");
279 list_task_queue(this, b, ike_sa, TASK_QUEUE_ACTIVE, "tasks-active");
280 list_task_queue(this, b, ike_sa, TASK_QUEUE_PASSIVE, "tasks-passive");
281 }
282
283 CALLBACK(list_sas, vici_message_t*,
284 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
285 {
286 vici_builder_t *b;
287 enumerator_t *isas, *csas;
288 ike_sa_t *ike_sa;
289 child_sa_t *child_sa;
290 time_t now;
291 char *ike;
292 u_int ike_id;
293 bool bl;
294
295 bl = request->get_str(request, NULL, "noblock") == NULL;
296 ike = request->get_str(request, NULL, "ike");
297 ike_id = request->get_int(request, 0, "ike-id");
298
299 isas = charon->controller->create_ike_sa_enumerator(charon->controller, bl);
300 while (isas->enumerate(isas, &ike_sa))
301 {
302 if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
303 {
304 continue;
305 }
306 if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
307 {
308 continue;
309 }
310
311 now = time_monotonic(NULL);
312
313 b = vici_builder_create();
314 b->begin_section(b, ike_sa->get_name(ike_sa));
315
316 list_ike(this, b, ike_sa, now);
317
318 b->begin_section(b, "child-sas");
319 csas = ike_sa->create_child_sa_enumerator(ike_sa);
320 while (csas->enumerate(csas, &child_sa))
321 {
322 b->begin_section(b, child_sa->get_name(child_sa));
323 list_child(this, b, child_sa, now);
324 b->end_section(b);
325 }
326 csas->destroy(csas);
327 b->end_section(b /* child-sas */ );
328
329 b->end_section(b);
330
331 this->dispatcher->raise_event(this->dispatcher, "list-sa", id,
332 b->finalize(b));
333 }
334 isas->destroy(isas);
335
336 b = vici_builder_create();
337 return b->finalize(b);
338 }
339
340 /**
341 * Raise a list-policy event for given CHILD_SA
342 */
343 static void raise_policy(private_vici_query_t *this, u_int id, child_sa_t *child)
344 {
345 enumerator_t *enumerator;
346 traffic_selector_t *ts;
347 vici_builder_t *b;
348
349 b = vici_builder_create();
350 b->begin_section(b, child->get_name(child));
351
352 b->add_kv(b, "mode", "%N", ipsec_mode_names, child->get_mode(child));
353
354 b->begin_list(b, "local-ts");
355 enumerator = child->create_ts_enumerator(child, TRUE);
356 while (enumerator->enumerate(enumerator, &ts))
357 {
358 b->add_li(b, "%R", ts);
359 }
360 enumerator->destroy(enumerator);
361 b->end_list(b /* local-ts */);
362
363 b->begin_list(b, "remote-ts");
364 enumerator = child->create_ts_enumerator(child, FALSE);
365 while (enumerator->enumerate(enumerator, &ts))
366 {
367 b->add_li(b, "%R", ts);
368 }
369 enumerator->destroy(enumerator);
370 b->end_list(b /* remote-ts */);
371
372 b->end_section(b);
373
374 this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
375 b->finalize(b));
376 }
377
378 /**
379 * Raise a list-policy event for given CHILD_SA config
380 */
381 static void raise_policy_cfg(private_vici_query_t *this, u_int id,
382 child_cfg_t *cfg)
383 {
384 enumerator_t *enumerator;
385 linked_list_t *list;
386 traffic_selector_t *ts;
387 vici_builder_t *b;
388
389 b = vici_builder_create();
390 b->begin_section(b, cfg->get_name(cfg));
391
392 b->add_kv(b, "mode", "%N", ipsec_mode_names, cfg->get_mode(cfg));
393
394 b->begin_list(b, "local-ts");
395 list = cfg->get_traffic_selectors(cfg, TRUE, NULL, NULL);
396 enumerator = list->create_enumerator(list);
397 while (enumerator->enumerate(enumerator, &ts))
398 {
399 b->add_li(b, "%R", ts);
400 }
401 enumerator->destroy(enumerator);
402 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
403 b->end_list(b /* local-ts */);
404
405 b->begin_list(b, "remote-ts");
406 list = cfg->get_traffic_selectors(cfg, FALSE, NULL, NULL);
407 enumerator = list->create_enumerator(list);
408 while (enumerator->enumerate(enumerator, &ts))
409 {
410 b->add_li(b, "%R", ts);
411 }
412 enumerator->destroy(enumerator);
413 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
414 b->end_list(b /* remote-ts */);
415
416 b->end_section(b);
417
418 this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
419 b->finalize(b));
420 }
421
422 CALLBACK(list_policies, vici_message_t*,
423 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
424 {
425 enumerator_t *enumerator;
426 vici_builder_t *b;
427 child_sa_t *child_sa;
428 child_cfg_t *child_cfg;
429 bool drop, pass, trap;
430 char *child;
431
432 drop = request->get_str(request, NULL, "drop") != NULL;
433 pass = request->get_str(request, NULL, "pass") != NULL;
434 trap = request->get_str(request, NULL, "trap") != NULL;
435 child = request->get_str(request, NULL, "child");
436
437 if (trap)
438 {
439 enumerator = charon->traps->create_enumerator(charon->traps);
440 while (enumerator->enumerate(enumerator, NULL, &child_sa))
441 {
442 if (child && !streq(child, child_sa->get_name(child_sa)))
443 {
444 continue;
445 }
446 raise_policy(this, id, child_sa);
447 }
448 enumerator->destroy(enumerator);
449 }
450
451 if (drop || pass)
452 {
453 enumerator = charon->shunts->create_enumerator(charon->shunts);
454 while (enumerator->enumerate(enumerator, &child_cfg))
455 {
456 if (child && !streq(child, child_cfg->get_name(child_cfg)))
457 {
458 continue;
459 }
460 switch (child_cfg->get_mode(child_cfg))
461 {
462 case MODE_DROP:
463 if (drop)
464 {
465 raise_policy_cfg(this, id, child_cfg);
466 }
467 break;
468 case MODE_PASS:
469 if (pass)
470 {
471 raise_policy_cfg(this, id, child_cfg);
472 }
473 break;
474 default:
475 break;
476 }
477 }
478 enumerator->destroy(enumerator);
479 }
480
481 b = vici_builder_create();
482 return b->finalize(b);
483 }
484
485 /**
486 * Build sections for auth configs, local or remote
487 */
488 static void build_auth_cfgs(peer_cfg_t *peer_cfg, bool local, vici_builder_t *b)
489 {
490 enumerator_t *enumerator, *rules;
491 auth_rule_t rule;
492 auth_cfg_t *auth;
493 union {
494 uintptr_t u;
495 identification_t *id;
496 certificate_t *cert;
497 char *str;
498 } v;
499
500 enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
501 while (enumerator->enumerate(enumerator, &auth))
502 {
503 b->begin_section(b, local ? "local" : "remote");
504
505 rules = auth->create_enumerator(auth);
506 while (rules->enumerate(rules, &rule, &v))
507 {
508 switch (rule)
509 {
510 case AUTH_RULE_AUTH_CLASS:
511 b->add_kv(b, "class", "%N", auth_class_names, v.u);
512 break;
513 case AUTH_RULE_EAP_TYPE:
514 b->add_kv(b, "eap-type", "%N", eap_type_names, v.u);
515 break;
516 case AUTH_RULE_EAP_VENDOR:
517 b->add_kv(b, "eap-vendor", "%u", v.u);
518 break;
519 case AUTH_RULE_XAUTH_BACKEND:
520 b->add_kv(b, "xauth", "%s", v.str);
521 break;
522 case AUTH_RULE_CRL_VALIDATION:
523 b->add_kv(b, "revocation", "%N", cert_validation_names, v.u);
524 break;
525 case AUTH_RULE_IDENTITY:
526 b->add_kv(b, "id", "%Y", v.id);
527 break;
528 case AUTH_RULE_AAA_IDENTITY:
529 b->add_kv(b, "aaa_id", "%Y", v.id);
530 break;
531 case AUTH_RULE_EAP_IDENTITY:
532 b->add_kv(b, "eap_id", "%Y", v.id);
533 break;
534 case AUTH_RULE_XAUTH_IDENTITY:
535 b->add_kv(b, "xauth_id", "%Y", v.id);
536 break;
537 default:
538 break;
539 }
540 }
541 rules->destroy(rules);
542
543 b->begin_list(b, "groups");
544 rules = auth->create_enumerator(auth);
545 while (rules->enumerate(rules, &rule, &v))
546 {
547 if (rule == AUTH_RULE_GROUP)
548 {
549 b->add_li(b, "%Y", v.id);
550 }
551 }
552 rules->destroy(rules);
553 b->end_list(b);
554
555 b->begin_list(b, "certs");
556 rules = auth->create_enumerator(auth);
557 while (rules->enumerate(rules, &rule, &v))
558 {
559 if (rule == AUTH_RULE_SUBJECT_CERT)
560 {
561 b->add_li(b, "%Y", v.cert->get_subject(v.cert));
562 }
563 }
564 rules->destroy(rules);
565 b->end_list(b);
566
567 b->begin_list(b, "cacerts");
568 rules = auth->create_enumerator(auth);
569 while (rules->enumerate(rules, &rule, &v))
570 {
571 if (rule == AUTH_RULE_CA_CERT)
572 {
573 b->add_li(b, "%Y", v.cert->get_subject(v.cert));
574 }
575 }
576 rules->destroy(rules);
577 b->end_list(b);
578
579 b->end_section(b);
580 }
581 enumerator->destroy(enumerator);
582 }
583
584 CALLBACK(list_conns, vici_message_t*,
585 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
586 {
587 enumerator_t *enumerator, *tokens, *selectors, *children;
588 peer_cfg_t *peer_cfg;
589 ike_cfg_t *ike_cfg;
590 child_cfg_t *child_cfg;
591 char *ike, *str;
592 linked_list_t *list;
593 traffic_selector_t *ts;
594 vici_builder_t *b;
595
596 ike = request->get_str(request, NULL, "ike");
597
598 enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
599 NULL, NULL, NULL, NULL, IKE_ANY);
600 while (enumerator->enumerate(enumerator, &peer_cfg))
601 {
602 if (ike && !streq(ike, peer_cfg->get_name(peer_cfg)))
603 {
604 continue;
605 }
606
607 b = vici_builder_create();
608 b->begin_section(b, peer_cfg->get_name(peer_cfg));
609
610 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
611
612 b->begin_list(b, "local_addrs");
613 str = ike_cfg->get_my_addr(ike_cfg);
614 tokens = enumerator_create_token(str, ",", " ");
615 while (tokens->enumerate(tokens, &str))
616 {
617 b->add_li(b, "%s", str);
618 }
619 tokens->destroy(tokens);
620 b->end_list(b);
621
622 b->begin_list(b, "remote_addrs");
623 str = ike_cfg->get_other_addr(ike_cfg);
624 tokens = enumerator_create_token(str, ",", " ");
625 while (tokens->enumerate(tokens, &str))
626 {
627 b->add_li(b, "%s", str);
628 }
629 tokens->destroy(tokens);
630 b->end_list(b);
631
632 b->add_kv(b, "version", "%N", ike_version_names,
633 peer_cfg->get_ike_version(peer_cfg));
634
635 build_auth_cfgs(peer_cfg, TRUE, b);
636 build_auth_cfgs(peer_cfg, FALSE, b);
637
638 b->begin_section(b, "children");
639
640 children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
641 while (children->enumerate(children, &child_cfg))
642 {
643 b->begin_section(b, child_cfg->get_name(child_cfg));
644
645 b->add_kv(b, "mode", "%N", ipsec_mode_names,
646 child_cfg->get_mode(child_cfg));
647
648 b->begin_list(b, "local-ts");
649 list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
650 selectors = list->create_enumerator(list);
651 while (selectors->enumerate(selectors, &ts))
652 {
653 b->add_li(b, "%R", ts);
654 }
655 selectors->destroy(selectors);
656 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
657 b->end_list(b /* local-ts */);
658
659 b->begin_list(b, "remote-ts");
660 list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
661 selectors = list->create_enumerator(list);
662 while (selectors->enumerate(selectors, &ts))
663 {
664 b->add_li(b, "%R", ts);
665 }
666 selectors->destroy(selectors);
667 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
668 b->end_list(b /* remote-ts */);
669
670 b->end_section(b);
671 }
672 children->destroy(children);
673
674 b->end_section(b); /* children */
675
676 b->end_section(b); /* name */
677
678 this->dispatcher->raise_event(this->dispatcher, "list-conn", id,
679 b->finalize(b));
680 }
681 enumerator->destroy(enumerator);
682
683 b = vici_builder_create();
684 return b->finalize(b);
685 }
686
687 /**
688 * Do we have a private key for given certificate
689 */
690 static bool has_privkey(private_vici_query_t *this, certificate_t *cert)
691 {
692 private_key_t *private;
693 public_key_t *public;
694 identification_t *keyid;
695 chunk_t chunk;
696 bool found = FALSE;
697
698 public = cert->get_public_key(cert);
699 if (public)
700 {
701 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
702 {
703 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
704 private = lib->credmgr->get_private(lib->credmgr,
705 public->get_type(public), keyid, NULL);
706 if (private)
707 {
708 found = TRUE;
709 private->destroy(private);
710 }
711 keyid->destroy(keyid);
712 }
713 public->destroy(public);
714 }
715 return found;
716 }
717
718 CALLBACK(list_certs, vici_message_t*,
719 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
720 {
721 enumerator_t *enumerator, *added;
722 linked_list_t *list;
723 certificate_t *cert, *current;
724 chunk_t encoding;
725 identification_t *subject = NULL;
726 int type;
727 vici_builder_t *b;
728 bool found;
729 char *str;
730
731 str = request->get_str(request, "ANY", "type");
732 type = enum_from_name(certificate_type_names, str);
733 if (type == -1)
734 {
735 b = vici_builder_create();
736 return b->finalize(b);
737 }
738 str = request->get_str(request, NULL, "subject");
739 if (str)
740 {
741 subject = identification_create_from_string(str);
742 }
743
744 list = linked_list_create();
745 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
746 type, KEY_ANY, subject, FALSE);
747 while (enumerator->enumerate(enumerator, &cert))
748 {
749 found = FALSE;
750 added = list->create_enumerator(list);
751 while (added->enumerate(added, &current))
752 {
753 if (current->equals(current, cert))
754 {
755 found = TRUE;
756 break;
757 }
758 }
759 added->destroy(added);
760
761 if (!found && cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
762 {
763 b = vici_builder_create();
764 b->add_kv(b, "type", "%N",
765 certificate_type_names, cert->get_type(cert));
766 if (has_privkey(this, cert))
767 {
768 b->add_kv(b, "has_privkey", "yes");
769 }
770 b->add(b, VICI_KEY_VALUE, "data", encoding);
771 free(encoding.ptr);
772
773 this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
774 b->finalize(b));
775 list->insert_last(list, cert->get_ref(cert));
776 }
777 }
778 enumerator->destroy(enumerator);
779
780 list->destroy_offset(list, offsetof(certificate_t, destroy));
781 DESTROY_IF(subject);
782
783 b = vici_builder_create();
784 return b->finalize(b);
785 }
786
787 CALLBACK(version, vici_message_t*,
788 private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
789 {
790 struct utsname utsname;
791 vici_builder_t *b;
792
793 b = vici_builder_create();
794
795 b->add_kv(b, "daemon", "%s", lib->ns);
796 b->add_kv(b, "version", "%s", VERSION);
797
798 if (uname(&utsname) == 0)
799 {
800 b->add_kv(b, "sysname", "%s", utsname.sysname);
801 b->add_kv(b, "release", "%s", utsname.release);
802 b->add_kv(b, "machine", "%s", utsname.machine);
803 }
804
805 return b->finalize(b);
806 }
807
808 static void manage_command(private_vici_query_t *this,
809 char *name, vici_command_cb_t cb, bool reg)
810 {
811 this->dispatcher->manage_command(this->dispatcher, name,
812 reg ? cb : NULL, this);
813 }
814
815 /**
816 * (Un-)register dispatcher functions
817 */
818 static void manage_commands(private_vici_query_t *this, bool reg)
819 {
820 this->dispatcher->manage_event(this->dispatcher, "list-sa", reg);
821 this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
822 this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
823 this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
824 manage_command(this, "list-sas", list_sas, reg);
825 manage_command(this, "list-policies", list_policies, reg);
826 manage_command(this, "list-conns", list_conns, reg);
827 manage_command(this, "list-certs", list_certs, reg);
828 manage_command(this, "version", version, reg);
829 }
830
831 METHOD(vici_query_t, destroy, void,
832 private_vici_query_t *this)
833 {
834 manage_commands(this, FALSE);
835 free(this);
836 }
837
838 /**
839 * See header
840 */
841 vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
842 {
843 private_vici_query_t *this;
844
845 INIT(this,
846 .public = {
847 .destroy = _destroy,
848 },
849 .dispatcher = dispatcher,
850 );
851
852 manage_commands(this, TRUE);
853
854 return &this->public;
855 }