12567168dSJake Freeland /*- 22567168dSJake Freeland * SPDX-License-Identifier: BSD-2-Clause 32567168dSJake Freeland * 42567168dSJake Freeland * Copyright (c) 2023 The FreeBSD Foundation 52567168dSJake Freeland * 62567168dSJake Freeland * This software was developed by Jake Freeland <jfree@FreeBSD.org> 72567168dSJake Freeland * under sponsorship from the FreeBSD Foundation. 82567168dSJake Freeland * 92567168dSJake Freeland * Redistribution and use in source and binary forms, with or without 102567168dSJake Freeland * modification, are permitted provided that the following conditions 112567168dSJake Freeland * are met: 122567168dSJake Freeland * 1. Redistributions of source code must retain the above copyright 132567168dSJake Freeland * notice, this list of conditions and the following disclaimer. 142567168dSJake Freeland * 2. Redistributions in binary form must reproduce the above copyright 152567168dSJake Freeland * notice, this list of conditions and the following disclaimer in the 162567168dSJake Freeland * documentation and/or other materials provided with the distribution. 172567168dSJake Freeland * 182567168dSJake Freeland * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 192567168dSJake Freeland * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202567168dSJake Freeland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 212567168dSJake Freeland * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 222567168dSJake Freeland * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 232567168dSJake Freeland * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 242567168dSJake Freeland * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 252567168dSJake Freeland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 262567168dSJake Freeland * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 272567168dSJake Freeland * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 282567168dSJake Freeland * SUCH DAMAGE. 292567168dSJake Freeland */ 302567168dSJake Freeland 312567168dSJake Freeland #include <sys/types.h> 322567168dSJake Freeland #include <sys/socket.h> 332567168dSJake Freeland 342567168dSJake Freeland #include <assert.h> 352567168dSJake Freeland #include <err.h> 362567168dSJake Freeland #include <libcasper.h> 372567168dSJake Freeland #include <netdb.h> 382567168dSJake Freeland #include <string.h> 392567168dSJake Freeland 402567168dSJake Freeland #include <casper/cap_net.h> 412567168dSJake Freeland 422567168dSJake Freeland #include "syslogd_cap.h" 432567168dSJake Freeland 442567168dSJake Freeland /* 452567168dSJake Freeland * Convert the given prop_filter structure into an nvlist. 462567168dSJake Freeland * Return a heap allocated pointer to the resulting nvlist. 472567168dSJake Freeland */ 482567168dSJake Freeland nvlist_t * 492567168dSJake Freeland prop_filter_to_nvlist(const struct prop_filter *pfilter) 502567168dSJake Freeland { 512567168dSJake Freeland nvlist_t *nvl_prop_filter = nvlist_create(0); 522567168dSJake Freeland 532567168dSJake Freeland nvlist_add_number(nvl_prop_filter, "prop_type", pfilter->prop_type); 542567168dSJake Freeland nvlist_add_number(nvl_prop_filter, "cmp_type", pfilter->cmp_type); 552567168dSJake Freeland nvlist_add_number(nvl_prop_filter, "cmp_flags", pfilter->cmp_flags); 562567168dSJake Freeland nvlist_add_string(nvl_prop_filter, "pflt_strval", pfilter->pflt_strval); 572567168dSJake Freeland /* 582567168dSJake Freeland * Do not bother adding pflt_re. It will be recompiled 592567168dSJake Freeland * using pflt_strval later, if applicable. 602567168dSJake Freeland */ 612567168dSJake Freeland 622567168dSJake Freeland return (nvl_prop_filter); 632567168dSJake Freeland } 642567168dSJake Freeland 652567168dSJake Freeland /* 662567168dSJake Freeland * Convert the given nvlist into a prop_filter structure. 672567168dSJake Freeland * Return a heap allocated pointer to the resulting prop_filter. 682567168dSJake Freeland */ 692567168dSJake Freeland struct prop_filter * 702567168dSJake Freeland nvlist_to_prop_filter(const nvlist_t *nvl_prop_filter) 712567168dSJake Freeland { 722567168dSJake Freeland struct prop_filter *pfilter; 732567168dSJake Freeland 742567168dSJake Freeland pfilter = calloc(1, sizeof(*pfilter)); 752567168dSJake Freeland if (pfilter == NULL) 762567168dSJake Freeland err(1, "calloc"); 772567168dSJake Freeland pfilter->prop_type = nvlist_get_number(nvl_prop_filter, "prop_type"); 782567168dSJake Freeland pfilter->cmp_type = nvlist_get_number(nvl_prop_filter, "cmp_type"); 792567168dSJake Freeland pfilter->cmp_flags = nvlist_get_number(nvl_prop_filter, "cmp_flags"); 802567168dSJake Freeland pfilter->pflt_strval = strdup(nvlist_get_string(nvl_prop_filter, 812567168dSJake Freeland "pflt_strval")); 822567168dSJake Freeland if (pfilter->cmp_type == FILT_CMP_REGEX) { 832567168dSJake Freeland int re_flags = REG_NOSUB; 842567168dSJake Freeland pfilter->pflt_re = calloc(1, sizeof(*pfilter->pflt_re)); 852567168dSJake Freeland if (pfilter->pflt_re == NULL) 862567168dSJake Freeland errx(1, "RE calloc() error"); 872567168dSJake Freeland if ((pfilter->cmp_flags & FILT_FLAG_EXTENDED) != 0) 882567168dSJake Freeland re_flags |= REG_EXTENDED; 892567168dSJake Freeland if ((pfilter->cmp_flags & FILT_FLAG_ICASE) != 0) 902567168dSJake Freeland re_flags |= REG_ICASE; 912567168dSJake Freeland if (regcomp(pfilter->pflt_re, pfilter->pflt_strval, 922567168dSJake Freeland re_flags) != 0) 932567168dSJake Freeland errx(1, "RE compilation error"); 942567168dSJake Freeland } 952567168dSJake Freeland 962567168dSJake Freeland return (pfilter); 972567168dSJake Freeland } 982567168dSJake Freeland 992567168dSJake Freeland /* 1002567168dSJake Freeland * Convert the given struct filed into an nvl_filed nvlist. 1012567168dSJake Freeland * Return a heap allocated pointer to the resulting nvlist. 1022567168dSJake Freeland */ 1032567168dSJake Freeland nvlist_t * 1042567168dSJake Freeland filed_to_nvlist(const struct filed *filed) 1052567168dSJake Freeland { 1062567168dSJake Freeland nvlist_t *nvl_filed = nvlist_create(0); 1072567168dSJake Freeland enum f_type f_type = filed->f_type; 1082567168dSJake Freeland size_t i, sz; 1092567168dSJake Freeland 1102567168dSJake Freeland nvlist_add_number(nvl_filed, "f_type", f_type); 1112567168dSJake Freeland nvlist_add_string(nvl_filed, "f_host", filed->f_host); 1122567168dSJake Freeland nvlist_add_string(nvl_filed, "f_program", filed->f_program); 1132567168dSJake Freeland if (filed->f_prop_filter != NULL) { 1142567168dSJake Freeland nvlist_add_nvlist(nvl_filed, "f_prop_filter", 1152567168dSJake Freeland prop_filter_to_nvlist(filed->f_prop_filter)); 1162567168dSJake Freeland } 1172567168dSJake Freeland sz = nitems(filed->f_pmask); 1182567168dSJake Freeland for (i = 0; i < sz; ++i) { 1192567168dSJake Freeland nvlist_append_number_array(nvl_filed, "f_pmask", 1202567168dSJake Freeland filed->f_pmask[i]); 1212567168dSJake Freeland } 1222567168dSJake Freeland sz = nitems(filed->f_pcmp); 1232567168dSJake Freeland for (i = 0; i < sz; ++i) { 1242567168dSJake Freeland nvlist_append_number_array(nvl_filed, "f_pcmp", 1252567168dSJake Freeland filed->f_pcmp[i]); 1262567168dSJake Freeland } 1272567168dSJake Freeland 1282567168dSJake Freeland if (filed->f_file >= 0) 1292567168dSJake Freeland nvlist_add_descriptor(nvl_filed, "f_file", filed->f_file); 1302567168dSJake Freeland nvlist_add_number(nvl_filed, "f_flags", filed->f_flags); 1312567168dSJake Freeland if (f_type == F_WALL || f_type == F_USERS) { 1322567168dSJake Freeland sz = nitems(filed->f_uname); 1332567168dSJake Freeland for (i = 0; i < sz; ++i) { 1342567168dSJake Freeland nvlist_append_string_array(nvl_filed, "f_uname", 1352567168dSJake Freeland filed->f_uname[i]); 1362567168dSJake Freeland } 1372567168dSJake Freeland } else if (f_type == F_FILE || f_type == F_CONSOLE || f_type == F_TTY) { 1382567168dSJake Freeland nvlist_add_string(nvl_filed, "f_fname", filed->f_fname); 1392567168dSJake Freeland } else if (f_type == F_FORW) { 1402567168dSJake Freeland nvlist_add_string(nvl_filed, "f_hname", filed->f_hname); 1414ecbee27SJake Freeland nvlist_add_descriptor_array(nvl_filed, "f_addr_fds", 1424ecbee27SJake Freeland filed->f_addr_fds, filed->f_num_addr_fds); 143*ae4f708fSMark Johnston nvlist_add_binary(nvl_filed, "f_addrs", filed->f_addrs, 144*ae4f708fSMark Johnston filed->f_num_addr_fds * sizeof(*filed->f_addrs)); 1452567168dSJake Freeland } else if (filed->f_type == F_PIPE) { 1462567168dSJake Freeland nvlist_add_string(nvl_filed, "f_pname", filed->f_pname); 1472567168dSJake Freeland if (filed->f_procdesc >= 0) { 1482567168dSJake Freeland nvlist_add_descriptor(nvl_filed, "f_procdesc", 1492567168dSJake Freeland filed->f_procdesc); 1502567168dSJake Freeland } 1512567168dSJake Freeland } 1522567168dSJake Freeland 1532567168dSJake Freeland /* 1542567168dSJake Freeland * Book-keeping fields are not transferred. 1552567168dSJake Freeland */ 1562567168dSJake Freeland 1572567168dSJake Freeland return (nvl_filed); 1582567168dSJake Freeland } 1592567168dSJake Freeland 1602567168dSJake Freeland /* 1612567168dSJake Freeland * Convert the given nvl_filed nvlist into a struct filed. 1622567168dSJake Freeland * Return a heap allocated pointer to the resulting struct 1632567168dSJake Freeland * filed. 1642567168dSJake Freeland */ 1652567168dSJake Freeland struct filed * 1662567168dSJake Freeland nvlist_to_filed(const nvlist_t *nvl_filed) 1672567168dSJake Freeland { 1682567168dSJake Freeland struct filed *filed; 1692567168dSJake Freeland enum f_type f_type; 1702567168dSJake Freeland const uint64_t *narr; 1712567168dSJake Freeland size_t i, sz; 1722567168dSJake Freeland 1732567168dSJake Freeland filed = calloc(1, sizeof(*filed)); 1742567168dSJake Freeland if (filed == NULL) 1752567168dSJake Freeland err(1, "calloc"); 1762567168dSJake Freeland 1772567168dSJake Freeland f_type = filed->f_type = nvlist_get_number(nvl_filed, "f_type"); 1782567168dSJake Freeland (void)strlcpy(filed->f_host, nvlist_get_string(nvl_filed, "f_host"), 1792567168dSJake Freeland sizeof(filed->f_host)); 1802567168dSJake Freeland (void)strlcpy(filed->f_program, nvlist_get_string(nvl_filed, 1812567168dSJake Freeland "f_program"), sizeof(filed->f_program)); 1822567168dSJake Freeland if (nvlist_exists_nvlist(nvl_filed, "f_prop_filter")) { 1832567168dSJake Freeland filed->f_prop_filter = nvlist_to_prop_filter( 1842567168dSJake Freeland nvlist_get_nvlist(nvl_filed, "f_prop_filter")); 1852567168dSJake Freeland } 1862567168dSJake Freeland narr = nvlist_get_number_array(nvl_filed, "f_pmask", &sz); 1872567168dSJake Freeland assert(sz == nitems(filed->f_pmask)); 1882567168dSJake Freeland for (i = 0; i < sz; ++i) 1892567168dSJake Freeland filed->f_pmask[i] = narr[i]; 1902567168dSJake Freeland narr = nvlist_get_number_array(nvl_filed, "f_pcmp", &sz); 1912567168dSJake Freeland assert(sz == nitems(filed->f_pcmp)); 1922567168dSJake Freeland for (i = 0; i < sz; ++i) 1932567168dSJake Freeland filed->f_pcmp[i] = narr[i]; 1942567168dSJake Freeland 1952567168dSJake Freeland if (nvlist_exists_descriptor(nvl_filed, "f_file")) 1962567168dSJake Freeland filed->f_file = dup(nvlist_get_descriptor(nvl_filed, "f_file")); 1972567168dSJake Freeland else 1982567168dSJake Freeland filed->f_file = -1; 1992567168dSJake Freeland filed->f_flags = nvlist_get_number(nvl_filed, "f_flags"); 2002567168dSJake Freeland if (f_type == F_WALL || f_type == F_USERS) { 2012567168dSJake Freeland const char * const *f_uname; 2022567168dSJake Freeland 2032567168dSJake Freeland f_uname = nvlist_get_string_array(nvl_filed, "f_uname", &sz); 2042567168dSJake Freeland assert(sz == nitems(filed->f_uname)); 2052567168dSJake Freeland for (i = 0; i < sz; ++i) { 2062567168dSJake Freeland (void)strlcpy(filed->f_uname[i], f_uname[i], 2072567168dSJake Freeland sizeof(filed->f_uname[i])); 2082567168dSJake Freeland } 2092567168dSJake Freeland } else if (f_type == F_FILE || f_type == F_CONSOLE || f_type == F_TTY) { 2102567168dSJake Freeland (void)strlcpy(filed->f_fname, nvlist_get_string(nvl_filed, 2112567168dSJake Freeland "f_fname"), sizeof(filed->f_fname)); 2122567168dSJake Freeland } else if (f_type == F_FORW) { 2134ecbee27SJake Freeland const int *f_addr_fds; 2142567168dSJake Freeland 2152567168dSJake Freeland (void)strlcpy(filed->f_hname, nvlist_get_string(nvl_filed, 2162567168dSJake Freeland "f_hname"), sizeof(filed->f_hname)); 2174ecbee27SJake Freeland 2184ecbee27SJake Freeland f_addr_fds = nvlist_get_descriptor_array(nvl_filed, 2194ecbee27SJake Freeland "f_addr_fds", &filed->f_num_addr_fds); 2204ecbee27SJake Freeland filed->f_addr_fds = calloc(filed->f_num_addr_fds, 2214ecbee27SJake Freeland sizeof(*f_addr_fds)); 2224ecbee27SJake Freeland if (filed->f_addr_fds == NULL) 2234ecbee27SJake Freeland err(1, "calloc"); 2244ecbee27SJake Freeland for (i = 0; i < filed->f_num_addr_fds; ++i) { 2254ecbee27SJake Freeland filed->f_addr_fds[i] = dup(f_addr_fds[i]); 2264ecbee27SJake Freeland if (filed->f_addr_fds[i] < 0) 2274ecbee27SJake Freeland err(1, "dup"); 2282567168dSJake Freeland } 2292567168dSJake Freeland } else if (filed->f_type == F_PIPE) { 2302567168dSJake Freeland (void)strlcpy(filed->f_pname, nvlist_get_string(nvl_filed, 2312567168dSJake Freeland "f_pname"), sizeof(filed->f_pname)); 2322567168dSJake Freeland if (nvlist_exists_descriptor(nvl_filed, "f_procdesc")) { 2332567168dSJake Freeland filed->f_procdesc = dup(nvlist_get_descriptor(nvl_filed, 2342567168dSJake Freeland "f_procdesc")); 2352567168dSJake Freeland } else { 2362567168dSJake Freeland filed->f_procdesc = -1; 2372567168dSJake Freeland } 2382567168dSJake Freeland } 2392567168dSJake Freeland 2402567168dSJake Freeland /* 2412567168dSJake Freeland * Book-keeping fields are not transferred. 2422567168dSJake Freeland */ 2432567168dSJake Freeland 2442567168dSJake Freeland return (filed); 2452567168dSJake Freeland } 2462567168dSJake Freeland 2472567168dSJake Freeland nvlist_t * 2482567168dSJake Freeland cap_readconfigfile(cap_channel_t *chan, const char *path) 2492567168dSJake Freeland { 2502567168dSJake Freeland nvlist_t *nvl, *nvl_conf; 2512567168dSJake Freeland 2522567168dSJake Freeland nvl = nvlist_create(0); 2532567168dSJake Freeland nvlist_add_string(nvl, "cmd", "readconfigfile"); 2542567168dSJake Freeland nvlist_add_string(nvl, "path", path); 2552567168dSJake Freeland /* It is possible that our hostname has changed. */ 2562567168dSJake Freeland nvlist_add_string(nvl, "LocalHostName", LocalHostName); 2572567168dSJake Freeland nvl = cap_xfer_nvlist(chan, nvl); 2582567168dSJake Freeland if (nvl == NULL) { 2592567168dSJake Freeland logerror("Failed to xfer configuration nvlist"); 2602567168dSJake Freeland exit(1); 2612567168dSJake Freeland } 2622567168dSJake Freeland nvl_conf = nvlist_take_nvlist(nvl, "nvl_conf"); 2632567168dSJake Freeland 2642567168dSJake Freeland nvlist_destroy(nvl); 2652567168dSJake Freeland return (nvl_conf); 2662567168dSJake Freeland } 2672567168dSJake Freeland 2682567168dSJake Freeland /* 2692567168dSJake Freeland * Now that we're executing as libcasper, we can obtain the 2702567168dSJake Freeland * resources specified in the configuration. 2712567168dSJake Freeland */ 2722567168dSJake Freeland int 2732567168dSJake Freeland casper_readconfigfile(nvlist_t *nvlin, nvlist_t *nvlout) 2742567168dSJake Freeland { 27561a29ecaSJake Freeland const nvlist_t * const *filed_list; 27661a29ecaSJake Freeland nvlist_t *nvl_conf; 27761a29ecaSJake Freeland size_t n_fileds; 2782567168dSJake Freeland const char *path; 2792567168dSJake Freeland 2802567168dSJake Freeland /* 2812567168dSJake Freeland * Verify that syslogd did not manipulate the 2822567168dSJake Freeland * configuration file path. 2832567168dSJake Freeland */ 2842567168dSJake Freeland path = nvlist_get_string(nvlin, "path"); 2852567168dSJake Freeland if (strcmp(path, ConfFile) != 0) 2862567168dSJake Freeland err(1, "Configuration file mismatch: %s != %s", path, ConfFile); 2872567168dSJake Freeland 2882567168dSJake Freeland /* Refresh our copy of LocalHostName, in case it changed. */ 2892567168dSJake Freeland strlcpy(LocalHostName, nvlist_get_string(nvlin, "LocalHostName"), 2902567168dSJake Freeland sizeof(LocalHostName)); 2912567168dSJake Freeland 29261a29ecaSJake Freeland nvl_conf = readconfigfile(path); 29361a29ecaSJake Freeland 29461a29ecaSJake Freeland /* Remove old filed data in case we are reloading. */ 29561a29ecaSJake Freeland while (!SLIST_EMPTY(&cfiled_head)) { 29661a29ecaSJake Freeland struct cap_filed *cfiled; 29761a29ecaSJake Freeland 29861a29ecaSJake Freeland cfiled = SLIST_FIRST(&cfiled_head); 29961a29ecaSJake Freeland SLIST_REMOVE_HEAD(&cfiled_head, next); 30061a29ecaSJake Freeland free(cfiled); 30161a29ecaSJake Freeland } 30261a29ecaSJake Freeland /* Record F_PIPE filed data for use in p_open(). */ 30361a29ecaSJake Freeland if (!nvlist_exists_nvlist_array(nvl_conf, "filed_list")) 30461a29ecaSJake Freeland return (0); 30561a29ecaSJake Freeland filed_list = nvlist_get_nvlist_array(nvl_conf, "filed_list", &n_fileds); 30661a29ecaSJake Freeland for (size_t i = 0; i < n_fileds; ++i) { 30761a29ecaSJake Freeland if (nvlist_get_number(filed_list[i], "f_type") == F_PIPE) { 30861a29ecaSJake Freeland struct cap_filed *cfiled; 30961a29ecaSJake Freeland const char *pipe_cmd; 31061a29ecaSJake Freeland 31161a29ecaSJake Freeland cfiled = malloc(sizeof(*cfiled)); 31261a29ecaSJake Freeland if (cfiled == NULL) 31361a29ecaSJake Freeland err(1, "malloc"); 31461a29ecaSJake Freeland cfiled->idx = i; 31561a29ecaSJake Freeland pipe_cmd = nvlist_get_string(filed_list[i], "f_pname"); 31661a29ecaSJake Freeland strlcpy(cfiled->pipe_cmd, pipe_cmd, sizeof(cfiled->pipe_cmd)); 31761a29ecaSJake Freeland SLIST_INSERT_HEAD(&cfiled_head, cfiled, next); 31861a29ecaSJake Freeland } 31961a29ecaSJake Freeland } 32061a29ecaSJake Freeland 32161a29ecaSJake Freeland nvlist_move_nvlist(nvlout, "nvl_conf", nvl_conf); 3222567168dSJake Freeland return (0); 3232567168dSJake Freeland } 324