1935a0024SGeoff Rehmet /* 2935a0024SGeoff Rehmet * Copyright (c) 1993 Christopher G. Demetriou 3935a0024SGeoff Rehmet * All rights reserved. 4935a0024SGeoff Rehmet * 5935a0024SGeoff Rehmet * Redistribution and use in source and binary forms, with or without 6935a0024SGeoff Rehmet * modification, are permitted provided that the following conditions 7935a0024SGeoff Rehmet * are met: 8935a0024SGeoff Rehmet * 1. Redistributions of source code must retain the above copyright 9935a0024SGeoff Rehmet * notice, this list of conditions and the following disclaimer. 10935a0024SGeoff Rehmet * 2. Redistributions in binary form must reproduce the above copyright 11935a0024SGeoff Rehmet * notice, this list of conditions and the following disclaimer in the 12935a0024SGeoff Rehmet * documentation and/or other materials provided with the distribution. 13935a0024SGeoff Rehmet * 3. The name of the author may not be used to endorse or promote 14935a0024SGeoff Rehmet * products derived from this software without specific prior written 15935a0024SGeoff Rehmet * permission. 16935a0024SGeoff Rehmet * 17935a0024SGeoff Rehmet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18935a0024SGeoff Rehmet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19935a0024SGeoff Rehmet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20935a0024SGeoff Rehmet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 21935a0024SGeoff Rehmet * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22935a0024SGeoff Rehmet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23935a0024SGeoff Rehmet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24935a0024SGeoff Rehmet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25935a0024SGeoff Rehmet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26935a0024SGeoff Rehmet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27935a0024SGeoff Rehmet * SUCH DAMAGE. 28935a0024SGeoff Rehmet */ 29935a0024SGeoff Rehmet 30935a0024SGeoff Rehmet #ifndef lint 3140150947SPhilippe Charnier static const char rcsid[] = 327f3dea24SPeter Wemm "$FreeBSD$"; 33935a0024SGeoff Rehmet #endif /* not lint */ 34935a0024SGeoff Rehmet 3540150947SPhilippe Charnier #include <err.h> 36935a0024SGeoff Rehmet #include <pwd.h> 37935a0024SGeoff Rehmet #include <signal.h> 3840150947SPhilippe Charnier #include <stdio.h> 3940150947SPhilippe Charnier #include <stdlib.h> 4040150947SPhilippe Charnier #include <string.h> 4140150947SPhilippe Charnier #include <syslog.h> 42935a0024SGeoff Rehmet #include <rpc/rpc.h> 4340150947SPhilippe Charnier #include <rpc/pmap_clnt.h> 44935a0024SGeoff Rehmet #include <rpcsvc/rwall.h> 4540150947SPhilippe Charnier #include <sys/socket.h> 4640150947SPhilippe Charnier #include <sys/types.h> 4740150947SPhilippe Charnier #include <sys/wait.h> 4840150947SPhilippe Charnier #include <unistd.h> 49935a0024SGeoff Rehmet 50935a0024SGeoff Rehmet #ifdef OSF 51935a0024SGeoff Rehmet #define WALL_CMD "/usr/sbin/wall" 52935a0024SGeoff Rehmet #else 53935a0024SGeoff Rehmet #define WALL_CMD "/usr/bin/wall -n" 54935a0024SGeoff Rehmet #endif 55935a0024SGeoff Rehmet 56a174e5b1SWarner Losh void wallprog_1(struct svc_req *rqstp, SVCXPRT *transp); 57a174e5b1SWarner Losh void possess(void); 58a174e5b1SWarner Losh void killkids(int sig); 59a174e5b1SWarner Losh static void usage(void); 60935a0024SGeoff Rehmet 61935a0024SGeoff Rehmet int nodaemon = 0; 62935a0024SGeoff Rehmet int from_inetd = 1; 63935a0024SGeoff Rehmet 6440150947SPhilippe Charnier int 65a174e5b1SWarner Losh main(int argc, char *argv[]) 66935a0024SGeoff Rehmet { 67935a0024SGeoff Rehmet SVCXPRT *transp; 68935a0024SGeoff Rehmet int s, salen; 69935a0024SGeoff Rehmet struct sockaddr_in sa; 70935a0024SGeoff Rehmet int sock = 0; 71935a0024SGeoff Rehmet int proto = 0; 72935a0024SGeoff Rehmet 73935a0024SGeoff Rehmet if (argc == 2 && !strcmp(argv[1], "-n")) 74935a0024SGeoff Rehmet nodaemon = 1; 7540150947SPhilippe Charnier if (argc != 1 && !nodaemon) 7640150947SPhilippe Charnier usage(); 77935a0024SGeoff Rehmet 78935a0024SGeoff Rehmet if (geteuid() == 0) { 79935a0024SGeoff Rehmet struct passwd *pep = getpwnam("nobody"); 80935a0024SGeoff Rehmet if (pep) 81935a0024SGeoff Rehmet setuid(pep->pw_uid); 82935a0024SGeoff Rehmet else 83935a0024SGeoff Rehmet setuid(getuid()); 84935a0024SGeoff Rehmet } 85935a0024SGeoff Rehmet 86935a0024SGeoff Rehmet /* 87935a0024SGeoff Rehmet * See if inetd started us 88935a0024SGeoff Rehmet */ 897c760cfdSAndreas Schulz salen = sizeof(sa); 90935a0024SGeoff Rehmet if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) { 91935a0024SGeoff Rehmet from_inetd = 0; 92935a0024SGeoff Rehmet sock = RPC_ANYSOCK; 93935a0024SGeoff Rehmet proto = IPPROTO_UDP; 94935a0024SGeoff Rehmet } 95935a0024SGeoff Rehmet 96935a0024SGeoff Rehmet if (!from_inetd) { 97935a0024SGeoff Rehmet if (!nodaemon) 98935a0024SGeoff Rehmet possess(); 99935a0024SGeoff Rehmet 100935a0024SGeoff Rehmet (void)pmap_unset(WALLPROG, WALLVERS); 10140150947SPhilippe Charnier if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 10240150947SPhilippe Charnier err(1, "socket"); 103935a0024SGeoff Rehmet bzero((char *)&sa, sizeof sa); 10440150947SPhilippe Charnier if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) 10540150947SPhilippe Charnier err(1, "bind"); 106935a0024SGeoff Rehmet 107935a0024SGeoff Rehmet salen = sizeof sa; 10840150947SPhilippe Charnier if (getsockname(s, (struct sockaddr *)&sa, &salen)) 10940150947SPhilippe Charnier err(1, "getsockname"); 110935a0024SGeoff Rehmet 111935a0024SGeoff Rehmet pmap_set(WALLPROG, WALLVERS, IPPROTO_UDP, ntohs(sa.sin_port)); 11240150947SPhilippe Charnier if (dup2(s, 0) < 0) 11340150947SPhilippe Charnier err(1, "dup2"); 114935a0024SGeoff Rehmet (void)pmap_unset(WALLPROG, WALLVERS); 115935a0024SGeoff Rehmet } 116935a0024SGeoff Rehmet 117935a0024SGeoff Rehmet (void)signal(SIGCHLD, killkids); 118935a0024SGeoff Rehmet 11940150947SPhilippe Charnier openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON); 12040150947SPhilippe Charnier 121935a0024SGeoff Rehmet transp = svcudp_create(sock); 122935a0024SGeoff Rehmet if (transp == NULL) { 12340150947SPhilippe Charnier syslog(LOG_ERR, "cannot create udp service"); 124935a0024SGeoff Rehmet exit(1); 125935a0024SGeoff Rehmet } 126935a0024SGeoff Rehmet if (!svc_register(transp, WALLPROG, WALLVERS, wallprog_1, proto)) { 12740150947SPhilippe Charnier syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", proto?"udp":"(inetd)"); 128935a0024SGeoff Rehmet exit(1); 129935a0024SGeoff Rehmet } 130935a0024SGeoff Rehmet svc_run(); 13140150947SPhilippe Charnier syslog(LOG_ERR, "svc_run returned"); 132935a0024SGeoff Rehmet exit(1); 13340150947SPhilippe Charnier } 134935a0024SGeoff Rehmet 13540150947SPhilippe Charnier static void 136a174e5b1SWarner Losh usage(void) 13740150947SPhilippe Charnier { 13840150947SPhilippe Charnier fprintf(stderr, "usage: rpc.rwalld [-n]\n"); 13940150947SPhilippe Charnier exit(1); 140935a0024SGeoff Rehmet } 141935a0024SGeoff Rehmet 142a174e5b1SWarner Losh void 143a174e5b1SWarner Losh possess(void) 144935a0024SGeoff Rehmet { 145935a0024SGeoff Rehmet daemon(0, 0); 146935a0024SGeoff Rehmet } 147935a0024SGeoff Rehmet 148a174e5b1SWarner Losh void 149a174e5b1SWarner Losh killkids(int sig) 150935a0024SGeoff Rehmet { 151935a0024SGeoff Rehmet while(wait4(-1, NULL, WNOHANG, NULL) > 0) 152935a0024SGeoff Rehmet ; 153935a0024SGeoff Rehmet } 154935a0024SGeoff Rehmet 155a174e5b1SWarner Losh void * 156a174e5b1SWarner Losh wallproc_wall_1_svc(wrapstring *s, struct svc_req *rqstp) 157935a0024SGeoff Rehmet { 158e4a0e42bSBill Paul static void *dummy = NULL; 159e4a0e42bSBill Paul 160935a0024SGeoff Rehmet /* fork, popen wall with special option, and send the message */ 161935a0024SGeoff Rehmet if (fork() == 0) { 162935a0024SGeoff Rehmet FILE *pfp; 163935a0024SGeoff Rehmet 164935a0024SGeoff Rehmet pfp = popen(WALL_CMD, "w"); 165935a0024SGeoff Rehmet if (pfp != NULL) { 166935a0024SGeoff Rehmet fprintf(pfp, "\007\007%s", *s); 167935a0024SGeoff Rehmet pclose(pfp); 168935a0024SGeoff Rehmet exit(0); 169935a0024SGeoff Rehmet } 170935a0024SGeoff Rehmet } 171e4a0e42bSBill Paul return(&dummy); 172935a0024SGeoff Rehmet } 173935a0024SGeoff Rehmet 174935a0024SGeoff Rehmet void 175a174e5b1SWarner Losh wallprog_1(struct svc_req *rqstp, SVCXPRT *transp) 176935a0024SGeoff Rehmet { 177935a0024SGeoff Rehmet union { 178935a0024SGeoff Rehmet char *wallproc_wall_1_arg; 179935a0024SGeoff Rehmet } argument; 180935a0024SGeoff Rehmet char *result; 181935a0024SGeoff Rehmet bool_t (*xdr_argument)(), (*xdr_result)(); 182935a0024SGeoff Rehmet char *(*local)(); 183935a0024SGeoff Rehmet 184935a0024SGeoff Rehmet switch (rqstp->rq_proc) { 185935a0024SGeoff Rehmet case NULLPROC: 186935a0024SGeoff Rehmet (void)svc_sendreply(transp, xdr_void, (char *)NULL); 187935a0024SGeoff Rehmet goto leave; 188935a0024SGeoff Rehmet 189935a0024SGeoff Rehmet case WALLPROC_WALL: 190935a0024SGeoff Rehmet xdr_argument = xdr_wrapstring; 191935a0024SGeoff Rehmet xdr_result = xdr_void; 192e4a0e42bSBill Paul local = (char *(*)()) wallproc_wall_1_svc; 193935a0024SGeoff Rehmet break; 194935a0024SGeoff Rehmet 195935a0024SGeoff Rehmet default: 196935a0024SGeoff Rehmet svcerr_noproc(transp); 197935a0024SGeoff Rehmet goto leave; 198935a0024SGeoff Rehmet } 199935a0024SGeoff Rehmet bzero((char *)&argument, sizeof(argument)); 200e4a0e42bSBill Paul if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { 201935a0024SGeoff Rehmet svcerr_decode(transp); 202935a0024SGeoff Rehmet goto leave; 203935a0024SGeoff Rehmet } 204935a0024SGeoff Rehmet result = (*local)(&argument, rqstp); 205935a0024SGeoff Rehmet if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 206935a0024SGeoff Rehmet svcerr_systemerr(transp); 207935a0024SGeoff Rehmet } 208e4a0e42bSBill Paul if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { 20940150947SPhilippe Charnier syslog(LOG_ERR, "unable to free arguments"); 210935a0024SGeoff Rehmet exit(1); 211935a0024SGeoff Rehmet } 212935a0024SGeoff Rehmet leave: 213935a0024SGeoff Rehmet if (from_inetd) 214935a0024SGeoff Rehmet exit(0); 215935a0024SGeoff Rehmet } 216