aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/syslogd/syslogd_cap_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/syslogd/syslogd_cap_log.c')
-rw-r--r--usr.sbin/syslogd/syslogd_cap_log.c211
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);
+}