xref: /csrg-svn/lib/libc/net/rcmd.c (revision 33679)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of California at Berkeley. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12 
13 #if defined(LIBC_SCCS) && !defined(lint)
14 static char sccsid[] = "@(#)rcmd.c	5.16 (Berkeley) 03/07/88";
15 #endif /* LIBC_SCCS and not lint */
16 
17 #include <stdio.h>
18 #include <ctype.h>
19 #include <pwd.h>
20 #include <sys/param.h>
21 #include <sys/file.h>
22 #include <sys/signal.h>
23 #include <sys/socket.h>
24 #include <sys/stat.h>
25 
26 #include <netinet/in.h>
27 
28 #include <netdb.h>
29 #include <errno.h>
30 
31 extern	errno;
32 char	*index();
33 
34 rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
35 	char **ahost;
36 	u_short rport;
37 	char *locuser, *remuser, *cmd;
38 	int *fd2p;
39 {
40 	int s, timo = 1, pid;
41 	long oldmask;
42 	struct sockaddr_in sin, sin2, from;
43 	char c;
44 	int lport = IPPORT_RESERVED - 1;
45 	struct hostent *hp;
46 
47 	pid = getpid();
48 	hp = gethostbyname(*ahost);
49 	if (hp == 0) {
50 		fprintf(stderr, "%s: unknown host\n", *ahost);
51 		return (-1);
52 	}
53 	*ahost = hp->h_name;
54 	oldmask = sigblock(sigmask(SIGURG));
55 	for (;;) {
56 		s = rresvport(&lport);
57 		if (s < 0) {
58 			if (errno == EAGAIN)
59 				fprintf(stderr, "socket: All ports in use\n");
60 			else
61 				perror("rcmd: socket");
62 			sigsetmask(oldmask);
63 			return (-1);
64 		}
65 		fcntl(s, F_SETOWN, pid);
66 		sin.sin_family = hp->h_addrtype;
67 		bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
68 		sin.sin_port = rport;
69 		if (connect(s, (caddr_t)&sin, sizeof (sin), 0) >= 0)
70 			break;
71 		(void) close(s);
72 		if (errno == EADDRINUSE) {
73 			lport--;
74 			continue;
75 		}
76 		if (errno == ECONNREFUSED && timo <= 16) {
77 			sleep(timo);
78 			timo *= 2;
79 			continue;
80 		}
81 		if (hp->h_addr_list[1] != NULL) {
82 			int oerrno = errno;
83 
84 			fprintf(stderr,
85 			    "connect to address %s: ", inet_ntoa(sin.sin_addr));
86 			errno = oerrno;
87 			perror(0);
88 			hp->h_addr_list++;
89 			bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
90 			    hp->h_length);
91 			fprintf(stderr, "Trying %s...\n",
92 				inet_ntoa(sin.sin_addr));
93 			continue;
94 		}
95 		perror(hp->h_name);
96 		sigsetmask(oldmask);
97 		return (-1);
98 	}
99 	lport--;
100 	if (fd2p == 0) {
101 		write(s, "", 1);
102 		lport = 0;
103 	} else {
104 		char num[8];
105 		int s2 = rresvport(&lport), s3;
106 		int len = sizeof (from);
107 
108 		if (s2 < 0)
109 			goto bad;
110 		listen(s2, 1);
111 		(void) sprintf(num, "%d", lport);
112 		if (write(s, num, strlen(num)+1) != strlen(num)+1) {
113 			perror("write: setting up stderr");
114 			(void) close(s2);
115 			goto bad;
116 		}
117 		s3 = accept(s2, &from, &len, 0);
118 		(void) close(s2);
119 		if (s3 < 0) {
120 			perror("accept");
121 			lport = 0;
122 			goto bad;
123 		}
124 		*fd2p = s3;
125 		from.sin_port = ntohs((u_short)from.sin_port);
126 		if (from.sin_family != AF_INET ||
127 		    from.sin_port >= IPPORT_RESERVED) {
128 			fprintf(stderr,
129 			    "socket: protocol failure in circuit setup.\n");
130 			goto bad2;
131 		}
132 	}
133 	(void) write(s, locuser, strlen(locuser)+1);
134 	(void) write(s, remuser, strlen(remuser)+1);
135 	(void) write(s, cmd, strlen(cmd)+1);
136 	if (read(s, &c, 1) != 1) {
137 		perror(*ahost);
138 		goto bad2;
139 	}
140 	if (c != 0) {
141 		while (read(s, &c, 1) == 1) {
142 			(void) write(2, &c, 1);
143 			if (c == '\n')
144 				break;
145 		}
146 		goto bad2;
147 	}
148 	sigsetmask(oldmask);
149 	return (s);
150 bad2:
151 	if (lport)
152 		(void) close(*fd2p);
153 bad:
154 	(void) close(s);
155 	sigsetmask(oldmask);
156 	return (-1);
157 }
158 
159 rresvport(alport)
160 	int *alport;
161 {
162 	struct sockaddr_in sin;
163 	int s;
164 
165 	sin.sin_family = AF_INET;
166 	sin.sin_addr.s_addr = INADDR_ANY;
167 	s = socket(AF_INET, SOCK_STREAM, 0);
168 	if (s < 0)
169 		return (-1);
170 	for (;;) {
171 		sin.sin_port = htons((u_short)*alport);
172 		if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0)
173 			return (s);
174 		if (errno != EADDRINUSE) {
175 			(void) close(s);
176 			return (-1);
177 		}
178 		(*alport)--;
179 		if (*alport == IPPORT_RESERVED/2) {
180 			(void) close(s);
181 			errno = EAGAIN;		/* close */
182 			return (-1);
183 		}
184 	}
185 }
186 
187 ruserok(rhost, superuser, ruser, luser)
188 	char *rhost;
189 	int superuser;
190 	char *ruser, *luser;
191 {
192 	FILE *hostf;
193 	char fhost[MAXHOSTNAMELEN];
194 	int first = 1;
195 	register char *sp, *p;
196 	int baselen = -1;
197 
198 	sp = rhost;
199 	p = fhost;
200 	while (*sp) {
201 		if (*sp == '.') {
202 			if (baselen == -1)
203 				baselen = sp - rhost;
204 			*p++ = *sp++;
205 		} else {
206 			*p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
207 		}
208 	}
209 	*p = '\0';
210 	hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
211 again:
212 	if (hostf) {
213 		if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
214 			(void) fclose(hostf);
215 			return(0);
216 		}
217 		(void) fclose(hostf);
218 	}
219 	if (first == 1) {
220 		struct stat sbuf;
221 		struct passwd *pwd;
222 		char pbuf[MAXPATHLEN];
223 
224 		first = 0;
225 		if ((pwd = getpwnam(luser)) == NULL)
226 			return(-1);
227 		(void)strcpy(pbuf, pwd->pw_dir);
228 		(void)strcat(pbuf, "/.rhosts");
229 		if ((hostf = fopen(pbuf, "r")) == NULL)
230 			return(-1);
231 		(void)fstat(fileno(hostf), &sbuf);
232 		if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
233 			fclose(hostf);
234 			return(-1);
235 		}
236 		goto again;
237 	}
238 	return (-1);
239 }
240 
241 _validuser(hostf, rhost, luser, ruser, baselen)
242 char *rhost, *luser, *ruser;
243 FILE *hostf;
244 int baselen;
245 {
246 	char *user;
247 	char ahost[MAXHOSTNAMELEN];
248 	register char *p;
249 
250 	while (fgets(ahost, sizeof (ahost), hostf)) {
251 		p = ahost;
252 		while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
253 			*p = isupper(*p) ? tolower(*p) : *p;
254 			p++;
255 		}
256 		if (*p == ' ' || *p == '\t') {
257 			*p++ = '\0';
258 			while (*p == ' ' || *p == '\t')
259 				p++;
260 			user = p;
261 			while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
262 				p++;
263 		} else
264 			user = p;
265 		*p = '\0';
266 		if (_checkhost(rhost, ahost, baselen) &&
267 		    !strcmp(ruser, *user ? user : luser)) {
268 			return (0);
269 		}
270 	}
271 	return (-1);
272 }
273 
274 _checkhost(rhost, lhost, len)
275 char *rhost, *lhost;
276 int len;
277 {
278 	static char ldomain[MAXHOSTNAMELEN + 1];
279 	static char *domainp = NULL;
280 	static int nodomain = 0;
281 	register char *cp;
282 
283 	if (len == -1)
284 		return(!strcmp(rhost, lhost));
285 	if (strncmp(rhost, lhost, len))
286 		return(0);
287 	if (!strcmp(rhost, lhost))
288 		return(1);
289 	if (*(lhost + len) != '\0')
290 		return(0);
291 	if (nodomain)
292 		return(0);
293 	if (!domainp) {
294 		if (gethostname(ldomain, sizeof(ldomain)) == -1) {
295 			nodomain = 1;
296 			return(0);
297 		}
298 		ldomain[MAXHOSTNAMELEN] = NULL;
299 		if ((domainp = index(ldomain, '.')) == (char *)NULL) {
300 			nodomain = 1;
301 			return(0);
302 		}
303 		for (cp = ++domainp; *cp; ++cp)
304 			if (isupper(*cp))
305 				*cp = tolower(*cp);
306 	}
307 	return(!strcmp(domainp, rhost + len +1));
308 }
309