xref: /freebsd-src/usr.sbin/syslogd/syslogd_cap_log.c (revision 61a29eca550b80d179934a7198c41ad4d255f81c)
1*61a29ecaSJake Freeland /*-
2*61a29ecaSJake Freeland  * SPDX-License-Identifier: BSD-2-Clause
3*61a29ecaSJake Freeland  *
4*61a29ecaSJake Freeland  * Copyright (c) 2023 The FreeBSD Foundation
5*61a29ecaSJake Freeland  *
6*61a29ecaSJake Freeland  * This software was developed by Jake Freeland <jfree@FreeBSD.org>
7*61a29ecaSJake Freeland  * under sponsorship from the FreeBSD Foundation.
8*61a29ecaSJake Freeland  *
9*61a29ecaSJake Freeland  * Redistribution and use in source and binary forms, with or without
10*61a29ecaSJake Freeland  * modification, are permitted provided that the following conditions
11*61a29ecaSJake Freeland  * are met:
12*61a29ecaSJake Freeland  * 1. Redistributions of source code must retain the above copyright
13*61a29ecaSJake Freeland  *    notice, this list of conditions and the following disclaimer.
14*61a29ecaSJake Freeland  * 2. Redistributions in binary form must reproduce the above copyright
15*61a29ecaSJake Freeland  *    notice, this list of conditions and the following disclaimer in the
16*61a29ecaSJake Freeland  *    documentation and/or other materials provided with the distribution.
17*61a29ecaSJake Freeland  *
18*61a29ecaSJake Freeland  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*61a29ecaSJake Freeland  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*61a29ecaSJake Freeland  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*61a29ecaSJake Freeland  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*61a29ecaSJake Freeland  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*61a29ecaSJake Freeland  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*61a29ecaSJake Freeland  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*61a29ecaSJake Freeland  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*61a29ecaSJake Freeland  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*61a29ecaSJake Freeland  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*61a29ecaSJake Freeland  * SUCH DAMAGE.
29*61a29ecaSJake Freeland  */
30*61a29ecaSJake Freeland 
31*61a29ecaSJake Freeland #include <assert.h>
32*61a29ecaSJake Freeland #include <err.h>
33*61a29ecaSJake Freeland #include <string.h>
34*61a29ecaSJake Freeland 
35*61a29ecaSJake Freeland #include "syslogd_cap.h"
36*61a29ecaSJake Freeland 
37*61a29ecaSJake Freeland struct cfiled_list cfiled_head;
38*61a29ecaSJake Freeland 
39*61a29ecaSJake Freeland int
40*61a29ecaSJake Freeland cap_p_open(cap_channel_t *chan, size_t filed_idx, const char *prog,
41*61a29ecaSJake Freeland     int *procdesc)
42*61a29ecaSJake Freeland {
43*61a29ecaSJake Freeland 	nvlist_t *nvl = nvlist_create(0);
44*61a29ecaSJake Freeland 	int error, pipedesc_w;
45*61a29ecaSJake Freeland 
46*61a29ecaSJake Freeland 	nvlist_add_string(nvl, "cmd", "p_open");
47*61a29ecaSJake Freeland 	nvlist_add_number(nvl, "filed_idx", filed_idx);
48*61a29ecaSJake Freeland 	nvlist_add_string(nvl, "prog", prog);
49*61a29ecaSJake Freeland 	nvl = cap_xfer_nvlist(chan, nvl);
50*61a29ecaSJake Freeland 	if (nvl == NULL) {
51*61a29ecaSJake Freeland 		logerror("Failed to xfer p_open nvlist");
52*61a29ecaSJake Freeland 		exit(1);
53*61a29ecaSJake Freeland 	}
54*61a29ecaSJake Freeland 	error = nvlist_get_number(nvl, "error");
55*61a29ecaSJake Freeland 	if (error != 0) {
56*61a29ecaSJake Freeland 		errno = error;
57*61a29ecaSJake Freeland 		logerror("Failed to open piped command");
58*61a29ecaSJake Freeland 	}
59*61a29ecaSJake Freeland 	pipedesc_w = dnvlist_take_descriptor(nvl, "pipedesc_w", -1);
60*61a29ecaSJake Freeland 	*procdesc = dnvlist_take_descriptor(nvl, "procdesc", -1);
61*61a29ecaSJake Freeland 
62*61a29ecaSJake Freeland 	nvlist_destroy(nvl);
63*61a29ecaSJake Freeland 	return (pipedesc_w);
64*61a29ecaSJake Freeland }
65*61a29ecaSJake Freeland 
66*61a29ecaSJake Freeland int
67*61a29ecaSJake Freeland casper_p_open(nvlist_t *nvlin, nvlist_t *nvlout)
68*61a29ecaSJake Freeland {
69*61a29ecaSJake Freeland 	struct cap_filed *cfiled;
70*61a29ecaSJake Freeland 	size_t filed_idx;
71*61a29ecaSJake Freeland 	int pipedesc_w, procdesc = -1;
72*61a29ecaSJake Freeland 	const char *prog;
73*61a29ecaSJake Freeland 
74*61a29ecaSJake Freeland 	filed_idx = nvlist_get_number(nvlin, "filed_idx");
75*61a29ecaSJake Freeland 	prog = nvlist_get_string(nvlin, "prog");
76*61a29ecaSJake Freeland 	SLIST_FOREACH(cfiled, &cfiled_head, next) {
77*61a29ecaSJake Freeland 		if (cfiled->idx != filed_idx)
78*61a29ecaSJake Freeland 			continue;
79*61a29ecaSJake Freeland 		if (strcmp(cfiled->pipe_cmd, prog) != 0)
80*61a29ecaSJake Freeland 			return (-1);
81*61a29ecaSJake Freeland 
82*61a29ecaSJake Freeland 		pipedesc_w = p_open(prog, &procdesc);
83*61a29ecaSJake Freeland 		if (pipedesc_w == -1)
84*61a29ecaSJake Freeland 			return (-1);
85*61a29ecaSJake Freeland 		nvlist_move_descriptor(nvlout, "pipedesc_w", pipedesc_w);
86*61a29ecaSJake Freeland 		nvlist_move_descriptor(nvlout, "procdesc", procdesc);
87*61a29ecaSJake Freeland 		return (0);
88*61a29ecaSJake Freeland 	}
89*61a29ecaSJake Freeland 
90*61a29ecaSJake Freeland 	return (-1);
91*61a29ecaSJake Freeland }
92*61a29ecaSJake Freeland 
93*61a29ecaSJake Freeland const char *
94*61a29ecaSJake Freeland cap_ttymsg(cap_channel_t *chan, struct iovec *iov, int iovcnt,
95*61a29ecaSJake Freeland     const char *line, int tmout)
96*61a29ecaSJake Freeland {
97*61a29ecaSJake Freeland 	nvlist_t *nvl = nvlist_create(0);
98*61a29ecaSJake Freeland 	int error;
99*61a29ecaSJake Freeland 	static char errbuf[1024];
100*61a29ecaSJake Freeland 	char *ret = NULL;
101*61a29ecaSJake Freeland 
102*61a29ecaSJake Freeland 	nvlist_add_string(nvl, "cmd", "ttymsg");
103*61a29ecaSJake Freeland 	for (int i = 0; i < iovcnt; ++i)
104*61a29ecaSJake Freeland 		nvlist_append_string_array(nvl, "iov_strs", iov[i].iov_base);
105*61a29ecaSJake Freeland 	nvlist_add_string(nvl, "line", line);
106*61a29ecaSJake Freeland 	nvlist_add_number(nvl, "tmout", tmout);
107*61a29ecaSJake Freeland 
108*61a29ecaSJake Freeland 	nvl = cap_xfer_nvlist(chan, nvl);
109*61a29ecaSJake Freeland 	if (nvl == NULL) {
110*61a29ecaSJake Freeland 		logerror("Failed to xfer ttymsg nvlist");
111*61a29ecaSJake Freeland 		exit(1);
112*61a29ecaSJake Freeland 	}
113*61a29ecaSJake Freeland 	error = nvlist_get_number(nvl, "error");
114*61a29ecaSJake Freeland 	if (error != 0) {
115*61a29ecaSJake Freeland 		errno = error;
116*61a29ecaSJake Freeland 		logerror("Failed to ttymsg");
117*61a29ecaSJake Freeland 	}
118*61a29ecaSJake Freeland 	if (nvlist_exists_string(nvl, "errstr")) {
119*61a29ecaSJake Freeland 		const char *errstr = nvlist_get_string(nvl, "errstr");
120*61a29ecaSJake Freeland 		(void)strlcpy(errbuf, errstr, sizeof(errbuf));
121*61a29ecaSJake Freeland 		ret = errbuf;
122*61a29ecaSJake Freeland 	}
123*61a29ecaSJake Freeland 
124*61a29ecaSJake Freeland 	nvlist_destroy(nvl);
125*61a29ecaSJake Freeland 	return (ret);
126*61a29ecaSJake Freeland }
127*61a29ecaSJake Freeland 
128*61a29ecaSJake Freeland int
129*61a29ecaSJake Freeland casper_ttymsg(nvlist_t *nvlin, nvlist_t *nvlout)
130*61a29ecaSJake Freeland {
131*61a29ecaSJake Freeland 	char **nvlstrs;
132*61a29ecaSJake Freeland 	struct iovec *iov;
133*61a29ecaSJake Freeland 	size_t iovcnt;
134*61a29ecaSJake Freeland 	int tmout;
135*61a29ecaSJake Freeland 	const char *line;
136*61a29ecaSJake Freeland 
137*61a29ecaSJake Freeland 	nvlstrs = nvlist_take_string_array(nvlin, "iov_strs", &iovcnt);
138*61a29ecaSJake Freeland 	assert(iovcnt <= TTYMSG_IOV_MAX);
139*61a29ecaSJake Freeland 	iov = calloc(iovcnt, sizeof(*iov));
140*61a29ecaSJake Freeland 	if (iov == NULL)
141*61a29ecaSJake Freeland 		err(EXIT_FAILURE, "calloc");
142*61a29ecaSJake Freeland 	for (size_t i = 0; i < iovcnt; ++i) {
143*61a29ecaSJake Freeland 		iov[i].iov_base = nvlstrs[i];
144*61a29ecaSJake Freeland 		iov[i].iov_len = strlen(nvlstrs[i]);
145*61a29ecaSJake Freeland 	}
146*61a29ecaSJake Freeland 	line = nvlist_get_string(nvlin, "line");
147*61a29ecaSJake Freeland 	tmout = nvlist_get_number(nvlin, "tmout");
148*61a29ecaSJake Freeland 	line = ttymsg(iov, iovcnt, line, tmout);
149*61a29ecaSJake Freeland 	if (line != NULL)
150*61a29ecaSJake Freeland 		nvlist_add_string(nvlout, "errstr", line);
151*61a29ecaSJake Freeland 
152*61a29ecaSJake Freeland 	free(iov);
153*61a29ecaSJake Freeland 	return (0);
154*61a29ecaSJake Freeland }
155*61a29ecaSJake Freeland 
156*61a29ecaSJake Freeland void
157*61a29ecaSJake Freeland cap_wallmsg(cap_channel_t *chan, const struct filed *f, struct iovec *iov,
158*61a29ecaSJake Freeland     int iovcnt)
159*61a29ecaSJake Freeland {
160*61a29ecaSJake Freeland 	nvlist_t *nvl = nvlist_create(0);
161*61a29ecaSJake Freeland 	int error;
162*61a29ecaSJake Freeland 
163*61a29ecaSJake Freeland 	nvlist_add_string(nvl, "cmd", "wallmsg");
164*61a29ecaSJake Freeland 	/*
165*61a29ecaSJake Freeland 	 * The filed_to_nvlist() function is not needed
166*61a29ecaSJake Freeland 	 * here because wallmsg() only uses f_type and
167*61a29ecaSJake Freeland 	 * fu_uname members, which are both inline.
168*61a29ecaSJake Freeland 	 */
169*61a29ecaSJake Freeland 	nvlist_add_binary(nvl, "filed", f, sizeof(*f));
170*61a29ecaSJake Freeland 	for (int i = 0; i < iovcnt; ++i)
171*61a29ecaSJake Freeland 		nvlist_append_string_array(nvl, "iov_strs", iov[i].iov_base);
172*61a29ecaSJake Freeland 
173*61a29ecaSJake Freeland 	nvl = cap_xfer_nvlist(chan, nvl);
174*61a29ecaSJake Freeland 	if (nvl == NULL) {
175*61a29ecaSJake Freeland 		logerror("Failed to xfer wallmsg nvlist");
176*61a29ecaSJake Freeland 		exit(1);
177*61a29ecaSJake Freeland 	}
178*61a29ecaSJake Freeland 	error = nvlist_get_number(nvl, "error");
179*61a29ecaSJake Freeland 	if (error != 0) {
180*61a29ecaSJake Freeland 		errno = error;
181*61a29ecaSJake Freeland 		logerror("Failed to wallmsg");
182*61a29ecaSJake Freeland 	}
183*61a29ecaSJake Freeland 	nvlist_destroy(nvl);
184*61a29ecaSJake Freeland }
185*61a29ecaSJake Freeland 
186*61a29ecaSJake Freeland int
187*61a29ecaSJake Freeland casper_wallmsg(nvlist_t *nvlin)
188*61a29ecaSJake Freeland {
189*61a29ecaSJake Freeland 	const struct filed *f;
190*61a29ecaSJake Freeland 	char **nvlstrs;
191*61a29ecaSJake Freeland 	struct iovec *iov;
192*61a29ecaSJake Freeland 	size_t sz;
193*61a29ecaSJake Freeland 
194*61a29ecaSJake Freeland 	f = nvlist_get_binary(nvlin, "filed", &sz);
195*61a29ecaSJake Freeland 	assert(sz == sizeof(*f));
196*61a29ecaSJake Freeland 	nvlstrs = nvlist_take_string_array(nvlin, "iov_strs", &sz);
197*61a29ecaSJake Freeland 	assert(sz <= TTYMSG_IOV_MAX);
198*61a29ecaSJake Freeland 	iov = calloc(sz, sizeof(*iov));
199*61a29ecaSJake Freeland 	if (iov == NULL)
200*61a29ecaSJake Freeland 		err(EXIT_FAILURE, "calloc");
201*61a29ecaSJake Freeland 	for (size_t i = 0; i < sz; ++i) {
202*61a29ecaSJake Freeland 		iov[i].iov_base = nvlstrs[i];
203*61a29ecaSJake Freeland 		iov[i].iov_len = strlen(nvlstrs[i]);
204*61a29ecaSJake Freeland 	}
205*61a29ecaSJake Freeland 	wallmsg(f, iov, sz);
206*61a29ecaSJake Freeland 
207*61a29ecaSJake Freeland 	for (size_t i = 0; i < sz; ++i)
208*61a29ecaSJake Freeland 		free(iov[i].iov_base);
209*61a29ecaSJake Freeland 	free(iov);
210*61a29ecaSJake Freeland 	return (0);
211*61a29ecaSJake Freeland }
212