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> 42fd8e4ebcSMike Barcroft #include <arpa/inet.h> 43935a0024SGeoff Rehmet #include <rpc/rpc.h> 4440150947SPhilippe Charnier #include <rpc/pmap_clnt.h> 45935a0024SGeoff Rehmet #include <rpcsvc/rwall.h> 4640150947SPhilippe Charnier #include <sys/socket.h> 4740150947SPhilippe Charnier #include <sys/types.h> 4840150947SPhilippe Charnier #include <sys/wait.h> 4940150947SPhilippe Charnier #include <unistd.h> 50935a0024SGeoff Rehmet 51935a0024SGeoff Rehmet #ifdef OSF 52935a0024SGeoff Rehmet #define WALL_CMD "/usr/sbin/wall" 53935a0024SGeoff Rehmet #else 54935a0024SGeoff Rehmet #define WALL_CMD "/usr/bin/wall -n" 55935a0024SGeoff Rehmet #endif 56935a0024SGeoff Rehmet 57a174e5b1SWarner Losh void wallprog_1(struct svc_req *rqstp, SVCXPRT *transp); 58a174e5b1SWarner Losh void possess(void); 59a174e5b1SWarner Losh void killkids(int sig); 60a174e5b1SWarner Losh static void usage(void); 61935a0024SGeoff Rehmet 62935a0024SGeoff Rehmet int nodaemon = 0; 63935a0024SGeoff Rehmet int from_inetd = 1; 64935a0024SGeoff Rehmet 6540150947SPhilippe Charnier int 66a174e5b1SWarner Losh main(int argc, char *argv[]) 67935a0024SGeoff Rehmet { 68935a0024SGeoff Rehmet SVCXPRT *transp; 69935a0024SGeoff Rehmet int s, salen; 70935a0024SGeoff Rehmet struct sockaddr_in sa; 71935a0024SGeoff Rehmet int sock = 0; 72935a0024SGeoff Rehmet int proto = 0; 73935a0024SGeoff Rehmet 74935a0024SGeoff Rehmet if (argc == 2 && !strcmp(argv[1], "-n")) 75935a0024SGeoff Rehmet nodaemon = 1; 7640150947SPhilippe Charnier if (argc != 1 && !nodaemon) 7740150947SPhilippe Charnier usage(); 78935a0024SGeoff Rehmet 79935a0024SGeoff Rehmet if (geteuid() == 0) { 80935a0024SGeoff Rehmet struct passwd *pep = getpwnam("nobody"); 81935a0024SGeoff Rehmet if (pep) 82935a0024SGeoff Rehmet setuid(pep->pw_uid); 83935a0024SGeoff Rehmet else 84935a0024SGeoff Rehmet setuid(getuid()); 85935a0024SGeoff Rehmet } 86935a0024SGeoff Rehmet 87935a0024SGeoff Rehmet /* 88935a0024SGeoff Rehmet * See if inetd started us 89935a0024SGeoff Rehmet */ 907c760cfdSAndreas Schulz salen = sizeof(sa); 91935a0024SGeoff Rehmet if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) { 92935a0024SGeoff Rehmet from_inetd = 0; 93935a0024SGeoff Rehmet sock = RPC_ANYSOCK; 94935a0024SGeoff Rehmet proto = IPPROTO_UDP; 95935a0024SGeoff Rehmet } 96935a0024SGeoff Rehmet 97935a0024SGeoff Rehmet if (!from_inetd) { 98935a0024SGeoff Rehmet if (!nodaemon) 99935a0024SGeoff Rehmet possess(); 100935a0024SGeoff Rehmet 101935a0024SGeoff Rehmet (void)pmap_unset(WALLPROG, WALLVERS); 10240150947SPhilippe Charnier if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 10340150947SPhilippe Charnier err(1, "socket"); 104f249dbccSDag-Erling Smørgrav bzero(&sa, sizeof sa); 10540150947SPhilippe Charnier if (bind(s, (struct sockaddr *)&sa, sizeof sa) < 0) 10640150947SPhilippe Charnier err(1, "bind"); 107935a0024SGeoff Rehmet 108935a0024SGeoff Rehmet salen = sizeof sa; 10940150947SPhilippe Charnier if (getsockname(s, (struct sockaddr *)&sa, &salen)) 11040150947SPhilippe Charnier err(1, "getsockname"); 111935a0024SGeoff Rehmet 112935a0024SGeoff Rehmet pmap_set(WALLPROG, WALLVERS, IPPROTO_UDP, ntohs(sa.sin_port)); 11340150947SPhilippe Charnier if (dup2(s, 0) < 0) 11440150947SPhilippe Charnier err(1, "dup2"); 115935a0024SGeoff Rehmet (void)pmap_unset(WALLPROG, WALLVERS); 116935a0024SGeoff Rehmet } 117935a0024SGeoff Rehmet 118935a0024SGeoff Rehmet (void)signal(SIGCHLD, killkids); 119935a0024SGeoff Rehmet 12040150947SPhilippe Charnier openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON); 12140150947SPhilippe Charnier 122935a0024SGeoff Rehmet transp = svcudp_create(sock); 123935a0024SGeoff Rehmet if (transp == NULL) { 12440150947SPhilippe Charnier syslog(LOG_ERR, "cannot create udp service"); 125935a0024SGeoff Rehmet exit(1); 126935a0024SGeoff Rehmet } 127935a0024SGeoff Rehmet if (!svc_register(transp, WALLPROG, WALLVERS, wallprog_1, proto)) { 12840150947SPhilippe Charnier syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", proto?"udp":"(inetd)"); 129935a0024SGeoff Rehmet exit(1); 130935a0024SGeoff Rehmet } 131935a0024SGeoff Rehmet svc_run(); 13240150947SPhilippe Charnier syslog(LOG_ERR, "svc_run returned"); 133935a0024SGeoff Rehmet exit(1); 13440150947SPhilippe Charnier } 135935a0024SGeoff Rehmet 13640150947SPhilippe Charnier static void 137a174e5b1SWarner Losh usage(void) 13840150947SPhilippe Charnier { 13940150947SPhilippe Charnier fprintf(stderr, "usage: rpc.rwalld [-n]\n"); 14040150947SPhilippe Charnier exit(1); 141935a0024SGeoff Rehmet } 142935a0024SGeoff Rehmet 143a174e5b1SWarner Losh void 144a174e5b1SWarner Losh possess(void) 145935a0024SGeoff Rehmet { 146935a0024SGeoff Rehmet daemon(0, 0); 147935a0024SGeoff Rehmet } 148935a0024SGeoff Rehmet 149a174e5b1SWarner Losh void 150a174e5b1SWarner Losh killkids(int sig) 151935a0024SGeoff Rehmet { 152935a0024SGeoff Rehmet while(wait4(-1, NULL, WNOHANG, NULL) > 0) 153935a0024SGeoff Rehmet ; 154935a0024SGeoff Rehmet } 155935a0024SGeoff Rehmet 156a174e5b1SWarner Losh void * 157a174e5b1SWarner Losh wallproc_wall_1_svc(wrapstring *s, struct svc_req *rqstp) 158935a0024SGeoff Rehmet { 159e4a0e42bSBill Paul static void *dummy = NULL; 160e4a0e42bSBill Paul 161935a0024SGeoff Rehmet /* fork, popen wall with special option, and send the message */ 162935a0024SGeoff Rehmet if (fork() == 0) { 163935a0024SGeoff Rehmet FILE *pfp; 164935a0024SGeoff Rehmet 165935a0024SGeoff Rehmet pfp = popen(WALL_CMD, "w"); 166935a0024SGeoff Rehmet if (pfp != NULL) { 167935a0024SGeoff Rehmet fprintf(pfp, "\007\007%s", *s); 168935a0024SGeoff Rehmet pclose(pfp); 169935a0024SGeoff Rehmet exit(0); 170935a0024SGeoff Rehmet } 171935a0024SGeoff Rehmet } 172e4a0e42bSBill Paul return(&dummy); 173935a0024SGeoff Rehmet } 174935a0024SGeoff Rehmet 175935a0024SGeoff Rehmet void 176a174e5b1SWarner Losh wallprog_1(struct svc_req *rqstp, SVCXPRT *transp) 177935a0024SGeoff Rehmet { 178935a0024SGeoff Rehmet union { 179935a0024SGeoff Rehmet char *wallproc_wall_1_arg; 180935a0024SGeoff Rehmet } argument; 181935a0024SGeoff Rehmet char *result; 182935a0024SGeoff Rehmet bool_t (*xdr_argument)(), (*xdr_result)(); 183935a0024SGeoff Rehmet char *(*local)(); 184935a0024SGeoff Rehmet 185935a0024SGeoff Rehmet switch (rqstp->rq_proc) { 186935a0024SGeoff Rehmet case NULLPROC: 187f249dbccSDag-Erling Smørgrav (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 188935a0024SGeoff Rehmet goto leave; 189935a0024SGeoff Rehmet 190935a0024SGeoff Rehmet case WALLPROC_WALL: 191935a0024SGeoff Rehmet xdr_argument = xdr_wrapstring; 192935a0024SGeoff Rehmet xdr_result = xdr_void; 193e4a0e42bSBill Paul local = (char *(*)()) wallproc_wall_1_svc; 194935a0024SGeoff Rehmet break; 195935a0024SGeoff Rehmet 196935a0024SGeoff Rehmet default: 197935a0024SGeoff Rehmet svcerr_noproc(transp); 198935a0024SGeoff Rehmet goto leave; 199935a0024SGeoff Rehmet } 200f249dbccSDag-Erling Smørgrav bzero(&argument, sizeof(argument)); 201f249dbccSDag-Erling Smørgrav if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { 202935a0024SGeoff Rehmet svcerr_decode(transp); 203935a0024SGeoff Rehmet goto leave; 204935a0024SGeoff Rehmet } 205935a0024SGeoff Rehmet result = (*local)(&argument, rqstp); 206f249dbccSDag-Erling Smørgrav if (result != NULL && 207f249dbccSDag-Erling Smørgrav !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { 208935a0024SGeoff Rehmet svcerr_systemerr(transp); 209935a0024SGeoff Rehmet } 210f249dbccSDag-Erling Smørgrav if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) { 21140150947SPhilippe Charnier syslog(LOG_ERR, "unable to free arguments"); 212935a0024SGeoff Rehmet exit(1); 213935a0024SGeoff Rehmet } 214935a0024SGeoff Rehmet leave: 215935a0024SGeoff Rehmet if (from_inetd) 216935a0024SGeoff Rehmet exit(0); 217935a0024SGeoff Rehmet } 218