diff options
Diffstat (limited to 'usr.sbin/syslogd/syslogd_cap_log.c')
| -rw-r--r-- | usr.sbin/syslogd/syslogd_cap_log.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/usr.sbin/syslogd/syslogd_cap_log.c b/usr.sbin/syslogd/syslogd_cap_log.c new file mode 100644 index 000000000000..0156cc6f6b6c --- /dev/null +++ b/usr.sbin/syslogd/syslogd_cap_log.c @@ -0,0 +1,211 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 The FreeBSD Foundation + * + * This software was developed by Jake Freeland <jfree@FreeBSD.org> + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <assert.h> +#include <err.h> +#include <string.h> + +#include "syslogd_cap.h" + +struct cfiled_list cfiled_head; + +int +cap_p_open(cap_channel_t *chan, size_t filed_idx, const char *prog, + int *procdesc) +{ + nvlist_t *nvl = nvlist_create(0); + int error, pipedesc_w; + + nvlist_add_string(nvl, "cmd", "p_open"); + nvlist_add_number(nvl, "filed_idx", filed_idx); + nvlist_add_string(nvl, "prog", prog); + nvl = cap_xfer_nvlist(chan, nvl); + if (nvl == NULL) { + logerror("Failed to xfer p_open nvlist"); + exit(1); + } + error = nvlist_get_number(nvl, "error"); + if (error != 0) { + errno = error; + logerror("Failed to open piped command"); + } + pipedesc_w = dnvlist_take_descriptor(nvl, "pipedesc_w", -1); + *procdesc = dnvlist_take_descriptor(nvl, "procdesc", -1); + + nvlist_destroy(nvl); + return (pipedesc_w); +} + +int +casper_p_open(nvlist_t *nvlin, nvlist_t *nvlout) +{ + struct cap_filed *cfiled; + size_t filed_idx; + int pipedesc_w, procdesc = -1; + const char *prog; + + filed_idx = nvlist_get_number(nvlin, "filed_idx"); + prog = nvlist_get_string(nvlin, "prog"); + SLIST_FOREACH(cfiled, &cfiled_head, next) { + if (cfiled->idx != filed_idx) + continue; + if (strcmp(cfiled->pipe_cmd, prog) != 0) + return (-1); + + pipedesc_w = p_open(prog, &procdesc); + if (pipedesc_w == -1) + return (-1); + nvlist_move_descriptor(nvlout, "pipedesc_w", pipedesc_w); + nvlist_move_descriptor(nvlout, "procdesc", procdesc); + return (0); + } + + return (-1); +} + +const char * +cap_ttymsg(cap_channel_t *chan, struct iovec *iov, int iovcnt, + const char *line, int tmout) +{ + nvlist_t *nvl = nvlist_create(0); + int error; + static char errbuf[1024]; + char *ret = NULL; + + nvlist_add_string(nvl, "cmd", "ttymsg"); + for (int i = 0; i < iovcnt; ++i) + nvlist_append_string_array(nvl, "iov_strs", iov[i].iov_base); + nvlist_add_string(nvl, "line", line); + nvlist_add_number(nvl, "tmout", tmout); + + nvl = cap_xfer_nvlist(chan, nvl); + if (nvl == NULL) { + logerror("Failed to xfer ttymsg nvlist"); + exit(1); + } + error = nvlist_get_number(nvl, "error"); + if (error != 0) { + errno = error; + logerror("Failed to ttymsg"); + } + if (nvlist_exists_string(nvl, "errstr")) { + const char *errstr = nvlist_get_string(nvl, "errstr"); + (void)strlcpy(errbuf, errstr, sizeof(errbuf)); + ret = errbuf; + } + + nvlist_destroy(nvl); + return (ret); +} + +int +casper_ttymsg(nvlist_t *nvlin, nvlist_t *nvlout) +{ + char **nvlstrs; + struct iovec *iov; + size_t iovcnt; + int tmout; + const char *line; + + nvlstrs = nvlist_take_string_array(nvlin, "iov_strs", &iovcnt); + assert(iovcnt <= TTYMSG_IOV_MAX); + iov = calloc(iovcnt, sizeof(*iov)); + if (iov == NULL) + err(EXIT_FAILURE, "calloc"); + for (size_t i = 0; i < iovcnt; ++i) { + iov[i].iov_base = nvlstrs[i]; + iov[i].iov_len = strlen(nvlstrs[i]); + } + line = nvlist_get_string(nvlin, "line"); + tmout = nvlist_get_number(nvlin, "tmout"); + line = ttymsg(iov, iovcnt, line, tmout); + if (line != NULL) + nvlist_add_string(nvlout, "errstr", line); + + free(iov); + return (0); +} + +void +cap_wallmsg(cap_channel_t *chan, const struct filed *f, struct iovec *iov, + int iovcnt) +{ + nvlist_t *nvl = nvlist_create(0); + int error; + + nvlist_add_string(nvl, "cmd", "wallmsg"); + /* + * The filed_to_nvlist() function is not needed + * here because wallmsg() only uses f_type and + * fu_uname members, which are both inline. + */ + nvlist_add_binary(nvl, "filed", f, sizeof(*f)); + for (int i = 0; i < iovcnt; ++i) + nvlist_append_string_array(nvl, "iov_strs", iov[i].iov_base); + + nvl = cap_xfer_nvlist(chan, nvl); + if (nvl == NULL) { + logerror("Failed to xfer wallmsg nvlist"); + exit(1); + } + error = nvlist_get_number(nvl, "error"); + if (error != 0) { + errno = error; + logerror("Failed to wallmsg"); + } + nvlist_destroy(nvl); +} + +int +casper_wallmsg(nvlist_t *nvlin) +{ + const struct filed *f; + char **nvlstrs; + struct iovec *iov; + size_t sz; + + f = nvlist_get_binary(nvlin, "filed", &sz); + assert(sz == sizeof(*f)); + nvlstrs = nvlist_take_string_array(nvlin, "iov_strs", &sz); + assert(sz <= TTYMSG_IOV_MAX); + iov = calloc(sz, sizeof(*iov)); + if (iov == NULL) + err(EXIT_FAILURE, "calloc"); + for (size_t i = 0; i < sz; ++i) { + iov[i].iov_base = nvlstrs[i]; + iov[i].iov_len = strlen(nvlstrs[i]); + } + wallmsg(f, iov, sz); + + for (size_t i = 0; i < sz; ++i) + free(iov[i].iov_base); + free(iov); + return (0); +} |
