xref: /freebsd/libexec/rpc.rwalld/rwalld.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
1e6209940SPedro F. Giffuni /*-
2e6209940SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3e6209940SPedro F. Giffuni  *
4935a0024SGeoff Rehmet  * Copyright (c) 1993 Christopher G. Demetriou
5935a0024SGeoff Rehmet  * All rights reserved.
6935a0024SGeoff Rehmet  *
7935a0024SGeoff Rehmet  * Redistribution and use in source and binary forms, with or without
8935a0024SGeoff Rehmet  * modification, are permitted provided that the following conditions
9935a0024SGeoff Rehmet  * are met:
10935a0024SGeoff Rehmet  * 1. Redistributions of source code must retain the above copyright
11935a0024SGeoff Rehmet  *    notice, this list of conditions and the following disclaimer.
12935a0024SGeoff Rehmet  * 2. Redistributions in binary form must reproduce the above copyright
13935a0024SGeoff Rehmet  *    notice, this list of conditions and the following disclaimer in the
14935a0024SGeoff Rehmet  *    documentation and/or other materials provided with the distribution.
15935a0024SGeoff Rehmet  * 3. The name of the author may not be used to endorse or promote
16935a0024SGeoff Rehmet  *    products derived from this software without specific prior written
17935a0024SGeoff Rehmet  *    permission.
18935a0024SGeoff Rehmet  *
19935a0024SGeoff Rehmet  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20935a0024SGeoff Rehmet  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21935a0024SGeoff Rehmet  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22935a0024SGeoff Rehmet  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23935a0024SGeoff Rehmet  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24935a0024SGeoff Rehmet  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25935a0024SGeoff Rehmet  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26935a0024SGeoff Rehmet  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27935a0024SGeoff Rehmet  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28935a0024SGeoff Rehmet  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29935a0024SGeoff Rehmet  * SUCH DAMAGE.
30935a0024SGeoff Rehmet  */
31935a0024SGeoff Rehmet 
32f0c80f9bSPhilippe Charnier #include <sys/cdefs.h>
3340150947SPhilippe Charnier #include <err.h>
34935a0024SGeoff Rehmet #include <pwd.h>
35935a0024SGeoff Rehmet #include <signal.h>
3640150947SPhilippe Charnier #include <stdio.h>
3740150947SPhilippe Charnier #include <stdlib.h>
3840150947SPhilippe Charnier #include <string.h>
3940150947SPhilippe Charnier #include <syslog.h>
40fd8e4ebcSMike Barcroft #include <arpa/inet.h>
41935a0024SGeoff Rehmet #include <rpc/rpc.h>
42935a0024SGeoff Rehmet #include <rpcsvc/rwall.h>
4340150947SPhilippe Charnier #include <sys/socket.h>
4440150947SPhilippe Charnier #include <sys/types.h>
4540150947SPhilippe Charnier #include <sys/wait.h>
4640150947SPhilippe Charnier #include <unistd.h>
47935a0024SGeoff Rehmet 
48935a0024SGeoff Rehmet #ifdef OSF
49935a0024SGeoff Rehmet #define WALL_CMD "/usr/sbin/wall"
50935a0024SGeoff Rehmet #else
51935a0024SGeoff Rehmet #define WALL_CMD "/usr/bin/wall -n"
52935a0024SGeoff Rehmet #endif
53935a0024SGeoff Rehmet 
54a174e5b1SWarner Losh void wallprog_1(struct svc_req *rqstp, SVCXPRT *transp);
55a174e5b1SWarner Losh void possess(void);
56a174e5b1SWarner Losh void killkids(int sig);
57*69c0fb2aSAlfonso Gregory static void usage(void) __dead2;
58935a0024SGeoff Rehmet 
59935a0024SGeoff Rehmet int nodaemon = 0;
60935a0024SGeoff Rehmet int from_inetd = 1;
61935a0024SGeoff Rehmet 
6240150947SPhilippe Charnier int
main(int argc,char * argv[])63a174e5b1SWarner Losh main(int argc, char *argv[])
64935a0024SGeoff Rehmet {
65935a0024SGeoff Rehmet 	SVCXPRT *transp;
6678e3eed0SStefan Farfeleder 	socklen_t salen;
6778e3eed0SStefan Farfeleder 	int ok;
68af37179bSAlfred Perlstein 	struct sockaddr_storage sa;
69935a0024SGeoff Rehmet 
70935a0024SGeoff Rehmet 	if (argc == 2 && !strcmp(argv[1], "-n"))
71935a0024SGeoff Rehmet 		nodaemon = 1;
7240150947SPhilippe Charnier 	if (argc != 1 && !nodaemon)
7340150947SPhilippe Charnier 		usage();
74935a0024SGeoff Rehmet 
75935a0024SGeoff Rehmet 	if (geteuid() == 0) {
76935a0024SGeoff Rehmet 		struct passwd *pep = getpwnam("nobody");
77935a0024SGeoff Rehmet 		if (pep)
78935a0024SGeoff Rehmet 			setuid(pep->pw_uid);
79935a0024SGeoff Rehmet 		else
80935a0024SGeoff Rehmet 			setuid(getuid());
81935a0024SGeoff Rehmet 	}
82935a0024SGeoff Rehmet 
83935a0024SGeoff Rehmet         /*
84935a0024SGeoff Rehmet          * See if inetd started us
85935a0024SGeoff Rehmet          */
867c760cfdSAndreas Schulz 	salen = sizeof(sa);
87935a0024SGeoff Rehmet         if (getsockname(0, (struct sockaddr *)&sa, &salen) < 0) {
88935a0024SGeoff Rehmet                 from_inetd = 0;
89935a0024SGeoff Rehmet         }
90935a0024SGeoff Rehmet 
91935a0024SGeoff Rehmet         if (!from_inetd) {
92935a0024SGeoff Rehmet                 if (!nodaemon)
93935a0024SGeoff Rehmet                         possess();
94935a0024SGeoff Rehmet 
95af37179bSAlfred Perlstein 		(void)rpcb_unset(WALLPROG, WALLVERS, NULL);
96935a0024SGeoff Rehmet         }
97935a0024SGeoff Rehmet 
98935a0024SGeoff Rehmet 	(void)signal(SIGCHLD, killkids);
99935a0024SGeoff Rehmet 
10040150947SPhilippe Charnier 	openlog("rpc.rwalld", LOG_CONS|LOG_PID, LOG_DAEMON);
10140150947SPhilippe Charnier 
102af37179bSAlfred Perlstein 	/* create and register the service */
103af37179bSAlfred Perlstein 	if (from_inetd) {
104af37179bSAlfred Perlstein 		transp = svc_tli_create(0, NULL, NULL, 0, 0);
105935a0024SGeoff Rehmet 		if (transp == NULL) {
106af37179bSAlfred Perlstein 			syslog(LOG_ERR, "couldn't create udp service.");
107935a0024SGeoff Rehmet 			exit(1);
108935a0024SGeoff Rehmet 		}
109af37179bSAlfred Perlstein 		ok = svc_reg(transp, WALLPROG, WALLVERS,
110af37179bSAlfred Perlstein 			     wallprog_1, NULL);
111af37179bSAlfred Perlstein 	} else
112af37179bSAlfred Perlstein 		ok = svc_create(wallprog_1,
113af37179bSAlfred Perlstein 				WALLPROG, WALLVERS, "udp");
114af37179bSAlfred Perlstein 	if (!ok) {
115af37179bSAlfred Perlstein 		syslog(LOG_ERR, "unable to register (WALLPROG, WALLVERS, %s)", (!from_inetd)?"udp":"(inetd)");
116935a0024SGeoff Rehmet 		exit(1);
117935a0024SGeoff Rehmet 	}
118935a0024SGeoff Rehmet 	svc_run();
11940150947SPhilippe Charnier 	syslog(LOG_ERR, "svc_run returned");
120935a0024SGeoff Rehmet 	exit(1);
12140150947SPhilippe Charnier }
122935a0024SGeoff Rehmet 
12340150947SPhilippe Charnier static void
usage(void)124a174e5b1SWarner Losh usage(void)
12540150947SPhilippe Charnier {
12640150947SPhilippe Charnier 	fprintf(stderr, "usage: rpc.rwalld [-n]\n");
12740150947SPhilippe Charnier 	exit(1);
128935a0024SGeoff Rehmet }
129935a0024SGeoff Rehmet 
130a174e5b1SWarner Losh void
possess(void)131a174e5b1SWarner Losh possess(void)
132935a0024SGeoff Rehmet {
133935a0024SGeoff Rehmet 	daemon(0, 0);
134935a0024SGeoff Rehmet }
135935a0024SGeoff Rehmet 
136a174e5b1SWarner Losh void
killkids(int sig __unused)137f0c80f9bSPhilippe Charnier killkids(int sig __unused)
138935a0024SGeoff Rehmet {
139935a0024SGeoff Rehmet 	while(wait4(-1, NULL, WNOHANG, NULL) > 0)
140935a0024SGeoff Rehmet 		;
141935a0024SGeoff Rehmet }
142935a0024SGeoff Rehmet 
143a174e5b1SWarner Losh void *
wallproc_wall_1_svc(wrapstring * s,struct svc_req * rqstp __unused)144f0c80f9bSPhilippe Charnier wallproc_wall_1_svc(wrapstring *s, struct svc_req *rqstp __unused)
145935a0024SGeoff Rehmet {
146e4a0e42bSBill Paul 	static void		*dummy = NULL;
147e4a0e42bSBill Paul 
148935a0024SGeoff Rehmet 	/* fork, popen wall with special option, and send the message */
149935a0024SGeoff Rehmet 	if (fork() == 0) {
150935a0024SGeoff Rehmet 		FILE *pfp;
151935a0024SGeoff Rehmet 
152935a0024SGeoff Rehmet 		pfp = popen(WALL_CMD, "w");
153935a0024SGeoff Rehmet 		if (pfp != NULL) {
154935a0024SGeoff Rehmet 			fprintf(pfp, "\007\007%s", *s);
155935a0024SGeoff Rehmet 			pclose(pfp);
156935a0024SGeoff Rehmet 			exit(0);
157935a0024SGeoff Rehmet 		}
158935a0024SGeoff Rehmet 	}
159e4a0e42bSBill Paul 	return(&dummy);
160935a0024SGeoff Rehmet }
161935a0024SGeoff Rehmet 
162935a0024SGeoff Rehmet void
wallprog_1(struct svc_req * rqstp,SVCXPRT * transp)163a174e5b1SWarner Losh wallprog_1(struct svc_req *rqstp, SVCXPRT *transp)
164935a0024SGeoff Rehmet {
165935a0024SGeoff Rehmet 	union {
166935a0024SGeoff Rehmet 		char *wallproc_wall_1_arg;
167935a0024SGeoff Rehmet 	} argument;
168e4253ae8SJohn Baldwin 	void *result;
169e4253ae8SJohn Baldwin 	xdrproc_t xdr_argument, xdr_result;
170e4253ae8SJohn Baldwin 	typedef void *(svc_cb)(void *arg, struct svc_req *rqstp);
171e4253ae8SJohn Baldwin 	svc_cb *local;
172935a0024SGeoff Rehmet 
173935a0024SGeoff Rehmet 	switch (rqstp->rq_proc) {
174935a0024SGeoff Rehmet 	case NULLPROC:
175f249dbccSDag-Erling Smørgrav 		(void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
176935a0024SGeoff Rehmet 		goto leave;
177935a0024SGeoff Rehmet 
178935a0024SGeoff Rehmet 	case WALLPROC_WALL:
179e4253ae8SJohn Baldwin 		xdr_argument = (xdrproc_t)xdr_wrapstring;
180e4253ae8SJohn Baldwin 		xdr_result = (xdrproc_t)xdr_void;
181e4253ae8SJohn Baldwin 		local = (svc_cb *)wallproc_wall_1_svc;
182935a0024SGeoff Rehmet 		break;
183935a0024SGeoff Rehmet 
184935a0024SGeoff Rehmet 	default:
185935a0024SGeoff Rehmet 		svcerr_noproc(transp);
186935a0024SGeoff Rehmet 		goto leave;
187935a0024SGeoff Rehmet 	}
188f249dbccSDag-Erling Smørgrav 	bzero(&argument, sizeof(argument));
189e4253ae8SJohn Baldwin 	if (!svc_getargs(transp, xdr_argument, &argument)) {
190935a0024SGeoff Rehmet 		svcerr_decode(transp);
191935a0024SGeoff Rehmet 		goto leave;
192935a0024SGeoff Rehmet 	}
193935a0024SGeoff Rehmet 	result = (*local)(&argument, rqstp);
194f249dbccSDag-Erling Smørgrav 	if (result != NULL &&
195e4253ae8SJohn Baldwin 	    !svc_sendreply(transp, xdr_result, result)) {
196935a0024SGeoff Rehmet 		svcerr_systemerr(transp);
197935a0024SGeoff Rehmet 	}
198e4253ae8SJohn Baldwin 	if (!svc_freeargs(transp, xdr_argument, &argument)) {
19940150947SPhilippe Charnier 		syslog(LOG_ERR, "unable to free arguments");
200935a0024SGeoff Rehmet 		exit(1);
201935a0024SGeoff Rehmet 	}
202935a0024SGeoff Rehmet leave:
203935a0024SGeoff Rehmet         if (from_inetd)
204935a0024SGeoff Rehmet                 exit(0);
205935a0024SGeoff Rehmet }
206