2 * Copyright (C) 2015 Tobias Brunner, Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2014 Martin Willi
6 * Copyright (C) 2014 revosec AG
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
22 * Permission is hereby granted, free of charge, to any person obtaining a copy
23 * of this software and associated documentation files (the "Software"), to deal
24 * in the Software without restriction, including without limitation the rights
25 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26 * copies of the Software, and to permit persons to whom the Software is
27 * furnished to do so, subject to the following conditions:
29 * The above copyright notice and this permission notice shall be included in
30 * all copies or substantial portions of the Software.
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41 #include "vici_query.h"
42 #include "vici_builder.h"
43 #include "vici_cert_info.h"
48 #include <sys/utsname.h>
55 #include <asn1/asn1.h>
56 #include <credentials/certificates/certificate.h>
57 #include <credentials/certificates/x509.h>
59 typedef struct private_vici_query_t private_vici_query_t
;
62 * Private data of an vici_query_t object.
64 struct private_vici_query_t
{
67 * Public vici_query_t interface.
74 vici_dispatcher_t
*dispatcher
;
77 * Daemon startup timestamp
83 * List details of a CHILD_SA
85 static void list_child(private_vici_query_t
*this, vici_builder_t
*b
,
86 child_sa_t
*child
, time_t now
)
89 uint64_t bytes
, packets
;
92 enumerator_t
*enumerator
;
93 traffic_selector_t
*ts
;
95 b
->add_kv(b
, "uniqueid", "%u", child
->get_unique_id(child
));
96 b
->add_kv(b
, "reqid", "%u", child
->get_reqid(child
));
97 b
->add_kv(b
, "state", "%N", child_sa_state_names
, child
->get_state(child
));
98 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, child
->get_mode(child
));
99 if (child
->get_state(child
) == CHILD_INSTALLED
||
100 child
->get_state(child
) == CHILD_REKEYING
||
101 child
->get_state(child
) == CHILD_REKEYED
)
103 b
->add_kv(b
, "protocol", "%N", protocol_id_names
,
104 child
->get_protocol(child
));
105 if (child
->has_encap(child
))
107 b
->add_kv(b
, "encap", "yes");
109 b
->add_kv(b
, "spi-in", "%.8x", ntohl(child
->get_spi(child
, TRUE
)));
110 b
->add_kv(b
, "spi-out", "%.8x", ntohl(child
->get_spi(child
, FALSE
)));
112 if (child
->get_ipcomp(child
) != IPCOMP_NONE
)
114 b
->add_kv(b
, "cpi-in", "%.4x", ntohs(child
->get_cpi(child
, TRUE
)));
115 b
->add_kv(b
, "cpi-out", "%.4x", ntohs(child
->get_cpi(child
, FALSE
)));
117 proposal
= child
->get_proposal(child
);
120 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
,
121 &alg
, &ks
) && alg
!= ENCR_UNDEFINED
)
123 b
->add_kv(b
, "encr-alg", "%N", encryption_algorithm_names
, alg
);
126 b
->add_kv(b
, "encr-keysize", "%u", ks
);
129 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
,
130 &alg
, &ks
) && alg
!= AUTH_UNDEFINED
)
132 b
->add_kv(b
, "integ-alg", "%N", integrity_algorithm_names
, alg
);
135 b
->add_kv(b
, "integ-keysize", "%u", ks
);
138 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
,
141 b
->add_kv(b
, "dh-group", "%N", diffie_hellman_group_names
, alg
);
143 if (proposal
->get_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
,
144 &alg
, NULL
) && alg
== EXT_SEQ_NUMBERS
)
146 b
->add_kv(b
, "esn", "1");
150 child
->get_usestats(child
, TRUE
, &t
, &bytes
, &packets
);
151 b
->add_kv(b
, "bytes-in", "%" PRIu64
, bytes
);
152 b
->add_kv(b
, "packets-in", "%" PRIu64
, packets
);
155 b
->add_kv(b
, "use-in", "%"PRIu64
, (uint64_t)(now
- t
));
158 child
->get_usestats(child
, FALSE
, &t
, &bytes
, &packets
);
159 b
->add_kv(b
, "bytes-out", "%"PRIu64
, bytes
);
160 b
->add_kv(b
, "packets-out", "%"PRIu64
, packets
);
163 b
->add_kv(b
, "use-out", "%"PRIu64
, (uint64_t)(now
- t
));
166 t
= child
->get_lifetime(child
, FALSE
);
169 b
->add_kv(b
, "rekey-time", "%"PRId64
, (int64_t)(t
- now
));
171 t
= child
->get_lifetime(child
, TRUE
);
174 b
->add_kv(b
, "life-time", "%"PRId64
, (int64_t)(t
- now
));
176 t
= child
->get_installtime(child
);
177 b
->add_kv(b
, "install-time", "%"PRId64
, (int64_t)(now
- t
));
180 b
->begin_list(b
, "local-ts");
181 enumerator
= child
->create_ts_enumerator(child
, TRUE
);
182 while (enumerator
->enumerate(enumerator
, &ts
))
184 b
->add_li(b
, "%R", ts
);
186 enumerator
->destroy(enumerator
);
187 b
->end_list(b
/* local-ts */);
189 b
->begin_list(b
, "remote-ts");
190 enumerator
= child
->create_ts_enumerator(child
, FALSE
);
191 while (enumerator
->enumerate(enumerator
, &ts
))
193 b
->add_li(b
, "%R", ts
);
195 enumerator
->destroy(enumerator
);
196 b
->end_list(b
/* remote-ts */);
200 * List tasks in a specific queue
202 static void list_task_queue(private_vici_query_t
*this, vici_builder_t
*b
,
203 ike_sa_t
*ike_sa
, task_queue_t q
, char *name
)
205 enumerator_t
*enumerator
;
209 enumerator
= ike_sa
->create_task_enumerator(ike_sa
, q
);
210 while (enumerator
->enumerate(enumerator
, &task
))
214 b
->begin_list(b
, name
);
217 b
->add_li(b
, "%N", task_type_names
, task
->get_type(task
));
219 enumerator
->destroy(enumerator
);
227 * Add an IKE_SA condition to the given builder
229 static void add_condition(vici_builder_t
*b
, ike_sa_t
*ike_sa
,
230 char *key
, ike_condition_t cond
)
232 if (ike_sa
->has_condition(ike_sa
, cond
))
234 b
->add_kv(b
, key
, "yes");
241 static void list_vips(private_vici_query_t
*this, vici_builder_t
*b
,
242 ike_sa_t
*ike_sa
, bool local
, char *name
)
244 enumerator_t
*enumerator
;
248 enumerator
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, local
);
249 while (enumerator
->enumerate(enumerator
, &vip
))
253 b
->begin_list(b
, name
);
256 b
->add_li(b
, "%H", vip
);
258 enumerator
->destroy(enumerator
);
266 * List details of an IKE_SA
268 static void list_ike(private_vici_query_t
*this, vici_builder_t
*b
,
269 ike_sa_t
*ike_sa
, time_t now
)
273 identification_t
*eap
;
274 proposal_t
*proposal
;
278 b
->add_kv(b
, "uniqueid", "%u", ike_sa
->get_unique_id(ike_sa
));
279 b
->add_kv(b
, "version", "%u", ike_sa
->get_version(ike_sa
));
280 b
->add_kv(b
, "state", "%N", ike_sa_state_names
, ike_sa
->get_state(ike_sa
));
282 host
= ike_sa
->get_my_host(ike_sa
);
283 b
->add_kv(b
, "local-host", "%H", host
);
284 b
->add_kv(b
, "local-port", "%d", host
->get_port(host
));
285 b
->add_kv(b
, "local-id", "%Y", ike_sa
->get_my_id(ike_sa
));
287 host
= ike_sa
->get_other_host(ike_sa
);
288 b
->add_kv(b
, "remote-host", "%H", host
);
289 b
->add_kv(b
, "remote-port", "%d", host
->get_port(host
));
290 b
->add_kv(b
, "remote-id", "%Y", ike_sa
->get_other_id(ike_sa
));
292 eap
= ike_sa
->get_other_eap_id(ike_sa
);
294 if (!eap
->equals(eap
, ike_sa
->get_other_id(ike_sa
)))
296 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
298 b
->add_kv(b
, "remote-xauth-id", "%Y", eap
);
302 b
->add_kv(b
, "remote-eap-id", "%Y", eap
);
306 id
= ike_sa
->get_id(ike_sa
);
307 if (id
->is_initiator(id
))
309 b
->add_kv(b
, "initiator", "yes");
311 b
->add_kv(b
, "initiator-spi", "%.16"PRIx64
,
312 be64toh(id
->get_initiator_spi(id
)));
313 b
->add_kv(b
, "responder-spi", "%.16"PRIx64
,
314 be64toh(id
->get_responder_spi(id
)));
316 add_condition(b
, ike_sa
, "nat-local", COND_NAT_HERE
);
317 add_condition(b
, ike_sa
, "nat-remote", COND_NAT_THERE
);
318 add_condition(b
, ike_sa
, "nat-fake", COND_NAT_FAKE
);
319 add_condition(b
, ike_sa
, "nat-any", COND_NAT_ANY
);
321 proposal
= ike_sa
->get_proposal(ike_sa
);
324 if (proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &ks
))
326 b
->add_kv(b
, "encr-alg", "%N", encryption_algorithm_names
, alg
);
329 b
->add_kv(b
, "encr-keysize", "%u", ks
);
332 if (proposal
->get_algorithm(proposal
, INTEGRITY_ALGORITHM
, &alg
, &ks
))
334 b
->add_kv(b
, "integ-alg", "%N", integrity_algorithm_names
, alg
);
337 b
->add_kv(b
, "integ-keysize", "%u", ks
);
340 if (proposal
->get_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, &alg
, NULL
))
342 b
->add_kv(b
, "prf-alg", "%N", pseudo_random_function_names
, alg
);
344 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &alg
, NULL
))
346 b
->add_kv(b
, "dh-group", "%N", diffie_hellman_group_names
, alg
);
350 if (ike_sa
->get_state(ike_sa
) == IKE_ESTABLISHED
)
352 t
= ike_sa
->get_statistic(ike_sa
, STAT_ESTABLISHED
);
353 b
->add_kv(b
, "established", "%"PRId64
, (int64_t)(now
- t
));
354 t
= ike_sa
->get_statistic(ike_sa
, STAT_REKEY
);
357 b
->add_kv(b
, "rekey-time", "%"PRId64
, (int64_t)(t
- now
));
359 t
= ike_sa
->get_statistic(ike_sa
, STAT_REAUTH
);
362 b
->add_kv(b
, "reauth-time", "%"PRId64
, (int64_t)(t
- now
));
366 list_vips(this, b
, ike_sa
, TRUE
, "local-vips");
367 list_vips(this, b
, ike_sa
, FALSE
, "remote-vips");
369 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_QUEUED
, "tasks-queued");
370 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_ACTIVE
, "tasks-active");
371 list_task_queue(this, b
, ike_sa
, TASK_QUEUE_PASSIVE
, "tasks-passive");
374 CALLBACK(list_sas
, vici_message_t
*,
375 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
378 enumerator_t
*isas
, *csas
;
380 child_sa_t
*child_sa
;
386 bl
= request
->get_str(request
, NULL
, "noblock") == NULL
;
387 ike
= request
->get_str(request
, NULL
, "ike");
388 ike_id
= request
->get_int(request
, 0, "ike-id");
390 isas
= charon
->controller
->create_ike_sa_enumerator(charon
->controller
, bl
);
391 while (isas
->enumerate(isas
, &ike_sa
))
393 if (ike
&& !streq(ike
, ike_sa
->get_name(ike_sa
)))
397 if (ike_id
&& ike_id
!= ike_sa
->get_unique_id(ike_sa
))
402 now
= time_monotonic(NULL
);
404 b
= vici_builder_create();
405 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
407 list_ike(this, b
, ike_sa
, now
);
409 b
->begin_section(b
, "child-sas");
410 csas
= ike_sa
->create_child_sa_enumerator(ike_sa
);
411 while (csas
->enumerate(csas
, &child_sa
))
413 b
->begin_section(b
, child_sa
->get_name(child_sa
));
414 list_child(this, b
, child_sa
, now
);
418 b
->end_section(b
/* child-sas */ );
422 this->dispatcher
->raise_event(this->dispatcher
, "list-sa", id
,
427 b
= vici_builder_create();
428 return b
->finalize(b
);
432 * Raise a list-policy event for given CHILD_SA
434 static void raise_policy(private_vici_query_t
*this, u_int id
, child_sa_t
*child
)
436 enumerator_t
*enumerator
;
437 traffic_selector_t
*ts
;
440 b
= vici_builder_create();
441 b
->begin_section(b
, child
->get_name(child
));
443 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, child
->get_mode(child
));
445 b
->begin_list(b
, "local-ts");
446 enumerator
= child
->create_ts_enumerator(child
, TRUE
);
447 while (enumerator
->enumerate(enumerator
, &ts
))
449 b
->add_li(b
, "%R", ts
);
451 enumerator
->destroy(enumerator
);
452 b
->end_list(b
/* local-ts */);
454 b
->begin_list(b
, "remote-ts");
455 enumerator
= child
->create_ts_enumerator(child
, FALSE
);
456 while (enumerator
->enumerate(enumerator
, &ts
))
458 b
->add_li(b
, "%R", ts
);
460 enumerator
->destroy(enumerator
);
461 b
->end_list(b
/* remote-ts */);
465 this->dispatcher
->raise_event(this->dispatcher
, "list-policy", id
,
470 * Raise a list-policy event for given CHILD_SA config
472 static void raise_policy_cfg(private_vici_query_t
*this, u_int id
,
475 enumerator_t
*enumerator
;
477 traffic_selector_t
*ts
;
480 b
= vici_builder_create();
481 b
->begin_section(b
, cfg
->get_name(cfg
));
483 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
, cfg
->get_mode(cfg
));
485 b
->begin_list(b
, "local-ts");
486 list
= cfg
->get_traffic_selectors(cfg
, TRUE
, NULL
, NULL
);
487 enumerator
= list
->create_enumerator(list
);
488 while (enumerator
->enumerate(enumerator
, &ts
))
490 b
->add_li(b
, "%R", ts
);
492 enumerator
->destroy(enumerator
);
493 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
494 b
->end_list(b
/* local-ts */);
496 b
->begin_list(b
, "remote-ts");
497 list
= cfg
->get_traffic_selectors(cfg
, FALSE
, NULL
, NULL
);
498 enumerator
= list
->create_enumerator(list
);
499 while (enumerator
->enumerate(enumerator
, &ts
))
501 b
->add_li(b
, "%R", ts
);
503 enumerator
->destroy(enumerator
);
504 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
505 b
->end_list(b
/* remote-ts */);
509 this->dispatcher
->raise_event(this->dispatcher
, "list-policy", id
,
513 CALLBACK(list_policies
, vici_message_t
*,
514 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
516 enumerator_t
*enumerator
;
518 child_sa_t
*child_sa
;
519 child_cfg_t
*child_cfg
;
520 bool drop
, pass
, trap
;
523 drop
= request
->get_str(request
, NULL
, "drop") != NULL
;
524 pass
= request
->get_str(request
, NULL
, "pass") != NULL
;
525 trap
= request
->get_str(request
, NULL
, "trap") != NULL
;
526 child
= request
->get_str(request
, NULL
, "child");
530 enumerator
= charon
->traps
->create_enumerator(charon
->traps
);
531 while (enumerator
->enumerate(enumerator
, NULL
, &child_sa
))
533 if (child
&& !streq(child
, child_sa
->get_name(child_sa
)))
537 raise_policy(this, id
, child_sa
);
539 enumerator
->destroy(enumerator
);
544 enumerator
= charon
->shunts
->create_enumerator(charon
->shunts
);
545 while (enumerator
->enumerate(enumerator
, &child_cfg
))
547 if (child
&& !streq(child
, child_cfg
->get_name(child_cfg
)))
551 switch (child_cfg
->get_mode(child_cfg
))
556 raise_policy_cfg(this, id
, child_cfg
);
562 raise_policy_cfg(this, id
, child_cfg
);
569 enumerator
->destroy(enumerator
);
572 b
= vici_builder_create();
573 return b
->finalize(b
);
577 * Build sections for auth configs, local or remote
579 static void build_auth_cfgs(peer_cfg_t
*peer_cfg
, bool local
, vici_builder_t
*b
)
581 enumerator_t
*enumerator
, *rules
;
586 identification_t
*id
;
593 enumerator
= peer_cfg
->create_auth_cfg_enumerator(peer_cfg
, local
);
594 while (enumerator
->enumerate(enumerator
, &auth
))
596 snprintf(buf
, sizeof(buf
), "%s-%d", local ?
"local" : "remote", ++i
);
597 b
->begin_section(b
, buf
);
599 rules
= auth
->create_enumerator(auth
);
600 while (rules
->enumerate(rules
, &rule
, &v
))
604 case AUTH_RULE_AUTH_CLASS
:
605 b
->add_kv(b
, "class", "%N", auth_class_names
, v
.u
);
607 case AUTH_RULE_EAP_TYPE
:
608 b
->add_kv(b
, "eap-type", "%N", eap_type_names
, v
.u
);
610 case AUTH_RULE_EAP_VENDOR
:
611 b
->add_kv(b
, "eap-vendor", "%u", v
.u
);
613 case AUTH_RULE_XAUTH_BACKEND
:
614 b
->add_kv(b
, "xauth", "%s", v
.str
);
616 case AUTH_RULE_CRL_VALIDATION
:
617 b
->add_kv(b
, "revocation", "%N", cert_validation_names
, v
.u
);
619 case AUTH_RULE_IDENTITY
:
620 b
->add_kv(b
, "id", "%Y", v
.id
);
622 case AUTH_RULE_AAA_IDENTITY
:
623 b
->add_kv(b
, "aaa_id", "%Y", v
.id
);
625 case AUTH_RULE_EAP_IDENTITY
:
626 b
->add_kv(b
, "eap_id", "%Y", v
.id
);
628 case AUTH_RULE_XAUTH_IDENTITY
:
629 b
->add_kv(b
, "xauth_id", "%Y", v
.id
);
635 rules
->destroy(rules
);
637 b
->begin_list(b
, "groups");
638 rules
= auth
->create_enumerator(auth
);
639 while (rules
->enumerate(rules
, &rule
, &v
))
641 if (rule
== AUTH_RULE_GROUP
)
643 b
->add_li(b
, "%Y", v
.id
);
646 rules
->destroy(rules
);
649 b
->begin_list(b
, "certs");
650 rules
= auth
->create_enumerator(auth
);
651 while (rules
->enumerate(rules
, &rule
, &v
))
653 if (rule
== AUTH_RULE_SUBJECT_CERT
)
655 b
->add_li(b
, "%Y", v
.cert
->get_subject(v
.cert
));
658 rules
->destroy(rules
);
661 b
->begin_list(b
, "cacerts");
662 rules
= auth
->create_enumerator(auth
);
663 while (rules
->enumerate(rules
, &rule
, &v
))
665 if (rule
== AUTH_RULE_CA_CERT
)
667 b
->add_li(b
, "%Y", v
.cert
->get_subject(v
.cert
));
670 rules
->destroy(rules
);
675 enumerator
->destroy(enumerator
);
678 CALLBACK(list_conns
, vici_message_t
*,
679 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
681 enumerator_t
*enumerator
, *tokens
, *selectors
, *children
;
682 peer_cfg_t
*peer_cfg
;
684 child_cfg_t
*child_cfg
;
685 char *ike
, *str
, *interface
;
686 uint32_t manual_prio
;
688 traffic_selector_t
*ts
;
692 ike
= request
->get_str(request
, NULL
, "ike");
694 enumerator
= charon
->backends
->create_peer_cfg_enumerator(charon
->backends
,
695 NULL
, NULL
, NULL
, NULL
, IKE_ANY
);
696 while (enumerator
->enumerate(enumerator
, &peer_cfg
))
698 if (ike
&& !streq(ike
, peer_cfg
->get_name(peer_cfg
)))
703 b
= vici_builder_create();
704 b
->begin_section(b
, peer_cfg
->get_name(peer_cfg
));
706 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
708 b
->begin_list(b
, "local_addrs");
709 str
= ike_cfg
->get_my_addr(ike_cfg
);
710 tokens
= enumerator_create_token(str
, ",", " ");
711 while (tokens
->enumerate(tokens
, &str
))
713 b
->add_li(b
, "%s", str
);
715 tokens
->destroy(tokens
);
718 b
->begin_list(b
, "remote_addrs");
719 str
= ike_cfg
->get_other_addr(ike_cfg
);
720 tokens
= enumerator_create_token(str
, ",", " ");
721 while (tokens
->enumerate(tokens
, &str
))
723 b
->add_li(b
, "%s", str
);
725 tokens
->destroy(tokens
);
728 b
->add_kv(b
, "version", "%N", ike_version_names
,
729 peer_cfg
->get_ike_version(peer_cfg
));
730 b
->add_kv(b
, "reauth_time", "%u",
731 peer_cfg
->get_reauth_time(peer_cfg
, FALSE
));
732 b
->add_kv(b
, "rekey_time", "%u",
733 peer_cfg
->get_rekey_time(peer_cfg
, FALSE
));
735 build_auth_cfgs(peer_cfg
, TRUE
, b
);
736 build_auth_cfgs(peer_cfg
, FALSE
, b
);
738 b
->begin_section(b
, "children");
740 children
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
741 while (children
->enumerate(children
, &child_cfg
))
743 b
->begin_section(b
, child_cfg
->get_name(child_cfg
));
745 b
->add_kv(b
, "mode", "%N", ipsec_mode_names
,
746 child_cfg
->get_mode(child_cfg
));
748 lft
= child_cfg
->get_lifetime(child_cfg
, FALSE
);
749 b
->add_kv(b
, "rekey_time", "%"PRIu64
, lft
->time
.rekey
);
750 b
->add_kv(b
, "rekey_bytes", "%"PRIu64
, lft
->bytes
.rekey
);
751 b
->add_kv(b
, "rekey_packets", "%"PRIu64
, lft
->packets
.rekey
);
754 b
->begin_list(b
, "local-ts");
755 list
= child_cfg
->get_traffic_selectors(child_cfg
, TRUE
, NULL
, NULL
);
756 selectors
= list
->create_enumerator(list
);
757 while (selectors
->enumerate(selectors
, &ts
))
759 b
->add_li(b
, "%R", ts
);
761 selectors
->destroy(selectors
);
762 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
763 b
->end_list(b
/* local-ts */);
765 b
->begin_list(b
, "remote-ts");
766 list
= child_cfg
->get_traffic_selectors(child_cfg
, FALSE
, NULL
, NULL
);
767 selectors
= list
->create_enumerator(list
);
768 while (selectors
->enumerate(selectors
, &ts
))
770 b
->add_li(b
, "%R", ts
);
772 selectors
->destroy(selectors
);
773 list
->destroy_offset(list
, offsetof(traffic_selector_t
, destroy
));
774 b
->end_list(b
/* remote-ts */);
776 interface
= child_cfg
->get_interface(child_cfg
);
779 b
->add_kv(b
, "interface", "%s", interface
);
782 manual_prio
= child_cfg
->get_manual_prio(child_cfg
);
785 b
->add_kv(b
, "priority", "%u", manual_prio
);
790 children
->destroy(children
);
792 b
->end_section(b
); /* children */
794 b
->end_section(b
); /* name */
796 this->dispatcher
->raise_event(this->dispatcher
, "list-conn", id
,
799 enumerator
->destroy(enumerator
);
801 b
= vici_builder_create();
802 return b
->finalize(b
);
806 * Do we have a private key for given certificate
808 static bool has_privkey(certificate_t
*cert
)
810 private_key_t
*private;
811 public_key_t
*public;
812 identification_t
*keyid
;
816 public = cert
->get_public_key(cert
);
819 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1
, &chunk
))
821 keyid
= identification_create_from_encoding(ID_KEY_ID
, chunk
);
822 private = lib
->credmgr
->get_private(lib
->credmgr
,
823 public->get_type(public), keyid
, NULL
);
827 private->destroy(private);
829 keyid
->destroy(keyid
);
831 public->destroy(public);
837 * Store cert filter data
840 certificate_type_t type
;
842 identification_t
*subject
;
846 * Enumerate all X.509 certificates with a given flag
848 static void enum_x509(private_vici_query_t
*this, u_int id
,
849 linked_list_t
*certs
, cert_filter_t
*filter
,
852 enumerator_t
*enumerator
;
858 if (filter
->type
!= CERT_ANY
&& filter
->flag
!= X509_ANY
&&
859 filter
->flag
!= flag
)
864 enumerator
= certs
->create_enumerator(certs
);
865 while (enumerator
->enumerate(enumerator
, &cert
))
867 x509
= (x509_t
*)cert
;
868 if ((x509
->get_flags(x509
) & X509_ANY
) != flag
)
873 if (cert
->get_encoding(cert
, CERT_ASN1_DER
, &encoding
))
875 b
= vici_builder_create();
876 b
->add_kv(b
, "type", "%N", certificate_type_names
, CERT_X509
);
877 b
->add_kv(b
, "flag", "%N", x509_flag_names
, flag
);
878 if (has_privkey(cert
))
880 b
->add_kv(b
, "has_privkey", "yes");
882 b
->add(b
, VICI_KEY_VALUE
, "data", encoding
);
885 this->dispatcher
->raise_event(this->dispatcher
, "list-cert", id
,
889 enumerator
->destroy(enumerator
);
893 * Enumerate all non-X.509 certificate types
895 static void enum_others(private_vici_query_t
*this, u_int id
,
896 linked_list_t
*certs
, certificate_type_t type
)
898 enumerator_t
*enumerator
;
901 chunk_t encoding
, t_ch
;
902 cred_encoding_type_t encoding_type
;
903 identification_t
*subject
;
904 time_t not_before
, not_after
;
906 encoding_type
= (type
== CERT_TRUSTED_PUBKEY
) ? PUBKEY_SPKI_ASN1_DER
:
909 enumerator
= certs
->create_enumerator(certs
);
910 while (enumerator
->enumerate(enumerator
, &cert
))
912 if (cert
->get_encoding(cert
, encoding_type
, &encoding
))
914 b
= vici_builder_create();
915 b
->add_kv(b
, "type", "%N", certificate_type_names
, type
);
916 if (has_privkey(cert
))
918 b
->add_kv(b
, "has_privkey", "yes");
920 b
->add(b
, VICI_KEY_VALUE
, "data", encoding
);
923 if (type
== CERT_TRUSTED_PUBKEY
)
925 subject
= cert
->get_subject(cert
);
926 if (subject
->get_type(subject
) != ID_KEY_ID
)
928 b
->add_kv(b
, "subject", "%Y", cert
->get_subject(cert
));
930 cert
->get_validity(cert
, NULL
, ¬_before
, ¬_after
);
931 if (not_before
!= UNDEFINED_TIME
)
933 t_ch
= asn1_from_time(¬_before
, ASN1_GENERALIZEDTIME
);
934 b
->add(b
, VICI_KEY_VALUE
, "not-before", chunk_skip(t_ch
, 2));
937 if (not_after
!= UNDEFINED_TIME
)
939 t_ch
= asn1_from_time(¬_after
, ASN1_GENERALIZEDTIME
);
940 b
->add(b
, VICI_KEY_VALUE
, "not-after", chunk_skip(t_ch
, 2));
944 this->dispatcher
->raise_event(this->dispatcher
, "list-cert", id
,
948 enumerator
->destroy(enumerator
);
952 * Enumerate all certificates of a given type
954 static void enum_certs(private_vici_query_t
*this, u_int id
,
955 cert_filter_t
*filter
, certificate_type_t type
)
957 enumerator_t
*e1
, *e2
;
958 certificate_t
*cert
, *current
;
959 linked_list_t
*certs
;
962 if (filter
->type
!= CERT_ANY
&& filter
->type
!= type
)
966 certs
= linked_list_create();
968 e1
= lib
->credmgr
->create_cert_enumerator(lib
->credmgr
, type
, KEY_ANY
,
969 filter
->subject
, FALSE
);
970 while (e1
->enumerate(e1
, &cert
))
974 e2
= certs
->create_enumerator(certs
);
975 while (e2
->enumerate(e2
, ¤t
))
977 if (current
->equals(current
, cert
))
987 certs
->insert_last(certs
, cert
->get_ref(cert
));
992 if (type
== CERT_X509
)
994 enum_x509(this, id
, certs
, filter
, X509_NONE
);
995 enum_x509(this, id
, certs
, filter
, X509_CA
);
996 enum_x509(this, id
, certs
, filter
, X509_AA
);
997 enum_x509(this, id
, certs
, filter
, X509_OCSP_SIGNER
);
1001 enum_others(this, id
, certs
, type
);
1003 certs
->destroy_offset(certs
, offsetof(certificate_t
, destroy
));
1006 CALLBACK(list_certs
, vici_message_t
*,
1007 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
1009 cert_filter_t filter
= {
1017 str
= request
->get_str(request
, "ANY", "type");
1018 if (enum_from_name(certificate_type_names
, str
, &filter
.type
))
1020 if (filter
.type
== CERT_X509
)
1022 str
= request
->get_str(request
, "ANY", "flag");
1023 if (!enum_from_name(x509_flag_names
, str
, &filter
.flag
))
1025 DBG1(DBG_CFG
, "invalid certificate flag '%s'", str
);
1030 else if (!vici_cert_info_from_str(str
, &filter
.type
, &filter
.flag
))
1032 DBG1(DBG_CFG
, "invalid certificate type '%s'", str
);
1036 str
= request
->get_str(request
, NULL
, "subject");
1039 filter
.subject
= identification_create_from_string(str
);
1042 enum_certs(this, id
, &filter
, CERT_TRUSTED_PUBKEY
);
1043 enum_certs(this, id
, &filter
, CERT_X509
);
1044 enum_certs(this, id
, &filter
, CERT_X509_AC
);
1045 enum_certs(this, id
, &filter
, CERT_X509_CRL
);
1046 enum_certs(this, id
, &filter
, CERT_X509_OCSP_RESPONSE
);
1047 DESTROY_IF(filter
.subject
);
1050 b
= vici_builder_create();
1051 return b
->finalize(b
);
1055 * Add a key/value pair of ALG => plugin
1057 static void add_algorithm(vici_builder_t
*b
, enum_name_t
*alg_names
,
1058 int alg_type
, const char *plugin_name
)
1060 char alg_name
[BUF_LEN
];
1062 sprintf(alg_name
, "%N", alg_names
, alg_type
);
1063 b
->add_kv(b
, alg_name
, (char*)plugin_name
);
1066 CALLBACK(get_algorithms
, vici_message_t
*,
1067 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
1070 enumerator_t
*enumerator
;
1071 encryption_algorithm_t encryption
;
1072 integrity_algorithm_t integrity
;
1073 hash_algorithm_t hash
;
1074 pseudo_random_function_t prf
;
1075 diffie_hellman_group_t group
;
1076 rng_quality_t quality
;
1077 const char *plugin_name
;
1079 b
= vici_builder_create();
1081 b
->begin_section(b
, "encryption");
1082 enumerator
= lib
->crypto
->create_crypter_enumerator(lib
->crypto
);
1083 while (enumerator
->enumerate(enumerator
, &encryption
, &plugin_name
))
1085 add_algorithm(b
, encryption_algorithm_names
, encryption
, plugin_name
);
1087 enumerator
->destroy(enumerator
);
1090 b
->begin_section(b
, "integrity");
1091 enumerator
= lib
->crypto
->create_signer_enumerator(lib
->crypto
);
1092 while (enumerator
->enumerate(enumerator
, &integrity
, &plugin_name
))
1094 add_algorithm(b
, integrity_algorithm_names
, integrity
, plugin_name
);
1096 enumerator
->destroy(enumerator
);
1099 b
->begin_section(b
, "aead");
1100 enumerator
= lib
->crypto
->create_aead_enumerator(lib
->crypto
);
1101 while (enumerator
->enumerate(enumerator
, &encryption
, &plugin_name
))
1103 add_algorithm(b
, encryption_algorithm_names
, encryption
, plugin_name
);
1105 enumerator
->destroy(enumerator
);
1108 b
->begin_section(b
, "hasher");
1109 enumerator
= lib
->crypto
->create_hasher_enumerator(lib
->crypto
);
1110 while (enumerator
->enumerate(enumerator
, &hash
, &plugin_name
))
1112 add_algorithm(b
, hash_algorithm_names
, hash
, plugin_name
);
1114 enumerator
->destroy(enumerator
);
1117 b
->begin_section(b
, "prf");
1118 enumerator
= lib
->crypto
->create_prf_enumerator(lib
->crypto
);
1119 while (enumerator
->enumerate(enumerator
, &prf
, &plugin_name
))
1121 add_algorithm(b
, pseudo_random_function_names
, prf
, plugin_name
);
1123 enumerator
->destroy(enumerator
);
1126 b
->begin_section(b
, "dh");
1127 enumerator
= lib
->crypto
->create_dh_enumerator(lib
->crypto
);
1128 while (enumerator
->enumerate(enumerator
, &group
, &plugin_name
))
1130 add_algorithm(b
, diffie_hellman_group_names
, group
, plugin_name
);
1132 enumerator
->destroy(enumerator
);
1135 b
->begin_section(b
, "rng");
1136 enumerator
= lib
->crypto
->create_rng_enumerator(lib
->crypto
);
1137 while (enumerator
->enumerate(enumerator
, &quality
, &plugin_name
))
1139 add_algorithm(b
, rng_quality_names
, quality
, plugin_name
);
1141 enumerator
->destroy(enumerator
);
1144 b
->begin_section(b
, "nonce-gen");
1145 enumerator
= lib
->crypto
->create_nonce_gen_enumerator(lib
->crypto
);
1146 while (enumerator
->enumerate(enumerator
, &plugin_name
))
1148 b
->add_kv(b
, "NONCE_GEN", (char*)plugin_name
);
1150 enumerator
->destroy(enumerator
);
1153 return b
->finalize(b
);
1156 CALLBACK(version
, vici_message_t
*,
1157 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
1161 b
= vici_builder_create();
1162 b
->add_kv(b
, "daemon", "%s", lib
->ns
);
1163 b
->add_kv(b
, "version", "%s", VERSION
);
1167 OSVERSIONINFOEX osvie
;
1169 memset(&osvie
, 0, sizeof(osvie
));
1170 osvie
.dwOSVersionInfoSize
= sizeof(osvie
);
1172 if (GetVersionEx((LPOSVERSIONINFO
)&osvie
))
1174 b
->add_kv(b
, "sysname", "Windows %s",
1175 osvie
.wProductType
== VER_NT_WORKSTATION ?
"Client" : "Server");
1176 b
->add_kv(b
, "release", "%d.%d.%d (SP %d.%d)",
1177 osvie
.dwMajorVersion
, osvie
.dwMinorVersion
, osvie
.dwBuildNumber
,
1178 osvie
.wServicePackMajor
, osvie
.wServicePackMinor
);
1179 b
->add_kv(b
, "machine", "%s",
1189 struct utsname utsname
;
1191 if (uname(&utsname
) == 0)
1193 b
->add_kv(b
, "sysname", "%s", utsname
.sysname
);
1194 b
->add_kv(b
, "release", "%s", utsname
.release
);
1195 b
->add_kv(b
, "machine", "%s", utsname
.machine
);
1199 return b
->finalize(b
);
1202 CALLBACK(stats
, vici_message_t
*,
1203 private_vici_query_t
*this, char *name
, u_int id
, vici_message_t
*request
)
1206 enumerator_t
*enumerator
;
1211 b
= vici_builder_create();
1213 now
= time_monotonic(NULL
);
1214 since
= time(NULL
) - (now
- this->uptime
);
1216 b
->begin_section(b
, "uptime");
1217 b
->add_kv(b
, "running", "%V", &now
, &this->uptime
);
1218 b
->add_kv(b
, "since", "%T", &since
, FALSE
);
1221 b
->begin_section(b
, "workers");
1222 b
->add_kv(b
, "total", "%d",
1223 lib
->processor
->get_total_threads(lib
->processor
));
1224 b
->add_kv(b
, "idle", "%d",
1225 lib
->processor
->get_idle_threads(lib
->processor
));
1226 b
->begin_section(b
, "active");
1227 for (i
= 0; i
< JOB_PRIO_MAX
; i
++)
1229 b
->add_kv(b
, enum_to_name(job_priority_names
, i
), "%d",
1230 lib
->processor
->get_working_threads(lib
->processor
, i
));
1235 b
->begin_section(b
, "queues");
1236 for (i
= 0; i
< JOB_PRIO_MAX
; i
++)
1238 b
->add_kv(b
, enum_to_name(job_priority_names
, i
), "%d",
1239 lib
->processor
->get_job_load(lib
->processor
, i
));
1243 b
->add_kv(b
, "scheduled", "%d",
1244 lib
->scheduler
->get_job_load(lib
->scheduler
));
1246 b
->begin_section(b
, "ikesas");
1247 b
->add_kv(b
, "total", "%u",
1248 charon
->ike_sa_manager
->get_count(charon
->ike_sa_manager
));
1249 b
->add_kv(b
, "half-open", "%u",
1250 charon
->ike_sa_manager
->get_half_open_count(charon
->ike_sa_manager
,
1254 b
->begin_list(b
, "plugins");
1255 enumerator
= lib
->plugins
->create_plugin_enumerator(lib
->plugins
);
1256 while (enumerator
->enumerate(enumerator
, &plugin
, NULL
))
1258 b
->add_li(b
, "%s", plugin
->get_name(plugin
));
1260 enumerator
->destroy(enumerator
);
1265 DWORD lasterr
= ERROR_INVALID_HANDLE
;
1272 b
->begin_section(b
, "mem");
1273 count
= GetProcessHeaps(countof(heaps
), heaps
);
1274 for (i
= 0; i
< count
; i
++)
1276 PROCESS_HEAP_ENTRY entry
= {};
1277 size_t heap_total
= 0;
1278 int heap_allocs
= 0;
1280 if (HeapLock(heaps
[i
]))
1282 while (HeapWalk(heaps
[i
], &entry
))
1284 if (entry
.wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
1286 heap_total
+= entry
.cbData
;
1290 lasterr
= GetLastError();
1291 HeapUnlock(heaps
[i
]);
1293 if (lasterr
!= ERROR_NO_MORE_ITEMS
)
1297 snprintf(buf
, sizeof(buf
), "heap-%d", i
);
1298 b
->begin_section(b
, buf
);
1299 b
->add_kv(b
, "total", "%zu", heap_total
);
1300 b
->add_kv(b
, "allocs", "%d", heap_allocs
);
1303 total
+= heap_total
;
1304 allocs
+= heap_allocs
;
1306 if (lasterr
== ERROR_NO_MORE_ITEMS
)
1308 b
->add_kv(b
, "total", "%zu", total
);
1309 b
->add_kv(b
, "allocs", "%d", allocs
);
1315 #ifdef HAVE_MALLINFO
1317 struct mallinfo mi
= mallinfo();
1319 b
->begin_section(b
, "mallinfo");
1320 b
->add_kv(b
, "sbrk", "%u", mi
.arena
);
1321 b
->add_kv(b
, "mmap", "%u", mi
.hblkhd
);
1322 b
->add_kv(b
, "used", "%u", mi
.uordblks
);
1323 b
->add_kv(b
, "free", "%u", mi
.fordblks
);
1326 #endif /* HAVE_MALLINFO */
1328 return b
->finalize(b
);
1331 static void manage_command(private_vici_query_t
*this,
1332 char *name
, vici_command_cb_t cb
, bool reg
)
1334 this->dispatcher
->manage_command(this->dispatcher
, name
,
1335 reg ? cb
: NULL
, this);
1339 * (Un-)register dispatcher functions
1341 static void manage_commands(private_vici_query_t
*this, bool reg
)
1343 this->dispatcher
->manage_event(this->dispatcher
, "list-sa", reg
);
1344 this->dispatcher
->manage_event(this->dispatcher
, "list-policy", reg
);
1345 this->dispatcher
->manage_event(this->dispatcher
, "list-conn", reg
);
1346 this->dispatcher
->manage_event(this->dispatcher
, "list-cert", reg
);
1347 this->dispatcher
->manage_event(this->dispatcher
, "ike-updown", reg
);
1348 this->dispatcher
->manage_event(this->dispatcher
, "ike-rekey", reg
);
1349 this->dispatcher
->manage_event(this->dispatcher
, "child-updown", reg
);
1350 this->dispatcher
->manage_event(this->dispatcher
, "child-rekey", reg
);
1351 manage_command(this, "list-sas", list_sas
, reg
);
1352 manage_command(this, "list-policies", list_policies
, reg
);
1353 manage_command(this, "list-conns", list_conns
, reg
);
1354 manage_command(this, "list-certs", list_certs
, reg
);
1355 manage_command(this, "get-algorithms", get_algorithms
, reg
);
1356 manage_command(this, "version", version
, reg
);
1357 manage_command(this, "stats", stats
, reg
);
1360 METHOD(listener_t
, ike_updown
, bool,
1361 private_vici_query_t
*this, ike_sa_t
*ike_sa
, bool up
)
1366 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "ike-updown"))
1371 now
= time_monotonic(NULL
);
1373 b
= vici_builder_create();
1377 b
->add_kv(b
, "up", "yes");
1380 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
1381 list_ike(this, b
, ike_sa
, now
);
1384 this->dispatcher
->raise_event(this->dispatcher
,
1385 "ike-updown", 0, b
->finalize(b
));
1390 METHOD(listener_t
, ike_rekey
, bool,
1391 private_vici_query_t
*this, ike_sa_t
*old
, ike_sa_t
*new)
1396 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "ike-rekey"))
1401 now
= time_monotonic(NULL
);
1403 b
= vici_builder_create();
1404 b
->begin_section(b
, old
->get_name(old
));
1405 b
->begin_section(b
, "old");
1406 list_ike(this, b
, old
, now
);
1408 b
->begin_section(b
, "new");
1409 list_ike(this, b
, new, now
);
1413 this->dispatcher
->raise_event(this->dispatcher
,
1414 "ike-rekey", 0, b
->finalize(b
));
1419 METHOD(listener_t
, child_updown
, bool,
1420 private_vici_query_t
*this, ike_sa_t
*ike_sa
, child_sa_t
*child_sa
, bool up
)
1425 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "child-updown"))
1430 now
= time_monotonic(NULL
);
1431 b
= vici_builder_create();
1435 b
->add_kv(b
, "up", "yes");
1438 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
1439 list_ike(this, b
, ike_sa
, now
);
1440 b
->begin_section(b
, "child-sas");
1442 b
->begin_section(b
, child_sa
->get_name(child_sa
));
1443 list_child(this, b
, child_sa
, now
);
1449 this->dispatcher
->raise_event(this->dispatcher
,
1450 "child-updown", 0, b
->finalize(b
));
1455 METHOD(listener_t
, child_rekey
, bool,
1456 private_vici_query_t
*this, ike_sa_t
*ike_sa
, child_sa_t
*old
,
1462 if (!this->dispatcher
->has_event_listeners(this->dispatcher
, "child-rekey"))
1467 now
= time_monotonic(NULL
);
1468 b
= vici_builder_create();
1470 b
->begin_section(b
, ike_sa
->get_name(ike_sa
));
1471 list_ike(this, b
, ike_sa
, now
);
1472 b
->begin_section(b
, "child-sas");
1474 b
->begin_section(b
, old
->get_name(old
));
1476 b
->begin_section(b
, "old");
1477 list_child(this, b
, old
, now
);
1479 b
->begin_section(b
, "new");
1480 list_child(this, b
, new, now
);
1488 this->dispatcher
->raise_event(this->dispatcher
,
1489 "child-rekey", 0, b
->finalize(b
));
1494 METHOD(vici_query_t
, destroy
, void,
1495 private_vici_query_t
*this)
1497 manage_commands(this, FALSE
);
1504 vici_query_t
*vici_query_create(vici_dispatcher_t
*dispatcher
)
1506 private_vici_query_t
*this;
1511 .ike_updown
= _ike_updown
,
1512 .ike_rekey
= _ike_rekey
,
1513 .child_updown
= _child_updown
,
1514 .child_rekey
= _child_rekey
,
1516 .destroy
= _destroy
,
1518 .dispatcher
= dispatcher
,
1519 .uptime
= time_monotonic(NULL
),
1522 manage_commands(this, TRUE
);
1524 return &this->public;