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