Coverage Report

Created: 2026-05-16 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libcharon/plugins/vici/vici_query.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2015-2020 Tobias Brunner
3
 * Copyright (C) 2015-2019 Andreas Steffen
4
 * Copyright (C) 2014 Martin Willi
5
 *
6
 * Copyright (C) secunet Security Networks AG
7
 *
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>.
12
 *
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
16
 * for more details.
17
 */
18
19
/*
20
 * Copyright (C) 2014 Timo Teräs <timo.teras@iki.fi>
21
 *
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:
28
 *
29
 * The above copyright notice and this permission notice shall be included in
30
 * all copies or substantial portions of the Software.
31
 *
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
38
 * THE SOFTWARE.
39
 */
40
41
#include "vici_query.h"
42
#include "vici_builder.h"
43
#include "vici_cert_info.h"
44
45
#include <inttypes.h>
46
#include <time.h>
47
#ifndef WIN32
48
#include <sys/utsname.h>
49
#endif
50
#if defined(HAVE_MALLINFO2) || defined (HAVE_MALLINFO)
51
#include <malloc.h>
52
#endif
53
54
#include <daemon.h>
55
#include <asn1/asn1.h>
56
#include <credentials/certificates/certificate.h>
57
#include <credentials/certificates/x509.h>
58
#include <counters_query.h>
59
60
ENUM(vici_counter_type_names,
61
  COUNTER_INIT_IKE_SA_REKEY, COUNTER_OUT_INFORMATIONAL_RSP,
62
  "ike-rekey-init",
63
  "ike-rekey-resp",
64
  "child-rekey",
65
  "invalid",
66
  "invalid-spi",
67
  "ike-init-in-req",
68
  "ike-init-in-resp",
69
  "ike-init-out-req",
70
  "ike-init-out-resp",
71
  "ike-auth-in-req",
72
  "ike-auth-in-resp",
73
  "ike-auth-out-req",
74
  "ike-auth-out-resp",
75
  "create-child-in-req",
76
  "create-child-in-resp",
77
  "create-child-out-req",
78
  "create-child-out-resp",
79
  "info-in-req",
80
  "info-in-resp",
81
  "info-out-req",
82
  "info-out-resp",
83
);
84
85
ENUM(alert_names, ALERT_RADIUS_NOT_RESPONDING, ALERT_CERT_POLICY_VIOLATION,
86
  "radius-not-responding",
87
  "shutdown-signal",
88
  "local-auth-failed",
89
  "peer-auth-failed",
90
  "peer-addr-failed",
91
  "peer-init-unreachable",
92
  "invalid-ike-spi",
93
  "parse-error-header",
94
  "parse-error-body",
95
  "retransmit-send",
96
  "retransmit-send-cleared",
97
  "retransmit-send-timeout",
98
  "retransmit-receive",
99
  "half-open-timeout",
100
  "proposal-mismatch-ike",
101
  "proposal-mismatch-child",
102
  "ts-mismatch",
103
  "ts-narrowed",
104
  "install-child-sa-failed",
105
  "install-child-policy-failed",
106
  "unique-replace",
107
  "unique-keep",
108
  "keep-on-child-sa-failure",
109
  "vip-failure",
110
  "authorization-failed",
111
  "ike-sa-expired",
112
  "cert-expired",
113
  "cert-revoked",
114
  "cert-validation-failed",
115
  "cert-no-issuer",
116
  "cert-untrusted-root",
117
  "cert-exceeded-path-len",
118
  "cert-policy-violation",
119
);
120
121
typedef struct private_vici_query_t private_vici_query_t;
122
123
/**
124
 * Private data of an vici_query_t object.
125
 */
126
struct private_vici_query_t {
127
128
  /**
129
   * Public vici_query_t interface.
130
   */
131
  vici_query_t public;
132
133
  /**
134
   * Dispatcher
135
   */
136
  vici_dispatcher_t *dispatcher;
137
138
  /**
139
   * Query interface for counters
140
   */
141
  counters_query_t *counters;
142
143
  /**
144
   * Daemon startup timestamp
145
   */
146
  time_t uptime;
147
};
148
149
/**
150
 * Add the given mark/mask to the message using the provided labels
151
 */
152
static void add_mark(vici_builder_t *b, mark_t mark,
153
           char *label, char *mask_label)
154
0
{
155
0
  if (mark.value | mark.mask)
156
0
  {
157
0
    b->add_kv(b, label, "%.8x", mark.value);
158
0
    if (~mark.mask)
159
0
    {
160
0
      b->add_kv(b, mask_label, "%.8x", mark.mask);
161
0
    }
162
0
  }
163
0
}
164
165
/**
166
 * List the mode of a CHILD_SA or config
167
 */
168
static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
169
0
{
170
0
  ipsec_mode_t mode;
171
0
  char *sub_mode = "";
172
173
0
  if (child || cfg)
174
0
  {
175
0
    if (!cfg)
176
0
    {
177
0
      cfg = child->get_config(child);
178
0
    }
179
0
    mode = child ? child->get_mode(child) : cfg->get_mode(cfg);
180
0
    if (mode == MODE_TRANSPORT && cfg->has_option(cfg, OPT_PROXY_MODE))
181
0
    { /* only report this if the negotiated mode is actually TRANSPORT */
182
0
      sub_mode = "_PROXY";
183
0
    }
184
0
    b->add_kv(b, "mode", "%N%s", ipsec_mode_names, mode, sub_mode);
185
0
  }
186
0
}
187
188
/**
189
 * List the security label of a CHILD_SA or config
190
 */
191
static void list_label(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
192
0
{
193
0
  sec_label_t *label = NULL;
194
0
  chunk_t enc;
195
196
0
  if (child)
197
0
  {
198
0
    label = child->get_label(child);
199
0
  }
200
0
  else if (cfg)
201
0
  {
202
0
    label = cfg->get_label(cfg);
203
0
  }
204
0
  if (label)
205
0
  {
206
0
    enc = label->get_encoding(label);
207
0
    b->add_kv(b, "label", "%+B", &enc);
208
0
  }
209
0
}
210
211
/**
212
 * List additional key exchanges
213
 */
214
static void list_ake(vici_builder_t *b, proposal_t *proposal)
215
0
{
216
0
  transform_type_t transform;
217
0
  char ake_str[5];
218
0
  uint16_t alg;
219
0
  int ake;
220
221
0
  for (ake = 1; ake <= 7; ake++)
222
0
  {
223
0
    transform = ADDITIONAL_KEY_EXCHANGE_1 + ake - 1;
224
0
    if (proposal->get_algorithm(proposal, transform, &alg, NULL))
225
0
    {
226
0
      sprintf(ake_str, "ake%d", ake);
227
0
      b->add_kv(b, ake_str, "%N", key_exchange_method_names, alg);
228
0
    }
229
0
  }
230
0
}
231
232
/**
233
 * List IPsec-related details about a CHILD_SA
234
 */
235
static void list_child_ipsec(vici_builder_t *b, child_sa_t *child)
236
0
{
237
0
  proposal_t *proposal;
238
0
  uint16_t alg, ks;
239
0
  uint32_t if_id, cpu;
240
241
0
  b->add_kv(b, "protocol", "%N", protocol_id_names,
242
0
        child->get_protocol(child));
243
0
  if (child->has_encap(child))
244
0
  {
245
0
    b->add_kv(b, "encap", "yes");
246
0
  }
247
0
  b->add_kv(b, "spi-in", "%.8x", ntohl(child->get_spi(child, TRUE)));
248
0
  b->add_kv(b, "spi-out", "%.8x", ntohl(child->get_spi(child, FALSE)));
249
250
0
  if (child->get_ipcomp(child) != IPCOMP_NONE)
251
0
  {
252
0
    b->add_kv(b, "cpi-in", "%.4x", ntohs(child->get_cpi(child, TRUE)));
253
0
    b->add_kv(b, "cpi-out", "%.4x", ntohs(child->get_cpi(child, FALSE)));
254
0
  }
255
0
  add_mark(b, child->get_mark(child, TRUE), "mark-in", "mark-mask-in");
256
0
  add_mark(b, child->get_mark(child, FALSE), "mark-out", "mark-mask-out");
257
258
0
  if_id = child->get_if_id(child, TRUE);
259
0
  if (if_id)
260
0
  {
261
0
    b->add_kv(b, "if-id-in", "%.8x", if_id);
262
0
  }
263
0
  if_id = child->get_if_id(child, FALSE);
264
0
  if (if_id)
265
0
  {
266
0
    b->add_kv(b, "if-id-out", "%.8x", if_id);
267
0
  }
268
0
  if (child->use_per_cpu(child))
269
0
  {
270
0
    b->add_kv(b, "per-cpu-sas", "yes");
271
0
  }
272
0
  cpu = child->get_cpu(child);
273
0
  if (cpu != CPU_ID_MAX)
274
0
  {
275
0
    b->add_kv(b, "cpu", "%u", cpu);
276
0
  }
277
278
0
  proposal = child->get_proposal(child);
279
0
  if (proposal)
280
0
  {
281
0
    if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
282
0
                  &alg, &ks) && alg != ENCR_UNDEFINED)
283
0
    {
284
0
      b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
285
0
      if (ks)
286
0
      {
287
0
        b->add_kv(b, "encr-keysize", "%u", ks);
288
0
      }
289
0
    }
290
0
    if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
291
0
                  &alg, &ks) && alg != AUTH_UNDEFINED)
292
0
    {
293
0
      b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
294
0
      if (ks)
295
0
      {
296
0
        b->add_kv(b, "integ-keysize", "%u", ks);
297
0
      }
298
0
    }
299
0
    if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD,
300
0
                  &alg, NULL))
301
0
    {
302
0
      b->add_kv(b, "dh-group", "%N", key_exchange_method_names, alg);
303
0
    }
304
0
    list_ake(b, proposal);
305
0
    if (proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
306
0
                  &alg, NULL) && alg == EXT_SEQ_NUMBERS)
307
0
    {
308
0
      b->add_kv(b, "esn", "1");
309
0
    }
310
0
  }
311
0
}
312
313
/**
314
 * List usage and lifetime stats of a CHILD_SA
315
 */
316
static void list_child_stats(vici_builder_t *b, child_sa_t *child, time_t now)
317
0
{
318
0
  uint64_t bytes, packets;
319
0
  time_t t;
320
321
0
  child->get_usestats(child, TRUE,  &t, &bytes, &packets);
322
0
  b->add_kv(b, "bytes-in", "%" PRIu64, bytes);
323
0
  b->add_kv(b, "packets-in", "%" PRIu64, packets);
324
0
  if (t)
325
0
  {
326
0
    b->add_kv(b, "use-in", "%"PRIu64, (uint64_t)(now - t));
327
0
  }
328
329
0
  child->get_usestats(child, FALSE, &t, &bytes, &packets);
330
0
  b->add_kv(b, "bytes-out", "%"PRIu64, bytes);
331
0
  b->add_kv(b, "packets-out", "%"PRIu64, packets);
332
0
  if (t)
333
0
  {
334
0
    b->add_kv(b, "use-out", "%"PRIu64, (uint64_t)(now - t));
335
0
  }
336
337
0
  t = child->get_lifetime(child, FALSE);
338
0
  if (t)
339
0
  {
340
0
    b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
341
0
  }
342
0
  t = child->get_lifetime(child, TRUE);
343
0
  if (t)
344
0
  {
345
0
    b->add_kv(b, "life-time", "%"PRId64, (int64_t)(t - now));
346
0
  }
347
0
  t = child->get_installtime(child);
348
0
  b->add_kv(b, "install-time", "%"PRId64, (int64_t)(now - t));
349
0
}
350
351
/**
352
 * List details of a CHILD_SA
353
 */
354
static void list_child(private_vici_query_t *this, vici_builder_t *b,
355
             child_sa_t *child, time_t now)
356
0
{
357
0
  enumerator_t *enumerator;
358
0
  traffic_selector_t *ts;
359
0
  child_sa_state_t state;
360
361
0
  b->add_kv(b, "name", "%s", child->get_name(child));
362
0
  b->add_kv(b, "uniqueid", "%u", child->get_unique_id(child));
363
0
  b->add_kv(b, "reqid", "%u", child->get_reqid(child));
364
0
  state = child->get_state(child);
365
0
  b->add_kv(b, "state", "%N", child_sa_state_names, state);
366
0
  list_mode(b, child, NULL);
367
0
  list_label(b, child, NULL);
368
369
0
  switch (state)
370
0
  {
371
0
    case CHILD_INSTALLED:
372
0
    case CHILD_REKEYING:
373
0
    case CHILD_REKEYED:
374
0
    case CHILD_DELETING:
375
0
    case CHILD_DELETED:
376
0
      list_child_ipsec(b, child);
377
0
      list_child_stats(b, child, now);
378
0
      break;
379
0
    default:
380
0
      break;
381
0
  }
382
383
0
  b->begin_list(b, "local-ts");
384
0
  enumerator = child->create_ts_enumerator(child, TRUE);
385
0
  while (enumerator->enumerate(enumerator, &ts))
386
0
  {
387
0
    b->add_li(b, "%R", ts);
388
0
  }
389
0
  enumerator->destroy(enumerator);
390
0
  b->end_list(b /* local-ts */);
391
392
0
  b->begin_list(b, "remote-ts");
393
0
  enumerator = child->create_ts_enumerator(child, FALSE);
394
0
  while (enumerator->enumerate(enumerator, &ts))
395
0
  {
396
0
    b->add_li(b, "%R", ts);
397
0
  }
398
0
  enumerator->destroy(enumerator);
399
0
  b->end_list(b /* remote-ts */);
400
0
}
401
402
/**
403
 * List tasks in a specific queue
404
 */
405
static void list_task_queue(private_vici_query_t *this, vici_builder_t *b,
406
              ike_sa_t *ike_sa, task_queue_t q, char *name)
407
0
{
408
0
  enumerator_t *enumerator;
409
0
  bool has = FALSE;
410
0
  task_t *task;
411
412
0
  enumerator = ike_sa->create_task_enumerator(ike_sa, q);
413
0
  while (enumerator->enumerate(enumerator, &task))
414
0
  {
415
0
    if (!has)
416
0
    {
417
0
      b->begin_list(b, name);
418
0
      has = TRUE;
419
0
    }
420
0
    b->add_li(b, "%N", task_type_names, task->get_type(task));
421
0
  }
422
0
  enumerator->destroy(enumerator);
423
0
  if (has)
424
0
  {
425
0
    b->end_list(b);
426
0
  }
427
0
}
428
429
/**
430
 * Add an IKE_SA condition to the given builder
431
 */
432
static void add_condition(vici_builder_t *b, ike_sa_t *ike_sa,
433
              char *key, ike_condition_t cond)
434
0
{
435
0
  if (ike_sa->has_condition(ike_sa, cond))
436
0
  {
437
0
    b->add_kv(b, key, "yes");
438
0
  }
439
0
}
440
441
/**
442
 * List virtual IPs
443
 */
444
static void list_vips(private_vici_query_t *this, vici_builder_t *b,
445
            ike_sa_t *ike_sa, bool local, char *name)
446
0
{
447
0
  enumerator_t *enumerator;
448
0
  bool has = FALSE;
449
0
  host_t *vip;
450
451
0
  enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
452
0
  while (enumerator->enumerate(enumerator, &vip))
453
0
  {
454
0
    if (!has)
455
0
    {
456
0
      b->begin_list(b, name);
457
0
      has = TRUE;
458
0
    }
459
0
    b->add_li(b, "%H", vip);
460
0
  }
461
0
  enumerator->destroy(enumerator);
462
0
  if (has)
463
0
  {
464
0
    b->end_list(b);
465
0
  }
466
0
}
467
468
/**
469
 * List details of an IKE_SA
470
 */
471
static void list_ike(private_vici_query_t *this, vici_builder_t *b,
472
           ike_sa_t *ike_sa, time_t now)
473
0
{
474
0
  time_t t;
475
0
  ike_sa_id_t *id;
476
0
  identification_t *eap;
477
0
  proposal_t *proposal;
478
0
  uint32_t if_id;
479
0
  uint16_t alg, ks;
480
0
  host_t *host;
481
482
0
  b->add_kv(b, "uniqueid", "%u", ike_sa->get_unique_id(ike_sa));
483
0
  b->add_kv(b, "version", "%u", ike_sa->get_version(ike_sa));
484
0
  b->add_kv(b, "state", "%N", ike_sa_state_names, ike_sa->get_state(ike_sa));
485
486
0
  host = ike_sa->get_my_host(ike_sa);
487
0
  b->add_kv(b, "local-host", "%H", host);
488
0
  b->add_kv(b, "local-port", "%d", host->get_port(host));
489
0
  b->add_kv(b, "local-id", "%Y", ike_sa->get_my_id(ike_sa));
490
491
0
  host = ike_sa->get_other_host(ike_sa);
492
0
  b->add_kv(b, "remote-host", "%H", host);
493
0
  b->add_kv(b, "remote-port", "%d", host->get_port(host));
494
0
  b->add_kv(b, "remote-id", "%Y", ike_sa->get_other_id(ike_sa));
495
496
0
  eap = ike_sa->get_other_eap_id(ike_sa);
497
498
0
  if (!eap->equals(eap, ike_sa->get_other_id(ike_sa)))
499
0
  {
500
0
    if (ike_sa->get_version(ike_sa) == IKEV1)
501
0
    {
502
0
      b->add_kv(b, "remote-xauth-id", "%Y", eap);
503
0
    }
504
0
    else
505
0
    {
506
0
      b->add_kv(b, "remote-eap-id", "%Y", eap);
507
0
    }
508
0
  }
509
510
0
  id = ike_sa->get_id(ike_sa);
511
0
  if (id->is_initiator(id))
512
0
  {
513
0
    b->add_kv(b, "initiator", "yes");
514
0
  }
515
0
  b->add_kv(b, "initiator-spi", "%.16"PRIx64,
516
0
        be64toh(id->get_initiator_spi(id)));
517
0
  b->add_kv(b, "responder-spi", "%.16"PRIx64,
518
0
        be64toh(id->get_responder_spi(id)));
519
520
0
  add_condition(b, ike_sa, "nat-local", COND_NAT_HERE);
521
0
  add_condition(b, ike_sa, "nat-remote", COND_NAT_THERE);
522
0
  add_condition(b, ike_sa, "nat-fake", COND_NAT_FAKE);
523
0
  add_condition(b, ike_sa, "nat-any", COND_NAT_ANY);
524
525
0
  if_id = ike_sa->get_if_id(ike_sa, TRUE);
526
0
  if (if_id)
527
0
  {
528
0
    b->add_kv(b, "if-id-in", "%.8x", if_id);
529
0
  }
530
0
  if_id = ike_sa->get_if_id(ike_sa, FALSE);
531
0
  if (if_id)
532
0
  {
533
0
    b->add_kv(b, "if-id-out", "%.8x", if_id);
534
0
  }
535
536
0
  proposal = ike_sa->get_proposal(ike_sa);
537
0
  if (proposal)
538
0
  {
539
0
    if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &ks))
540
0
    {
541
0
      b->add_kv(b, "encr-alg", "%N", encryption_algorithm_names, alg);
542
0
      if (ks)
543
0
      {
544
0
        b->add_kv(b, "encr-keysize", "%u", ks);
545
0
      }
546
0
    }
547
0
    if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, &ks))
548
0
    {
549
0
      b->add_kv(b, "integ-alg", "%N", integrity_algorithm_names, alg);
550
0
      if (ks)
551
0
      {
552
0
        b->add_kv(b, "integ-keysize", "%u", ks);
553
0
      }
554
0
    }
555
0
    if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL))
556
0
    {
557
0
      b->add_kv(b, "prf-alg", "%N", pseudo_random_function_names, alg);
558
0
    }
559
0
    if (proposal->get_algorithm(proposal, KEY_EXCHANGE_METHOD, &alg, NULL))
560
0
    {
561
0
      b->add_kv(b, "dh-group", "%N", key_exchange_method_names, alg);
562
0
    }
563
0
    list_ake(b, proposal);
564
0
  }
565
0
  add_condition(b, ike_sa, "ppk", COND_PPK);
566
567
0
  if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED)
568
0
  {
569
0
    t = ike_sa->get_statistic(ike_sa, STAT_ESTABLISHED);
570
0
    b->add_kv(b, "established", "%"PRId64, (int64_t)(now - t));
571
0
    t = ike_sa->get_statistic(ike_sa, STAT_REKEY);
572
0
    if (t)
573
0
    {
574
0
      b->add_kv(b, "rekey-time", "%"PRId64, (int64_t)(t - now));
575
0
    }
576
0
    t = ike_sa->get_statistic(ike_sa, STAT_REAUTH);
577
0
    if (t)
578
0
    {
579
0
      b->add_kv(b, "reauth-time", "%"PRId64, (int64_t)(t - now));
580
0
    }
581
0
  }
582
583
0
  list_vips(this, b, ike_sa, TRUE, "local-vips");
584
0
  list_vips(this, b, ike_sa, FALSE, "remote-vips");
585
586
0
  list_task_queue(this, b, ike_sa, TASK_QUEUE_QUEUED, "tasks-queued");
587
0
  list_task_queue(this, b, ike_sa, TASK_QUEUE_ACTIVE, "tasks-active");
588
0
  list_task_queue(this, b, ike_sa, TASK_QUEUE_PASSIVE, "tasks-passive");
589
0
}
590
591
CALLBACK(list_sas, vici_message_t*,
592
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
593
0
{
594
0
  vici_builder_t *b;
595
0
  enumerator_t *isas, *csas;
596
0
  ike_sa_t *ike_sa;
597
0
  child_sa_t *child_sa;
598
0
  time_t now;
599
0
  char *ike, *child;
600
0
  u_int ike_id, child_id;
601
0
  bool bl;
602
0
  char buf[BUF_LEN];
603
604
0
  bl = request->get_str(request, NULL, "noblock") == NULL;
605
0
  ike = request->get_str(request, NULL, "ike");
606
0
  ike_id = request->get_int(request, 0, "ike-id");
607
0
  child = request->get_str(request, NULL, "child");
608
0
  child_id = request->get_int(request, 0, "child-id");
609
610
0
  isas = charon->controller->create_ike_sa_enumerator(charon->controller, bl);
611
0
  while (isas->enumerate(isas, &ike_sa))
612
0
  {
613
0
    if (ike && !streq(ike, ike_sa->get_name(ike_sa)))
614
0
    {
615
0
      continue;
616
0
    }
617
0
    if (ike_id && ike_id != ike_sa->get_unique_id(ike_sa))
618
0
    {
619
0
      continue;
620
0
    }
621
622
0
    now = time_monotonic(NULL);
623
624
0
    b = vici_builder_create();
625
0
    b->begin_section(b, ike_sa->get_name(ike_sa));
626
627
0
    list_ike(this, b, ike_sa, now);
628
629
0
    b->begin_section(b, "child-sas");
630
0
    csas = ike_sa->create_child_sa_enumerator(ike_sa);
631
0
    while (csas->enumerate(csas, &child_sa))
632
0
    {
633
0
      if (child && !streq(child, child_sa->get_name(child_sa)))
634
0
      {
635
0
        continue;
636
0
      }
637
0
      if (child_id && child_sa->get_unique_id(child_sa) != child_id)
638
0
      {
639
0
        continue;
640
0
      }
641
642
0
      snprintf(buf, sizeof(buf), "%s-%u", child_sa->get_name(child_sa),
643
0
           child_sa->get_unique_id(child_sa));
644
0
      b->begin_section(b, buf);
645
0
      list_child(this, b, child_sa, now);
646
0
      b->end_section(b);
647
0
    }
648
0
    csas->destroy(csas);
649
0
    b->end_section(b /* child-sas */ );
650
651
0
    b->end_section(b);
652
653
0
    this->dispatcher->raise_event(this->dispatcher, "list-sa", id,
654
0
                    b->finalize(b));
655
0
  }
656
0
  isas->destroy(isas);
657
658
0
  b = vici_builder_create();
659
0
  return b->finalize(b);
660
0
}
661
662
/**
663
 * Raise a list-policy event for given CHILD_SA
664
 */
665
static void raise_policy(private_vici_query_t *this, u_int id, char *ike,
666
             child_sa_t *child)
667
0
{
668
0
  enumerator_t *enumerator;
669
0
  traffic_selector_t *ts;
670
0
  vici_builder_t *b;
671
0
  char buf[BUF_LEN];
672
673
0
  b = vici_builder_create();
674
0
  snprintf(buf, sizeof(buf), "%s/%s", ike, child->get_name(child));
675
0
  b->begin_section(b, buf);
676
0
  b->add_kv(b, "child", "%s", child->get_name(child));
677
0
  b->add_kv(b, "reqid", "%u", child->get_reqid(child));
678
0
  b->add_kv(b, "ike", "%s", ike);
679
680
0
  list_mode(b, child, NULL);
681
0
  list_label(b, child, NULL);
682
683
0
  b->begin_list(b, "local-ts");
684
0
  enumerator = child->create_ts_enumerator(child, TRUE);
685
0
  while (enumerator->enumerate(enumerator, &ts))
686
0
  {
687
0
    b->add_li(b, "%R", ts);
688
0
  }
689
0
  enumerator->destroy(enumerator);
690
0
  b->end_list(b /* local-ts */);
691
692
0
  b->begin_list(b, "remote-ts");
693
0
  enumerator = child->create_ts_enumerator(child, FALSE);
694
0
  while (enumerator->enumerate(enumerator, &ts))
695
0
  {
696
0
    b->add_li(b, "%R", ts);
697
0
  }
698
0
  enumerator->destroy(enumerator);
699
0
  b->end_list(b /* remote-ts */);
700
701
0
  b->end_section(b);
702
703
0
  this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
704
0
                  b->finalize(b));
705
0
}
706
707
/**
708
 * Raise a list-policy event for given CHILD_SA config
709
 */
710
static void raise_policy_cfg(private_vici_query_t *this, u_int id, char *ike,
711
               child_cfg_t *cfg)
712
0
{
713
0
  enumerator_t *enumerator;
714
0
  linked_list_t *list;
715
0
  traffic_selector_t *ts;
716
0
  vici_builder_t *b;
717
0
  char buf[BUF_LEN];
718
719
0
  b = vici_builder_create();
720
0
  snprintf(buf, sizeof(buf), "%s%s%s", ike ? ike : "", ike ? "/" : "",
721
0
       cfg->get_name(cfg));
722
0
  b->begin_section(b, buf);
723
0
  b->add_kv(b, "child", "%s", cfg->get_name(cfg));
724
0
  if (ike)
725
0
  {
726
0
    b->add_kv(b, "ike", "%s", ike);
727
0
  }
728
729
0
  list_mode(b, NULL, cfg);
730
0
  list_label(b, NULL, cfg);
731
732
0
  b->begin_list(b, "local-ts");
733
0
  list = cfg->get_traffic_selectors(cfg, TRUE, NULL);
734
0
  enumerator = list->create_enumerator(list);
735
0
  while (enumerator->enumerate(enumerator, &ts))
736
0
  {
737
0
    b->add_li(b, "%R", ts);
738
0
  }
739
0
  enumerator->destroy(enumerator);
740
0
  list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
741
0
  b->end_list(b /* local-ts */);
742
743
0
  b->begin_list(b, "remote-ts");
744
0
  list = cfg->get_traffic_selectors(cfg, FALSE, NULL);
745
0
  enumerator = list->create_enumerator(list);
746
0
  while (enumerator->enumerate(enumerator, &ts))
747
0
  {
748
0
    b->add_li(b, "%R", ts);
749
0
  }
750
0
  enumerator->destroy(enumerator);
751
0
  list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
752
0
  b->end_list(b /* remote-ts */);
753
754
0
  b->end_section(b);
755
756
0
  this->dispatcher->raise_event(this->dispatcher, "list-policy", id,
757
0
                  b->finalize(b));
758
0
}
759
760
CALLBACK(list_policies, vici_message_t*,
761
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
762
0
{
763
0
  enumerator_t *enumerator;
764
0
  vici_builder_t *b;
765
0
  child_sa_t *child_sa;
766
0
  peer_cfg_t *peer_cfg;
767
0
  child_cfg_t *child_cfg;
768
0
  bool drop, pass, trap;
769
0
  char *child, *ike, *ns;
770
771
0
  drop = request->get_str(request, NULL, "drop") != NULL;
772
0
  pass = request->get_str(request, NULL, "pass") != NULL;
773
0
  trap = request->get_str(request, NULL, "trap") != NULL;
774
0
  child = request->get_str(request, NULL, "child");
775
0
  ike = request->get_str(request, NULL, "ike");
776
777
0
  if (trap)
778
0
  {
779
0
    enumerator = charon->traps->create_enumerator(charon->traps);
780
0
    while (enumerator->enumerate(enumerator, &peer_cfg, &child_sa))
781
0
    {
782
0
      if ((ike && !streq(ike, peer_cfg->get_name(peer_cfg))) ||
783
0
        (child && !streq(child, child_sa->get_name(child_sa))))
784
0
      {
785
0
        continue;
786
0
      }
787
0
      raise_policy(this, id, peer_cfg->get_name(peer_cfg), child_sa);
788
0
    }
789
0
    enumerator->destroy(enumerator);
790
0
  }
791
792
0
  if (drop || pass)
793
0
  {
794
0
    enumerator = charon->shunts->create_enumerator(charon->shunts);
795
0
    while (enumerator->enumerate(enumerator, &ns, &child_cfg))
796
0
    {
797
0
      if ((ike && !streq(ike, ns)) ||
798
0
        (child && !streq(child, child_cfg->get_name(child_cfg))))
799
0
      {
800
0
        continue;
801
0
      }
802
0
      switch (child_cfg->get_mode(child_cfg))
803
0
      {
804
0
        case MODE_DROP:
805
0
          if (drop)
806
0
          {
807
0
            raise_policy_cfg(this, id, ns, child_cfg);
808
0
          }
809
0
          break;
810
0
        case MODE_PASS:
811
0
          if (pass)
812
0
          {
813
0
            raise_policy_cfg(this, id, ns, child_cfg);
814
0
          }
815
0
          break;
816
0
        default:
817
0
          break;
818
0
      }
819
0
    }
820
0
    enumerator->destroy(enumerator);
821
0
  }
822
823
0
  b = vici_builder_create();
824
0
  return b->finalize(b);
825
0
}
826
827
/**
828
 * Build sections for auth configs, local or remote
829
 */
830
static void build_auth_cfgs(peer_cfg_t *peer_cfg, bool local, vici_builder_t *b)
831
0
{
832
0
  enumerator_t *enumerator, *rules;
833
0
  auth_rule_t rule;
834
0
  auth_cfg_t *auth;
835
0
  union {
836
0
    uintptr_t u;
837
0
    identification_t *id;
838
0
    certificate_t *cert;
839
0
    char *str;
840
0
  } v;
841
0
  char buf[32];
842
0
  int i = 0;
843
844
0
  enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
845
0
  while (enumerator->enumerate(enumerator, &auth))
846
0
  {
847
0
    snprintf(buf, sizeof(buf), "%s-%d", local ? "local" : "remote", ++i);
848
0
    b->begin_section(b, buf);
849
850
0
    rules = auth->create_enumerator(auth);
851
0
    while (rules->enumerate(rules, &rule, &v))
852
0
    {
853
0
      switch (rule)
854
0
      {
855
0
        case AUTH_RULE_AUTH_CLASS:
856
0
          b->add_kv(b, "class", "%N", auth_class_names, v.u);
857
0
          break;
858
0
        case AUTH_RULE_EAP_TYPE:
859
0
          b->add_kv(b, "eap-type", "%N", eap_type_names, v.u);
860
0
          break;
861
0
        case AUTH_RULE_EAP_VENDOR:
862
0
          b->add_kv(b, "eap-vendor", "%u", v.u);
863
0
          break;
864
0
        case AUTH_RULE_XAUTH_BACKEND:
865
0
          b->add_kv(b, "xauth", "%s", v.str);
866
0
          break;
867
0
        case AUTH_RULE_CRL_VALIDATION:
868
0
          b->add_kv(b, "revocation", "%N", cert_validation_names, v.u);
869
0
          break;
870
0
        case AUTH_RULE_IDENTITY:
871
0
          b->add_kv(b, "id", "%Y", v.id);
872
0
          break;
873
0
        case AUTH_RULE_CA_IDENTITY:
874
0
          b->add_kv(b, "ca_id", "%Y", v.id);
875
0
          break;
876
0
        case AUTH_RULE_AAA_IDENTITY:
877
0
          b->add_kv(b, "aaa_id", "%Y", v.id);
878
0
          break;
879
0
        case AUTH_RULE_EAP_IDENTITY:
880
0
          b->add_kv(b, "eap_id", "%Y", v.id);
881
0
          break;
882
0
        case AUTH_RULE_XAUTH_IDENTITY:
883
0
          b->add_kv(b, "xauth_id", "%Y", v.id);
884
0
          break;
885
0
        default:
886
0
          break;
887
0
      }
888
0
    }
889
0
    rules->destroy(rules);
890
891
0
    b->begin_list(b, "groups");
892
0
    rules = auth->create_enumerator(auth);
893
0
    while (rules->enumerate(rules, &rule, &v))
894
0
    {
895
0
      if (rule == AUTH_RULE_GROUP)
896
0
      {
897
0
        b->add_li(b, "%Y", v.id);
898
0
      }
899
0
    }
900
0
    rules->destroy(rules);
901
0
    b->end_list(b);
902
903
0
    b->begin_list(b, "cert_policy");
904
0
    rules = auth->create_enumerator(auth);
905
0
    while (rules->enumerate(rules, &rule, &v))
906
0
    {
907
0
      if (rule == AUTH_RULE_CERT_POLICY)
908
0
      {
909
0
        b->add_li(b, "%s", v.str);
910
0
      }
911
0
    }
912
0
    rules->destroy(rules);
913
0
    b->end_list(b);
914
915
0
    b->begin_list(b, "certs");
916
0
    rules = auth->create_enumerator(auth);
917
0
    while (rules->enumerate(rules, &rule, &v))
918
0
    {
919
0
      if (rule == AUTH_RULE_SUBJECT_CERT)
920
0
      {
921
0
        b->add_li(b, "%Y", v.cert->get_subject(v.cert));
922
0
      }
923
0
    }
924
0
    rules->destroy(rules);
925
0
    b->end_list(b);
926
927
0
    b->begin_list(b, "cacerts");
928
0
    rules = auth->create_enumerator(auth);
929
0
    while (rules->enumerate(rules, &rule, &v))
930
0
    {
931
0
      if (rule == AUTH_RULE_CA_CERT)
932
0
      {
933
0
        b->add_li(b, "%Y", v.cert->get_subject(v.cert));
934
0
      }
935
0
    }
936
0
    rules->destroy(rules);
937
0
    b->end_list(b);
938
939
0
    b->end_section(b);
940
0
  }
941
0
  enumerator->destroy(enumerator);
942
0
}
943
944
CALLBACK(list_conns, vici_message_t*,
945
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
946
0
{
947
0
  enumerator_t *enumerator, *tokens, *selectors, *children;
948
0
  peer_cfg_t *peer_cfg;
949
0
  ike_cfg_t *ike_cfg;
950
0
  child_cfg_t *child_cfg;
951
0
  char *ike, *str, *interface;
952
0
  uint32_t manual_prio, dpd_delay, dpd_timeout;
953
0
  identification_t *ppk_id;
954
0
  linked_list_t *list;
955
0
  traffic_selector_t *ts;
956
0
  lifetime_cfg_t *lft;
957
0
  vici_builder_t *b;
958
959
0
  ike = request->get_str(request, NULL, "ike");
960
961
0
  enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
962
0
                      NULL, NULL, NULL, NULL, IKE_ANY);
963
0
  while (enumerator->enumerate(enumerator, &peer_cfg))
964
0
  {
965
0
    if (ike && !streq(ike, peer_cfg->get_name(peer_cfg)))
966
0
    {
967
0
      continue;
968
0
    }
969
970
0
    b = vici_builder_create();
971
0
    b->begin_section(b, peer_cfg->get_name(peer_cfg));
972
973
0
    ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
974
975
0
    b->begin_list(b, "local_addrs");
976
0
    str = ike_cfg->get_my_addr(ike_cfg);
977
0
    tokens = enumerator_create_token(str, ",", " ");
978
0
    while (tokens->enumerate(tokens, &str))
979
0
    {
980
0
      b->add_li(b, "%s", str);
981
0
    }
982
0
    tokens->destroy(tokens);
983
0
    b->end_list(b);
984
985
0
    b->begin_list(b, "remote_addrs");
986
0
    str = ike_cfg->get_other_addr(ike_cfg);
987
0
    tokens = enumerator_create_token(str, ",", " ");
988
0
    while (tokens->enumerate(tokens, &str))
989
0
    {
990
0
      b->add_li(b, "%s", str);
991
0
    }
992
0
    tokens->destroy(tokens);
993
0
    b->end_list(b);
994
995
0
    b->add_kv(b, "local_port", "%u",
996
0
          ike_cfg->get_my_port(ike_cfg));
997
0
    b->add_kv(b, "remote_port", "%u",
998
0
          ike_cfg->get_other_port(ike_cfg));
999
1000
0
    b->add_kv(b, "version", "%N", ike_version_names,
1001
0
          peer_cfg->get_ike_version(peer_cfg));
1002
0
    b->add_kv(b, "reauth_time", "%u",
1003
0
          peer_cfg->get_reauth_time(peer_cfg, FALSE));
1004
0
    b->add_kv(b, "rekey_time", "%u",
1005
0
          peer_cfg->get_rekey_time(peer_cfg, FALSE));
1006
0
    b->add_kv(b, "unique", "%N", unique_policy_names,
1007
0
          peer_cfg->get_unique_policy(peer_cfg));
1008
1009
0
    dpd_delay = peer_cfg->get_dpd(peer_cfg);
1010
0
    if (dpd_delay)
1011
0
    {
1012
0
      b->add_kv(b, "dpd_delay", "%u", dpd_delay);
1013
0
    }
1014
1015
0
    dpd_timeout = peer_cfg->get_dpd_timeout(peer_cfg);
1016
0
    if (dpd_timeout)
1017
0
    {
1018
0
      b->add_kv(b, "dpd_timeout", "%u", dpd_timeout);
1019
0
    }
1020
1021
0
    ppk_id = peer_cfg->get_ppk_id(peer_cfg);
1022
0
    if (ppk_id)
1023
0
    {
1024
0
      b->add_kv(b, "ppk_id", "%Y", ppk_id);
1025
0
    }
1026
0
    if (peer_cfg->has_option(peer_cfg, OPT_PPK_REQUIRED))
1027
0
    {
1028
0
      b->add_kv(b, "ppk_required", "yes");
1029
0
    }
1030
1031
0
    build_auth_cfgs(peer_cfg, TRUE, b);
1032
0
    build_auth_cfgs(peer_cfg, FALSE, b);
1033
1034
0
    b->begin_section(b, "children");
1035
1036
0
    children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
1037
0
    while (children->enumerate(children, &child_cfg))
1038
0
    {
1039
0
      b->begin_section(b, child_cfg->get_name(child_cfg));
1040
1041
0
      list_mode(b, NULL, child_cfg);
1042
0
      list_label(b, NULL, child_cfg);
1043
1044
0
      lft = child_cfg->get_lifetime(child_cfg, FALSE);
1045
0
      b->add_kv(b, "rekey_time",    "%"PRIu64, lft->time.rekey);
1046
0
      b->add_kv(b, "rekey_bytes",   "%"PRIu64, lft->bytes.rekey);
1047
0
      b->add_kv(b, "rekey_packets", "%"PRIu64, lft->packets.rekey);
1048
0
      free(lft);
1049
1050
0
      b->add_kv(b, "dpd_action", "%N", action_names,
1051
0
            child_cfg->get_dpd_action(child_cfg));
1052
0
      b->add_kv(b, "close_action", "%N", action_names,
1053
0
            child_cfg->get_close_action(child_cfg));
1054
1055
0
      b->begin_list(b, "local-ts");
1056
0
      list = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL);
1057
0
      selectors = list->create_enumerator(list);
1058
0
      while (selectors->enumerate(selectors, &ts))
1059
0
      {
1060
0
        b->add_li(b, "%R", ts);
1061
0
      }
1062
0
      selectors->destroy(selectors);
1063
0
      list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
1064
0
      b->end_list(b /* local-ts */);
1065
1066
0
      b->begin_list(b, "remote-ts");
1067
0
      list = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL);
1068
0
      selectors = list->create_enumerator(list);
1069
0
      while (selectors->enumerate(selectors, &ts))
1070
0
      {
1071
0
        b->add_li(b, "%R", ts);
1072
0
      }
1073
0
      selectors->destroy(selectors);
1074
0
      list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
1075
0
      b->end_list(b /* remote-ts */);
1076
1077
0
      interface = child_cfg->get_interface(child_cfg);
1078
0
      if (interface)
1079
0
      {
1080
0
        b->add_kv(b, "interface", "%s", interface);
1081
0
      }
1082
1083
0
      manual_prio = child_cfg->get_manual_prio(child_cfg);
1084
0
      if (manual_prio)
1085
0
      {
1086
0
        b->add_kv(b, "priority", "%u", manual_prio);
1087
0
      }
1088
1089
0
      b->end_section(b);
1090
0
    }
1091
0
    children->destroy(children);
1092
1093
0
    b->end_section(b); /* children */
1094
1095
0
    b->end_section(b); /* name */
1096
1097
0
    this->dispatcher->raise_event(this->dispatcher, "list-conn", id,
1098
0
                    b->finalize(b));
1099
0
  }
1100
0
  enumerator->destroy(enumerator);
1101
1102
0
  b = vici_builder_create();
1103
0
  return b->finalize(b);
1104
0
}
1105
1106
/**
1107
 * Do we have a private key for given certificate
1108
 */
1109
static bool has_privkey(certificate_t *cert)
1110
0
{
1111
0
  private_key_t *private;
1112
0
  public_key_t *public;
1113
0
  identification_t *keyid;
1114
0
  chunk_t chunk;
1115
0
  bool found = FALSE;
1116
1117
0
  public = cert->get_public_key(cert);
1118
0
  if (public)
1119
0
  {
1120
0
    if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
1121
0
    {
1122
0
      keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
1123
0
      private = lib->credmgr->get_private(lib->credmgr,
1124
0
                public->get_type(public), keyid, NULL);
1125
0
      if (private)
1126
0
      {
1127
0
        found = TRUE;
1128
0
        private->destroy(private);
1129
0
      }
1130
0
      keyid->destroy(keyid);
1131
0
    }
1132
0
    public->destroy(public);
1133
0
  }
1134
0
  return found;
1135
0
}
1136
1137
/**
1138
 * Store cert filter data
1139
 */
1140
typedef struct {
1141
  certificate_type_t type;
1142
  x509_flag_t flag;
1143
  identification_t *subject;
1144
} cert_filter_t;
1145
1146
/**
1147
 * Enumerate all X.509 certificates with a given flag
1148
 */
1149
static void enum_x509(private_vici_query_t *this, u_int id,
1150
            linked_list_t *certs, cert_filter_t *filter,
1151
            x509_flag_t flag)
1152
0
{
1153
0
  enumerator_t *enumerator;
1154
0
  certificate_t *cert;
1155
0
  vici_builder_t *b;
1156
0
  chunk_t encoding;
1157
0
  x509_t *x509;
1158
1159
0
  if (filter->type != CERT_ANY && filter->flag != X509_ANY &&
1160
0
    filter->flag != flag)
1161
0
  {
1162
0
    return;
1163
0
  }
1164
1165
0
  enumerator = certs->create_enumerator(certs);
1166
0
  while (enumerator->enumerate(enumerator, &cert))
1167
0
  {
1168
0
    x509 = (x509_t*)cert;
1169
0
    if ((x509->get_flags(x509) & X509_ANY) != flag)
1170
0
    {
1171
0
      continue;
1172
0
    }
1173
1174
0
    if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
1175
0
    {
1176
0
      b = vici_builder_create();
1177
0
      b->add_kv(b, "type", "%N", certificate_type_names, CERT_X509);
1178
0
      b->add_kv(b, "flag", "%N", x509_flag_names, flag);
1179
0
      if (has_privkey(cert))
1180
0
      {
1181
0
        b->add_kv(b, "has_privkey", "yes");
1182
0
      }
1183
0
      b->add(b, VICI_KEY_VALUE, "data", encoding);
1184
0
      free(encoding.ptr);
1185
1186
0
      this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
1187
0
                      b->finalize(b));
1188
0
    }
1189
0
  }
1190
0
  enumerator->destroy(enumerator);
1191
0
}
1192
1193
/**
1194
 * Enumerate all non-X.509 certificate types
1195
 */
1196
static void enum_others(private_vici_query_t *this, u_int id,
1197
            linked_list_t *certs, certificate_type_t type)
1198
0
{
1199
0
  enumerator_t *enumerator;
1200
0
  certificate_t *cert;
1201
0
  vici_builder_t *b;
1202
0
  chunk_t encoding, t_ch;
1203
0
  cred_encoding_type_t encoding_type;
1204
0
  identification_t *subject;
1205
0
  time_t not_before, not_after;
1206
1207
0
  encoding_type = (type == CERT_TRUSTED_PUBKEY) ? PUBKEY_SPKI_ASN1_DER :
1208
0
                          CERT_ASN1_DER;
1209
1210
0
  enumerator = certs->create_enumerator(certs);
1211
0
  while (enumerator->enumerate(enumerator, &cert))
1212
0
  {
1213
0
    if (cert->get_encoding(cert, encoding_type, &encoding))
1214
0
    {
1215
0
      b = vici_builder_create();
1216
0
      b->add_kv(b, "type", "%N", certificate_type_names, type);
1217
0
      if (has_privkey(cert))
1218
0
      {
1219
0
        b->add_kv(b, "has_privkey", "yes");
1220
0
      }
1221
0
      b->add(b, VICI_KEY_VALUE, "data", encoding);
1222
0
      free(encoding.ptr);
1223
1224
0
      if (type == CERT_TRUSTED_PUBKEY)
1225
0
      {
1226
0
        subject = cert->get_subject(cert);
1227
0
        if (subject->get_type(subject) != ID_KEY_ID)
1228
0
        {
1229
0
          b->add_kv(b, "subject", "%Y", cert->get_subject(cert));
1230
0
        }
1231
0
        cert->get_validity(cert, NULL, &not_before, &not_after);
1232
0
        if (not_before != UNDEFINED_TIME)
1233
0
        {
1234
0
          t_ch = asn1_from_time(&not_before, ASN1_GENERALIZEDTIME);
1235
0
          b->add(b, VICI_KEY_VALUE, "not-before", chunk_skip(t_ch, 2));
1236
0
          chunk_free(&t_ch);
1237
0
        }
1238
0
        if (not_after != UNDEFINED_TIME)
1239
0
        {
1240
0
          t_ch = asn1_from_time(&not_after, ASN1_GENERALIZEDTIME);
1241
0
          b->add(b, VICI_KEY_VALUE, "not-after", chunk_skip(t_ch, 2));
1242
0
          chunk_free(&t_ch);
1243
0
        }
1244
0
      }
1245
0
      this->dispatcher->raise_event(this->dispatcher, "list-cert", id,
1246
0
                      b->finalize(b));
1247
0
    }
1248
0
  }
1249
0
  enumerator->destroy(enumerator);
1250
0
}
1251
1252
/**
1253
 * Enumerate all certificates of a given type
1254
 */
1255
static void enum_certs(private_vici_query_t *this,  u_int id,
1256
             cert_filter_t *filter, certificate_type_t type)
1257
0
{
1258
0
  enumerator_t *e1, *e2;
1259
0
  certificate_t *cert, *current;
1260
0
  linked_list_t *certs;
1261
0
  bool found;
1262
1263
0
  if (filter->type != CERT_ANY && filter->type != type)
1264
0
  {
1265
0
    return;
1266
0
  }
1267
0
  certs = linked_list_create();
1268
1269
0
  e1 = lib->credmgr->create_cert_enumerator(lib->credmgr, type, KEY_ANY,
1270
0
                        filter->subject, FALSE);
1271
0
  while (e1->enumerate(e1, &cert))
1272
0
  {
1273
0
    found = FALSE;
1274
1275
0
    e2 = certs->create_enumerator(certs);
1276
0
    while (e2->enumerate(e2, &current))
1277
0
    {
1278
0
      if (current->equals(current, cert))
1279
0
      {
1280
0
        found = TRUE;
1281
0
        break;
1282
0
      }
1283
0
    }
1284
0
    e2->destroy(e2);
1285
1286
0
    if (!found)
1287
0
    {
1288
0
      certs->insert_last(certs, cert->get_ref(cert));
1289
0
    }
1290
0
  }
1291
0
  e1->destroy(e1);
1292
1293
0
  if (type == CERT_X509)
1294
0
  {
1295
0
    enum_x509(this, id, certs, filter, X509_NONE);
1296
0
    enum_x509(this, id, certs, filter, X509_CA);
1297
0
    enum_x509(this, id, certs, filter, X509_AA);
1298
0
    enum_x509(this, id, certs, filter, X509_OCSP_SIGNER);
1299
0
  }
1300
0
  else
1301
0
  {
1302
0
    enum_others(this, id, certs, type);
1303
0
  }
1304
0
  certs->destroy_offset(certs, offsetof(certificate_t, destroy));
1305
0
}
1306
1307
CALLBACK(list_certs, vici_message_t*,
1308
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1309
0
{
1310
0
  cert_filter_t filter = {
1311
0
    .type = CERT_ANY,
1312
0
    .flag = X509_ANY,
1313
0
    .subject = NULL
1314
0
  };
1315
0
  vici_builder_t *b;
1316
0
  char *str;
1317
1318
0
  str = request->get_str(request, "ANY", "type");
1319
0
  if (enum_from_name(certificate_type_names, str, &filter.type))
1320
0
  {
1321
0
    if (filter.type == CERT_X509)
1322
0
    {
1323
0
      str = request->get_str(request, "ANY", "flag");
1324
0
      if (!enum_from_name(x509_flag_names, str, &filter.flag))
1325
0
      {
1326
0
        DBG1(DBG_CFG, "invalid certificate flag '%s'", str);
1327
0
        goto finalize;
1328
0
      }
1329
0
    }
1330
0
  }
1331
0
  else if  (!vici_cert_info_from_str(str, &filter.type, &filter.flag))
1332
0
  {
1333
0
    DBG1(DBG_CFG, "invalid certificate type '%s'", str);
1334
0
    goto finalize;
1335
0
  }
1336
1337
0
  str = request->get_str(request, NULL, "subject");
1338
0
  if (str)
1339
0
  {
1340
0
    filter.subject = identification_create_from_string(str);
1341
0
  }
1342
1343
0
  enum_certs(this, id, &filter, CERT_TRUSTED_PUBKEY);
1344
0
  enum_certs(this, id, &filter, CERT_X509);
1345
0
  enum_certs(this, id, &filter, CERT_X509_AC);
1346
0
  enum_certs(this, id, &filter, CERT_X509_CRL);
1347
0
  enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE);
1348
0
  DESTROY_IF(filter.subject);
1349
1350
0
finalize:
1351
0
  b = vici_builder_create();
1352
0
  return b->finalize(b);
1353
0
}
1354
1355
/**
1356
 * Add a key/value pair of ALG => plugin
1357
 */
1358
static void add_algorithm(vici_builder_t *b, enum_name_t *alg_names,
1359
              int alg_type, const char *plugin_name)
1360
0
{
1361
0
  char alg_name[BUF_LEN];
1362
1363
0
  sprintf(alg_name, "%N", alg_names, alg_type);
1364
0
  b->add_kv(b, alg_name, (char*)plugin_name);
1365
0
}
1366
1367
CALLBACK(get_algorithms, vici_message_t*,
1368
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1369
0
{
1370
0
  vici_builder_t *b;
1371
0
  enumerator_t *enumerator;
1372
0
  encryption_algorithm_t encryption;
1373
0
  integrity_algorithm_t integrity;
1374
0
  hash_algorithm_t hash;
1375
0
  pseudo_random_function_t prf;
1376
0
  ext_out_function_t xof;
1377
0
  key_derivation_function_t kdf;
1378
0
  drbg_type_t drbg;
1379
0
  key_exchange_method_t group;
1380
0
  rng_quality_t quality;
1381
0
  const char *plugin_name;
1382
1383
0
  b = vici_builder_create();
1384
1385
0
  b->begin_section(b, "encryption");
1386
0
  enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
1387
0
  while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1388
0
  {
1389
0
    add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
1390
0
  }
1391
0
  enumerator->destroy(enumerator);
1392
0
  b->end_section(b);
1393
1394
0
  b->begin_section(b, "integrity");
1395
0
  enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
1396
0
  while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
1397
0
  {
1398
0
    add_algorithm(b, integrity_algorithm_names, integrity, plugin_name);
1399
0
  }
1400
0
  enumerator->destroy(enumerator);
1401
0
  b->end_section(b);
1402
1403
0
  b->begin_section(b, "aead");
1404
0
  enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
1405
0
  while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
1406
0
  {
1407
0
    add_algorithm(b, encryption_algorithm_names, encryption, plugin_name);
1408
0
  }
1409
0
  enumerator->destroy(enumerator);
1410
0
  b->end_section(b);
1411
1412
0
  b->begin_section(b, "hasher");
1413
0
  enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
1414
0
  while (enumerator->enumerate(enumerator, &hash, &plugin_name))
1415
0
  {
1416
0
    add_algorithm(b, hash_algorithm_names, hash, plugin_name);
1417
0
  }
1418
0
  enumerator->destroy(enumerator);
1419
0
  b->end_section(b);
1420
1421
0
  b->begin_section(b, "prf");
1422
0
  enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
1423
0
  while (enumerator->enumerate(enumerator, &prf, &plugin_name))
1424
0
  {
1425
0
    add_algorithm(b, pseudo_random_function_names, prf, plugin_name);
1426
0
  }
1427
0
  enumerator->destroy(enumerator);
1428
0
  b->end_section(b);
1429
1430
0
  b->begin_section(b, "xof");
1431
0
  enumerator = lib->crypto->create_xof_enumerator(lib->crypto);
1432
0
  while (enumerator->enumerate(enumerator, &xof, &plugin_name))
1433
0
  {
1434
0
    add_algorithm(b, ext_out_function_names, xof, plugin_name);
1435
0
  }
1436
0
  enumerator->destroy(enumerator);
1437
0
  b->end_section(b);
1438
1439
0
  b->begin_section(b, "kdf");
1440
0
  enumerator = lib->crypto->create_kdf_enumerator(lib->crypto);
1441
0
  while (enumerator->enumerate(enumerator, &kdf, &plugin_name))
1442
0
  {
1443
0
    add_algorithm(b, key_derivation_function_names, kdf, plugin_name);
1444
0
  }
1445
0
  enumerator->destroy(enumerator);
1446
0
  b->end_section(b);
1447
1448
0
  b->begin_section(b, "drbg");
1449
0
  enumerator = lib->crypto->create_drbg_enumerator(lib->crypto);
1450
0
  while (enumerator->enumerate(enumerator, &drbg, &plugin_name))
1451
0
  {
1452
0
    add_algorithm(b, drbg_type_names, drbg, plugin_name);
1453
0
  }
1454
0
  enumerator->destroy(enumerator);
1455
0
  b->end_section(b);
1456
1457
0
  b->begin_section(b, "ke");
1458
0
  enumerator = lib->crypto->create_ke_enumerator(lib->crypto);
1459
0
  while (enumerator->enumerate(enumerator, &group, &plugin_name))
1460
0
  {
1461
0
    add_algorithm(b, key_exchange_method_names, group, plugin_name);
1462
0
  }
1463
0
  enumerator->destroy(enumerator);
1464
0
  b->end_section(b);
1465
1466
0
  b->begin_section(b, "rng");
1467
0
  enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
1468
0
  while (enumerator->enumerate(enumerator, &quality, &plugin_name))
1469
0
  {
1470
0
    add_algorithm(b, rng_quality_names, quality, plugin_name);
1471
0
  }
1472
0
  enumerator->destroy(enumerator);
1473
0
  b->end_section(b);
1474
1475
0
  b->begin_section(b, "nonce-gen");
1476
0
  enumerator = lib->crypto->create_nonce_gen_enumerator(lib->crypto);
1477
0
  while (enumerator->enumerate(enumerator, &plugin_name))
1478
0
  {
1479
0
    b->add_kv(b, "NONCE_GEN", (char*)plugin_name);
1480
0
  }
1481
0
  enumerator->destroy(enumerator);
1482
0
  b->end_section(b);
1483
1484
0
  return b->finalize(b);
1485
0
}
1486
1487
/**
1488
 * Make sure we have the counters query interface
1489
 */
1490
static inline bool ensure_counters(private_vici_query_t *this)
1491
0
{
1492
0
  if (this->counters)
1493
0
  {
1494
0
    return TRUE;
1495
0
  }
1496
0
  return (this->counters = lib->get(lib, "counters")) != NULL;
1497
0
}
1498
1499
/**
1500
 * Add a single set of counters to the message
1501
 *
1502
 * Frees the array of counter values
1503
 */
1504
static void add_counters(vici_builder_t *b, char *name, uint64_t *counters)
1505
0
{
1506
0
  char buf[BUF_LEN];
1507
0
  counter_type_t i;
1508
1509
0
  b->begin_section(b, name ?: "");
1510
0
  for (i = 0; i < COUNTER_MAX; i++)
1511
0
  {
1512
0
    snprintf(buf, sizeof(buf), "%N", vici_counter_type_names, i);
1513
0
    b->add_kv(b, buf, "%"PRIu64, counters[i]);
1514
0
  }
1515
0
  b->end_section(b);
1516
0
  free(counters);
1517
0
}
1518
1519
CALLBACK(get_counters, vici_message_t*,
1520
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1521
0
{
1522
0
  vici_builder_t *b;
1523
0
  enumerator_t *enumerator;
1524
0
  uint64_t *counters;
1525
0
  char *conn, *errmsg = NULL;
1526
0
  bool all;
1527
1528
0
  b = vici_builder_create();
1529
1530
0
  if (ensure_counters(this))
1531
0
  {
1532
0
    conn = request->get_str(request, NULL, "name");
1533
0
    all = request->get_bool(request, FALSE, "all");
1534
1535
0
    b->begin_section(b, "counters");
1536
0
    if (all)
1537
0
    {
1538
0
      enumerator = this->counters->get_names(this->counters);
1539
0
      while (enumerator->enumerate(enumerator, &conn))
1540
0
      {
1541
0
        counters = this->counters->get_all(this->counters, conn);
1542
0
        if (counters)
1543
0
        {
1544
0
          add_counters(b, conn, counters);
1545
0
        }
1546
0
      }
1547
0
      enumerator->destroy(enumerator);
1548
0
    }
1549
0
    else
1550
0
    {
1551
0
      counters = this->counters->get_all(this->counters, conn);
1552
0
      if (counters)
1553
0
      {
1554
0
        add_counters(b, conn, counters);
1555
0
      }
1556
0
      else
1557
0
      {
1558
0
        errmsg = "no counters found for this connection";
1559
0
      }
1560
0
    }
1561
0
    b->end_section(b);
1562
0
  }
1563
0
  else
1564
0
  {
1565
0
    errmsg = "no counters available (plugin missing?)";
1566
0
  }
1567
1568
0
  b->add_kv(b, "success", errmsg ? "no" : "yes");
1569
0
  if (errmsg)
1570
0
  {
1571
0
    b->add_kv(b, "errmsg", "%s", errmsg);
1572
0
  }
1573
0
  return b->finalize(b);
1574
0
}
1575
1576
CALLBACK(reset_counters, vici_message_t*,
1577
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1578
0
{
1579
0
  vici_builder_t *b;
1580
0
  char *conn, *errmsg = NULL;
1581
0
  bool all;
1582
1583
0
  b = vici_builder_create();
1584
1585
0
  if (ensure_counters(this))
1586
0
  {
1587
0
    conn = request->get_str(request, NULL, "name");
1588
0
    all = request->get_bool(request, FALSE, "all");
1589
1590
0
    if (all)
1591
0
    {
1592
0
      this->counters->reset_all(this->counters);
1593
0
    }
1594
0
    else
1595
0
    {
1596
0
      this->counters->reset(this->counters, conn);
1597
0
    }
1598
0
  }
1599
0
  else
1600
0
  {
1601
0
    errmsg = "no counters available (plugin missing?)";
1602
0
  }
1603
1604
0
  b->add_kv(b, "success", errmsg ? "no" : "yes");
1605
0
  if (errmsg)
1606
0
  {
1607
0
    b->add_kv(b, "errmsg", "%s", errmsg);
1608
0
  }
1609
0
  return b->finalize(b);
1610
0
}
1611
1612
CALLBACK(version, vici_message_t*,
1613
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1614
0
{
1615
0
  vici_builder_t *b;
1616
1617
0
  b = vici_builder_create();
1618
0
  b->add_kv(b, "daemon", "%s", lib->ns);
1619
0
  b->add_kv(b, "version", "%s", VERSION);
1620
1621
#ifdef WIN32
1622
  {
1623
    OSVERSIONINFOEX osvie;
1624
1625
    memset(&osvie, 0, sizeof(osvie));
1626
    osvie.dwOSVersionInfoSize = sizeof(osvie);
1627
1628
    if (GetVersionEx((LPOSVERSIONINFO)&osvie))
1629
    {
1630
      b->add_kv(b, "sysname", "Windows %s",
1631
        osvie.wProductType == VER_NT_WORKSTATION ? "Client" : "Server");
1632
      b->add_kv(b, "release", "%d.%d.%d (SP %d.%d)",
1633
        osvie.dwMajorVersion, osvie.dwMinorVersion, osvie.dwBuildNumber,
1634
        osvie.wServicePackMajor, osvie.wServicePackMinor);
1635
      b->add_kv(b, "machine", "%s",
1636
#ifdef WIN64
1637
        "x86_64");
1638
#else
1639
        "x86");
1640
#endif /* !WIN64 */
1641
    }
1642
  }
1643
#else /* !WIN32 */
1644
0
  {
1645
0
    struct utsname utsname;
1646
1647
0
    if (uname(&utsname) == 0)
1648
0
    {
1649
0
      b->add_kv(b, "sysname", "%s", utsname.sysname);
1650
0
      b->add_kv(b, "release", "%s", utsname.release);
1651
0
      b->add_kv(b, "machine", "%s", utsname.machine);
1652
0
    }
1653
0
  }
1654
0
#endif /* !WIN32 */
1655
0
  return b->finalize(b);
1656
0
}
1657
1658
CALLBACK(stats, vici_message_t*,
1659
  private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
1660
0
{
1661
0
  vici_builder_t *b;
1662
0
  enumerator_t *enumerator;
1663
0
  plugin_t *plugin;
1664
0
  time_t since, now;
1665
0
  int i;
1666
1667
0
  b = vici_builder_create();
1668
1669
0
  now = time_monotonic(NULL);
1670
0
  since = time(NULL) - (now - this->uptime);
1671
1672
0
  b->begin_section(b, "uptime");
1673
0
  b->add_kv(b, "running", "%V", &now, &this->uptime);
1674
0
  b->add_kv(b, "since", "%T", &since, FALSE);
1675
0
  b->end_section(b);
1676
1677
0
  b->begin_section(b, "workers");
1678
0
  b->add_kv(b, "total", "%d",
1679
0
        lib->processor->get_total_threads(lib->processor));
1680
0
  b->add_kv(b, "idle", "%d",
1681
0
        lib->processor->get_idle_threads(lib->processor));
1682
0
  b->begin_section(b, "active");
1683
0
  for (i = 0; i < JOB_PRIO_MAX; i++)
1684
0
  {
1685
0
    b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
1686
0
          lib->processor->get_working_threads(lib->processor, i));
1687
0
  }
1688
0
  b->end_section(b);
1689
0
  b->end_section(b);
1690
1691
0
  b->begin_section(b, "queues");
1692
0
  for (i = 0; i < JOB_PRIO_MAX; i++)
1693
0
  {
1694
0
    b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
1695
0
          lib->processor->get_job_load(lib->processor, i));
1696
0
  }
1697
0
  b->end_section(b);
1698
1699
0
  b->add_kv(b, "scheduled", "%d",
1700
0
        lib->scheduler->get_job_load(lib->scheduler));
1701
1702
0
  b->begin_section(b, "ikesas");
1703
0
  b->add_kv(b, "total", "%u",
1704
0
    charon->ike_sa_manager->get_count(charon->ike_sa_manager));
1705
0
  b->add_kv(b, "half-open", "%u",
1706
0
    charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
1707
0
                          NULL, FALSE));
1708
0
  b->end_section(b);
1709
1710
0
  b->begin_list(b, "plugins");
1711
0
  enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
1712
0
  while (enumerator->enumerate(enumerator, &plugin, NULL))
1713
0
  {
1714
0
    b->add_li(b, "%s", plugin->get_name(plugin));
1715
0
  }
1716
0
  enumerator->destroy(enumerator);
1717
0
  b->end_list(b);
1718
1719
#ifdef WIN32
1720
  {
1721
    DWORD lasterr = ERROR_INVALID_HANDLE;
1722
    HANDLE heaps[32];
1723
    int i, count;
1724
    char buf[16];
1725
    size_t total = 0;
1726
    int allocs = 0;
1727
1728
    b->begin_section(b, "mem");
1729
    count = GetProcessHeaps(countof(heaps), heaps);
1730
    for (i = 0; i < count; i++)
1731
    {
1732
      PROCESS_HEAP_ENTRY entry = {};
1733
      size_t heap_total = 0;
1734
      int heap_allocs = 0;
1735
1736
      if (HeapLock(heaps[i]))
1737
      {
1738
        while (HeapWalk(heaps[i], &entry))
1739
        {
1740
          if (entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
1741
          {
1742
            heap_total += entry.cbData;
1743
            heap_allocs++;
1744
          }
1745
        }
1746
        lasterr = GetLastError();
1747
        HeapUnlock(heaps[i]);
1748
      }
1749
      if (lasterr != ERROR_NO_MORE_ITEMS)
1750
      {
1751
        break;
1752
      }
1753
      snprintf(buf, sizeof(buf), "heap-%d", i);
1754
      b->begin_section(b, buf);
1755
      b->add_kv(b, "total", "%zu", heap_total);
1756
      b->add_kv(b, "allocs", "%d", heap_allocs);
1757
      b->end_section(b);
1758
1759
      total += heap_total;
1760
      allocs += heap_allocs;
1761
    }
1762
    if (lasterr == ERROR_NO_MORE_ITEMS)
1763
    {
1764
      b->add_kv(b, "total", "%zu", total);
1765
      b->add_kv(b, "allocs", "%d", allocs);
1766
    }
1767
    b->end_section(b);
1768
  }
1769
#endif
1770
1771
0
  {
1772
#ifdef HAVE_MALLINFO2
1773
    struct mallinfo2 mi = mallinfo2();
1774
1775
    b->begin_section(b, "mallinfo");
1776
    b->add_kv(b, "sbrk", "%zu", mi.arena);
1777
    b->add_kv(b, "mmap", "%zu", mi.hblkhd);
1778
    b->add_kv(b, "used", "%zu", mi.uordblks);
1779
    b->add_kv(b, "free", "%zu", mi.fordblks);
1780
    b->end_section(b);
1781
#elif defined(HAVE_MALLINFO)
1782
    struct mallinfo mi = mallinfo();
1783
1784
0
    b->begin_section(b, "mallinfo");
1785
0
    b->add_kv(b, "sbrk", "%u", mi.arena);
1786
0
    b->add_kv(b, "mmap", "%u", mi.hblkhd);
1787
0
    b->add_kv(b, "used", "%u", mi.uordblks);
1788
0
    b->add_kv(b, "free", "%u", mi.fordblks);
1789
0
    b->end_section(b);
1790
0
#endif /* HAVE_MALLINFO(2) */
1791
0
  }
1792
1793
0
  return b->finalize(b);
1794
0
}
1795
1796
static void manage_command(private_vici_query_t *this,
1797
               char *name, vici_command_cb_t cb, bool reg)
1798
0
{
1799
0
  this->dispatcher->manage_command(this->dispatcher, name,
1800
0
                   reg ? cb : NULL, this);
1801
0
}
1802
1803
/**
1804
 * (Un-)register dispatcher functions
1805
 */
1806
static void manage_commands(private_vici_query_t *this, bool reg)
1807
0
{
1808
0
  this->dispatcher->manage_event(this->dispatcher, "list-sa", reg);
1809
0
  this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
1810
0
  this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
1811
0
  this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
1812
0
  this->dispatcher->manage_event(this->dispatcher, "ike-updown", reg);
1813
0
  this->dispatcher->manage_event(this->dispatcher, "ike-rekey", reg);
1814
0
  this->dispatcher->manage_event(this->dispatcher, "ike-update", reg);
1815
0
  this->dispatcher->manage_event(this->dispatcher, "child-updown", reg);
1816
0
  this->dispatcher->manage_event(this->dispatcher, "child-rekey", reg);
1817
0
  this->dispatcher->manage_event(this->dispatcher, "alert", reg);
1818
0
  manage_command(this, "list-sas", list_sas, reg);
1819
0
  manage_command(this, "list-policies", list_policies, reg);
1820
0
  manage_command(this, "list-conns", list_conns, reg);
1821
0
  manage_command(this, "list-certs", list_certs, reg);
1822
0
  manage_command(this, "get-algorithms", get_algorithms, reg);
1823
0
  manage_command(this, "get-counters", get_counters, reg);
1824
0
  manage_command(this, "reset-counters", reset_counters, reg);
1825
0
  manage_command(this, "version", version, reg);
1826
0
  manage_command(this, "stats", stats, reg);
1827
0
}
1828
1829
METHOD(listener_t, ike_updown, bool,
1830
  private_vici_query_t *this, ike_sa_t *ike_sa, bool up)
1831
0
{
1832
0
  vici_builder_t *b;
1833
0
  time_t now;
1834
1835
0
  if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-updown"))
1836
0
  {
1837
0
    return TRUE;
1838
0
  }
1839
1840
0
  now = time_monotonic(NULL);
1841
1842
0
  b = vici_builder_create();
1843
1844
0
  if (up)
1845
0
  {
1846
0
    b->add_kv(b, "up", "yes");
1847
0
  }
1848
1849
0
  b->begin_section(b, ike_sa->get_name(ike_sa));
1850
0
  list_ike(this, b, ike_sa, now);
1851
0
  b->end_section(b);
1852
1853
0
  this->dispatcher->raise_event(this->dispatcher,
1854
0
                  "ike-updown", 0, b->finalize(b));
1855
1856
0
  return TRUE;
1857
0
}
1858
1859
METHOD(listener_t, ike_rekey, bool,
1860
  private_vici_query_t *this, ike_sa_t *old, ike_sa_t *new)
1861
0
{
1862
0
  vici_builder_t *b;
1863
0
  time_t now;
1864
1865
0
  if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-rekey"))
1866
0
  {
1867
0
    return TRUE;
1868
0
  }
1869
1870
0
  now = time_monotonic(NULL);
1871
1872
0
  b = vici_builder_create();
1873
0
  b->begin_section(b, old->get_name(old));
1874
0
  b->begin_section(b, "old");
1875
0
  list_ike(this, b, old, now);
1876
0
  b->end_section(b);
1877
0
  b->begin_section(b, "new");
1878
0
  list_ike(this, b, new, now);
1879
0
  b->end_section(b);
1880
0
  b->end_section(b);
1881
1882
0
  this->dispatcher->raise_event(this->dispatcher,
1883
0
                  "ike-rekey", 0, b->finalize(b));
1884
1885
0
  return TRUE;
1886
0
}
1887
1888
METHOD(listener_t, ike_update, bool,
1889
  private_vici_query_t *this, ike_sa_t *ike_sa, host_t *local, host_t *remote)
1890
0
{
1891
0
  vici_builder_t *b;
1892
0
  time_t now;
1893
1894
0
  if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-update"))
1895
0
  {
1896
0
    return TRUE;
1897
0
  }
1898
1899
0
  now = time_monotonic(NULL);
1900
1901
0
  b = vici_builder_create();
1902
1903
0
  b->add_kv(b, "local-host", "%H", local);
1904
0
  b->add_kv(b, "local-port", "%d", local->get_port(local));
1905
0
  b->add_kv(b, "remote-host", "%H", remote);
1906
0
  b->add_kv(b, "remote-port", "%d", remote->get_port(remote));
1907
1908
0
  b->begin_section(b, ike_sa->get_name(ike_sa));
1909
0
  list_ike(this, b, ike_sa, now);
1910
0
  b->end_section(b);
1911
1912
0
  this->dispatcher->raise_event(this->dispatcher,
1913
0
                  "ike-update", 0, b->finalize(b));
1914
1915
0
  return TRUE;
1916
0
}
1917
1918
METHOD(listener_t, child_updown, bool,
1919
  private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
1920
0
{
1921
0
  vici_builder_t *b;
1922
0
  time_t now;
1923
0
  char buf[BUF_LEN];
1924
1925
0
  if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-updown"))
1926
0
  {
1927
0
    return TRUE;
1928
0
  }
1929
1930
0
  now = time_monotonic(NULL);
1931
0
  b = vici_builder_create();
1932
1933
0
  if (up)
1934
0
  {
1935
0
    b->add_kv(b, "up", "yes");
1936
0
  }
1937
1938
0
  b->begin_section(b, ike_sa->get_name(ike_sa));
1939
0
  list_ike(this, b, ike_sa, now);
1940
0
  b->begin_section(b, "child-sas");
1941
1942
0
  snprintf(buf, sizeof(buf), "%s-%u", child_sa->get_name(child_sa),
1943
0
       child_sa->get_unique_id(child_sa));
1944
1945
0
  b->begin_section(b, buf);
1946
0
  list_child(this, b, child_sa, now);
1947
0
  b->end_section(b);
1948
1949
0
  b->end_section(b);
1950
0
  b->end_section(b);
1951
1952
0
  this->dispatcher->raise_event(this->dispatcher,
1953
0
                  "child-updown", 0, b->finalize(b));
1954
1955
0
  return TRUE;
1956
0
}
1957
1958
METHOD(listener_t, child_rekey, bool,
1959
  private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *old,
1960
  child_sa_t *new)
1961
0
{
1962
0
  vici_builder_t *b;
1963
0
  time_t now;
1964
1965
0
  if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-rekey"))
1966
0
  {
1967
0
    return TRUE;
1968
0
  }
1969
1970
0
  now = time_monotonic(NULL);
1971
0
  b = vici_builder_create();
1972
1973
0
  b->begin_section(b, ike_sa->get_name(ike_sa));
1974
0
  list_ike(this, b, ike_sa, now);
1975
0
  b->begin_section(b, "child-sas");
1976
1977
0
  b->begin_section(b, old->get_name(old));
1978
1979
0
  b->begin_section(b, "old");
1980
0
  list_child(this, b, old, now);
1981
0
  b->end_section(b);
1982
0
  b->begin_section(b, "new");
1983
0
  list_child(this, b, new, now);
1984
0
  b->end_section(b);
1985
1986
0
  b->end_section(b);
1987
1988
0
  b->end_section(b);
1989
0
  b->end_section(b);
1990
1991
0
  this->dispatcher->raise_event(this->dispatcher,
1992
0
                  "child-rekey", 0, b->finalize(b));
1993
1994
0
  return TRUE;
1995
0
}
1996
1997
METHOD(listener_t, alert, bool,
1998
  private_vici_query_t *this, ike_sa_t *ike_sa, alert_t alert, va_list args)
1999
0
{
2000
0
  vici_builder_t *b;
2001
2002
0
  if (!this->dispatcher->has_event_listeners(this->dispatcher, "alert"))
2003
0
  {
2004
0
    return TRUE;
2005
0
  }
2006
2007
0
  b = vici_builder_create();
2008
0
  b->add_kv(b, "type", "%N", alert_names, alert);
2009
0
  if (ike_sa)
2010
0
  {
2011
0
    b->begin_section(b, "ike-sa");
2012
0
    b->begin_section(b, ike_sa->get_name(ike_sa));
2013
0
    list_ike(this, b, ike_sa, time_monotonic(NULL));
2014
0
    b->end_section(b);
2015
0
    b->end_section(b);
2016
0
  }
2017
2018
0
  this->dispatcher->raise_event(this->dispatcher, "alert", 0, b->finalize(b));
2019
2020
0
  return TRUE;
2021
0
}
2022
2023
METHOD(vici_query_t, destroy, void,
2024
  private_vici_query_t *this)
2025
0
{
2026
0
  manage_commands(this, FALSE);
2027
0
  free(this);
2028
0
}
2029
2030
/**
2031
 * See header
2032
 */
2033
vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
2034
0
{
2035
0
  private_vici_query_t *this;
2036
2037
0
  INIT(this,
2038
0
    .public = {
2039
0
      .listener = {
2040
0
        .alert = _alert,
2041
0
        .ike_updown = _ike_updown,
2042
0
        .ike_rekey = _ike_rekey,
2043
0
        .ike_update = _ike_update,
2044
0
        .child_updown = _child_updown,
2045
0
        .child_rekey = _child_rekey,
2046
0
      },
2047
0
      .destroy = _destroy,
2048
0
    },
2049
0
    .dispatcher = dispatcher,
2050
0
    .uptime = time_monotonic(NULL),
2051
0
  );
2052
2053
0
  manage_commands(this, TRUE);
2054
2055
0
  return &this->public;
2056
0
}