xref: /original-bsd/libexec/rexecd/rexecd.c (revision ce46c3ff)
130ae0772Sdist /*
2*ce46c3ffSbostic  * Copyright (c) 1983, 1993
3*ce46c3ffSbostic  *	The Regents of the University of California.  All rights reserved.
4e188a54cSbostic  *
5fac09079Sbostic  * %sccs.include.redist.c%
630ae0772Sdist  */
730ae0772Sdist 
88badd300Swnj #ifndef lint
9*ce46c3ffSbostic static char copyright[] =
10*ce46c3ffSbostic "@(#) Copyright (c) 1983, 1993\n\
11*ce46c3ffSbostic 	The Regents of the University of California.  All rights reserved.\n";
12e188a54cSbostic #endif /* not lint */
1330ae0772Sdist 
1430ae0772Sdist #ifndef lint
15*ce46c3ffSbostic static char sccsid[] = "@(#)rexecd.c	8.1 (Berkeley) 06/04/93";
16e188a54cSbostic #endif /* not lint */
178badd300Swnj 
188badd300Swnj #include <sys/param.h>
19f71c8376Sbostic #include <sys/ioctl.h>
208badd300Swnj #include <sys/socket.h>
21e2944021Slepreau #include <sys/time.h>
22c6ddb5f9Sbostic 
23f9dd9d42Ssam #include <netinet/in.h>
24c6ddb5f9Sbostic 
25f71c8376Sbostic #include <errno.h>
26c6ddb5f9Sbostic #include <netdb.h>
27c6ddb5f9Sbostic #include <paths.h>
28c6ddb5f9Sbostic #include <pwd.h>
29c6ddb5f9Sbostic #include <signal.h>
30f71c8376Sbostic #include <stdio.h>
31f71c8376Sbostic #include <stdlib.h>
32f71c8376Sbostic #include <string.h>
33c6ddb5f9Sbostic #include <unistd.h>
348badd300Swnj 
358badd300Swnj /*VARARGS1*/
368badd300Swnj int error();
37e2944021Slepreau 
388badd300Swnj /*
398badd300Swnj  * remote execute server:
408badd300Swnj  *	username\0
418badd300Swnj  *	password\0
428badd300Swnj  *	command\0
438badd300Swnj  *	data
448badd300Swnj  */
45e2944021Slepreau /*ARGSUSED*/
main(argc,argv)468badd300Swnj main(argc, argv)
478badd300Swnj 	int argc;
488badd300Swnj 	char **argv;
498badd300Swnj {
508badd300Swnj 	struct sockaddr_in from;
51bb6cbc71Skarels 	int fromlen;
528badd300Swnj 
53bb6cbc71Skarels 	fromlen = sizeof (from);
54f71c8376Sbostic 	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
55f71c8376Sbostic 		(void)fprintf(stderr,
56f71c8376Sbostic 		    "rexecd: getpeername: %s\n", strerror(errno));
57f9dd9d42Ssam 		exit(1);
58f9dd9d42Ssam 	}
59bb6cbc71Skarels 	doit(0, &from);
608badd300Swnj }
618badd300Swnj 
628badd300Swnj char	username[20] = "USER=";
638badd300Swnj char	homedir[64] = "HOME=";
648badd300Swnj char	shell[64] = "SHELL=";
655ad567c6Sbostic char	path[sizeof(_PATH_DEFPATH) + sizeof("PATH=")] = "PATH=";
668badd300Swnj char	*envinit[] =
675ad567c6Sbostic 	    {homedir, shell, path, username, 0};
688badd300Swnj char	**environ;
698badd300Swnj 
708badd300Swnj struct	sockaddr_in asin = { AF_INET };
718badd300Swnj 
doit(f,fromp)728badd300Swnj doit(f, fromp)
738badd300Swnj 	int f;
748badd300Swnj 	struct sockaddr_in *fromp;
758badd300Swnj {
768badd300Swnj 	char cmdbuf[NCARGS+1], *cp, *namep;
778badd300Swnj 	char user[16], pass[16];
788badd300Swnj 	struct passwd *pwd;
798badd300Swnj 	int s;
80ed20bae8Sbostic 	u_short port;
818badd300Swnj 	int pv[2], pid, ready, readfrom, cc;
828badd300Swnj 	char buf[BUFSIZ], sig;
838badd300Swnj 	int one = 1;
848badd300Swnj 
858badd300Swnj 	(void) signal(SIGINT, SIG_DFL);
868badd300Swnj 	(void) signal(SIGQUIT, SIG_DFL);
878badd300Swnj 	(void) signal(SIGTERM, SIG_DFL);
888badd300Swnj #ifdef DEBUG
8942b80877Sbostic 	{ int t = open(_PATH_TTY, 2);
908badd300Swnj 	  if (t >= 0) {
918badd300Swnj 		ioctl(t, TIOCNOTTY, (char *)0);
928badd300Swnj 		(void) close(t);
938badd300Swnj 	  }
948badd300Swnj 	}
958badd300Swnj #endif
968badd300Swnj 	dup2(f, 0);
978badd300Swnj 	dup2(f, 1);
988badd300Swnj 	dup2(f, 2);
998badd300Swnj 	(void) alarm(60);
1008badd300Swnj 	port = 0;
1018badd300Swnj 	for (;;) {
1028badd300Swnj 		char c;
1038badd300Swnj 		if (read(f, &c, 1) != 1)
1048badd300Swnj 			exit(1);
1058badd300Swnj 		if (c == 0)
1068badd300Swnj 			break;
1078badd300Swnj 		port = port * 10 + c - '0';
1088badd300Swnj 	}
1098badd300Swnj 	(void) alarm(0);
1108badd300Swnj 	if (port != 0) {
1119c06e5c6Sbloom 		s = socket(AF_INET, SOCK_STREAM, 0);
1128badd300Swnj 		if (s < 0)
1138badd300Swnj 			exit(1);
114f71c8376Sbostic 		if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0)
1151df21a87Ssam 			exit(1);
1168badd300Swnj 		(void) alarm(60);
117ed20bae8Sbostic 		fromp->sin_port = htons(port);
118f71c8376Sbostic 		if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0)
1198badd300Swnj 			exit(1);
1208badd300Swnj 		(void) alarm(0);
1218badd300Swnj 	}
1228badd300Swnj 	getstr(user, sizeof(user), "username");
1238badd300Swnj 	getstr(pass, sizeof(pass), "password");
1248badd300Swnj 	getstr(cmdbuf, sizeof(cmdbuf), "command");
1258badd300Swnj 	setpwent();
1268badd300Swnj 	pwd = getpwnam(user);
1278badd300Swnj 	if (pwd == NULL) {
1288badd300Swnj 		error("Login incorrect.\n");
1298badd300Swnj 		exit(1);
1308badd300Swnj 	}
1318badd300Swnj 	endpwent();
1328badd300Swnj 	if (*pwd->pw_passwd != '\0') {
1338badd300Swnj 		namep = crypt(pass, pwd->pw_passwd);
1348badd300Swnj 		if (strcmp(namep, pwd->pw_passwd)) {
1358badd300Swnj 			error("Password incorrect.\n");
1368badd300Swnj 			exit(1);
1378badd300Swnj 		}
1388badd300Swnj 	}
1398badd300Swnj 	if (chdir(pwd->pw_dir) < 0) {
1408badd300Swnj 		error("No remote directory.\n");
1418badd300Swnj 		exit(1);
1428badd300Swnj 	}
1438badd300Swnj 	(void) write(2, "\0", 1);
1448badd300Swnj 	if (port) {
1458badd300Swnj 		(void) pipe(pv);
1468badd300Swnj 		pid = fork();
1478badd300Swnj 		if (pid == -1)  {
1488badd300Swnj 			error("Try again.\n");
1498badd300Swnj 			exit(1);
1508badd300Swnj 		}
1518badd300Swnj 		if (pid) {
1528badd300Swnj 			(void) close(0); (void) close(1); (void) close(2);
1538badd300Swnj 			(void) close(f); (void) close(pv[1]);
1548badd300Swnj 			readfrom = (1<<s) | (1<<pv[0]);
1558badd300Swnj 			ioctl(pv[1], FIONBIO, (char *)&one);
1568badd300Swnj 			/* should set s nbio! */
1578badd300Swnj 			do {
1588badd300Swnj 				ready = readfrom;
159f71c8376Sbostic 				(void) select(16, (fd_set *)&ready,
160f71c8376Sbostic 				    (fd_set *)NULL, (fd_set *)NULL,
161f71c8376Sbostic 				    (struct timeval *)NULL);
1628badd300Swnj 				if (ready & (1<<s)) {
1638badd300Swnj 					if (read(s, &sig, 1) <= 0)
1648badd300Swnj 						readfrom &= ~(1<<s);
1658badd300Swnj 					else
1668badd300Swnj 						killpg(pid, sig);
1678badd300Swnj 				}
1688badd300Swnj 				if (ready & (1<<pv[0])) {
1698badd300Swnj 					cc = read(pv[0], buf, sizeof (buf));
1708badd300Swnj 					if (cc <= 0) {
17169714268Ssam 						shutdown(s, 1+1);
1728badd300Swnj 						readfrom &= ~(1<<pv[0]);
1738badd300Swnj 					} else
1748badd300Swnj 						(void) write(s, buf, cc);
1758badd300Swnj 				}
1768badd300Swnj 			} while (readfrom);
1778badd300Swnj 			exit(0);
1788badd300Swnj 		}
1798badd300Swnj 		setpgrp(0, getpid());
1808badd300Swnj 		(void) close(s); (void)close(pv[0]);
1818badd300Swnj 		dup2(pv[1], 2);
1828badd300Swnj 	}
1838badd300Swnj 	if (*pwd->pw_shell == '\0')
184f1729804Sbostic 		pwd->pw_shell = _PATH_BSHELL;
185ef279f11Sralph 	if (f > 2)
1868badd300Swnj 		(void) close(f);
187e2944021Slepreau 	(void) setgid((gid_t)pwd->pw_gid);
188f9dd9d42Ssam 	initgroups(pwd->pw_name, pwd->pw_gid);
189e2944021Slepreau 	(void) setuid((uid_t)pwd->pw_uid);
1905ad567c6Sbostic 	(void)strcat(path, _PATH_DEFPATH);
1918badd300Swnj 	environ = envinit;
1928badd300Swnj 	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
1938badd300Swnj 	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
1948badd300Swnj 	strncat(username, pwd->pw_name, sizeof(username)-6);
195c6ddb5f9Sbostic 	cp = strrchr(pwd->pw_shell, '/');
1968badd300Swnj 	if (cp)
1978badd300Swnj 		cp++;
1988badd300Swnj 	else
1998badd300Swnj 		cp = pwd->pw_shell;
2008badd300Swnj 	execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
2018badd300Swnj 	perror(pwd->pw_shell);
2028badd300Swnj 	exit(1);
2038badd300Swnj }
2048badd300Swnj 
2058badd300Swnj /*VARARGS1*/
error(fmt,a1,a2,a3)2068badd300Swnj error(fmt, a1, a2, a3)
2078badd300Swnj 	char *fmt;
2088badd300Swnj 	int a1, a2, a3;
2098badd300Swnj {
2108badd300Swnj 	char buf[BUFSIZ];
2118badd300Swnj 
2128badd300Swnj 	buf[0] = 1;
2138badd300Swnj 	(void) sprintf(buf+1, fmt, a1, a2, a3);
2148badd300Swnj 	(void) write(2, buf, strlen(buf));
2158badd300Swnj }
2168badd300Swnj 
getstr(buf,cnt,err)2178badd300Swnj getstr(buf, cnt, err)
2188badd300Swnj 	char *buf;
2198badd300Swnj 	int cnt;
2208badd300Swnj 	char *err;
2218badd300Swnj {
2228badd300Swnj 	char c;
2238badd300Swnj 
2248badd300Swnj 	do {
2258badd300Swnj 		if (read(0, &c, 1) != 1)
2268badd300Swnj 			exit(1);
2278badd300Swnj 		*buf++ = c;
2288badd300Swnj 		if (--cnt == 0) {
2298badd300Swnj 			error("%s too long\n", err);
2308badd300Swnj 			exit(1);
2318badd300Swnj 		}
2328badd300Swnj 	} while (c != 0);
2338badd300Swnj }
234