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