xref: /csrg-svn/lib/libc/net/rcmd.c (revision 24865)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)rcmd.c	5.7 (Berkeley) 09/17/85";
9 #endif not lint
10 
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <pwd.h>
14 #include <sys/param.h>
15 #include <sys/socket.h>
16 #include <sys/stat.h>
17 
18 #include <netinet/in.h>
19 
20 #include <netdb.h>
21 #include <errno.h>
22 
23 extern	errno;
24 char	*index(), *sprintf();
25 
26 rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
27 	char **ahost;
28 	int rport;
29 	char *locuser, *remuser, *cmd;
30 	int *fd2p;
31 {
32 	int s, timo = 1;
33 	struct sockaddr_in sin, sin2, from;
34 	char c;
35 	int lport = IPPORT_RESERVED - 1;
36 	struct hostent *hp;
37 
38 	hp = gethostbyname(*ahost);
39 	if (hp == 0) {
40 		fprintf(stderr, "%s: unknown host\n", *ahost);
41 		return (-1);
42 	}
43 	*ahost = hp->h_name;
44 retry:
45 	s = rresvport(&lport);
46 	if (s < 0) {
47 		if (errno == EAGAIN)
48 			fprintf(stderr, "socket: All ports in use\n");
49 		else
50 			perror("rcmd: socket");
51 		return (-1);
52 	}
53 	sin.sin_family = hp->h_addrtype;
54 	bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
55 	sin.sin_port = rport;
56 	if (connect(s, (caddr_t)&sin, sizeof (sin), 0) < 0) {
57 		(void) close(s);
58 		if (errno == EADDRINUSE) {
59 			lport--;
60 			goto retry;
61 		}
62 		if (errno == ECONNREFUSED && timo <= 16) {
63 			sleep(timo);
64 			timo *= 2;
65 			goto retry;
66 		}
67 		perror(hp->h_name);
68 		return (-1);
69 	}
70 	lport--;
71 	if (fd2p == 0) {
72 		write(s, "", 1);
73 		lport = 0;
74 	} else {
75 		char num[8];
76 		int s2 = rresvport(&lport), s3;
77 		int len = sizeof (from);
78 
79 		if (s2 < 0)
80 			goto bad;
81 		listen(s2, 1);
82 		(void) sprintf(num, "%d", lport);
83 		if (write(s, num, strlen(num)+1) != strlen(num)+1) {
84 			perror("write: setting up stderr");
85 			(void) close(s2);
86 			goto bad;
87 		}
88 		s3 = accept(s2, &from, &len, 0);
89 		(void) close(s2);
90 		if (s3 < 0) {
91 			perror("accept");
92 			lport = 0;
93 			goto bad;
94 		}
95 		*fd2p = s3;
96 		from.sin_port = ntohs((u_short)from.sin_port);
97 		if (from.sin_family != AF_INET ||
98 		    from.sin_port >= IPPORT_RESERVED) {
99 			fprintf(stderr,
100 			    "socket: protocol failure in circuit setup.\n");
101 			goto bad2;
102 		}
103 	}
104 	(void) write(s, locuser, strlen(locuser)+1);
105 	(void) write(s, remuser, strlen(remuser)+1);
106 	(void) write(s, cmd, strlen(cmd)+1);
107 	if (read(s, &c, 1) != 1) {
108 		perror(*ahost);
109 		goto bad2;
110 	}
111 	if (c != 0) {
112 		while (read(s, &c, 1) == 1) {
113 			(void) write(2, &c, 1);
114 			if (c == '\n')
115 				break;
116 		}
117 		goto bad2;
118 	}
119 	return (s);
120 bad2:
121 	if (lport)
122 		(void) close(*fd2p);
123 bad:
124 	(void) close(s);
125 	return (-1);
126 }
127 
128 rresvport(alport)
129 	int *alport;
130 {
131 	struct sockaddr_in sin;
132 	int s;
133 
134 	sin.sin_family = AF_INET;
135 	sin.sin_addr.s_addr = INADDR_ANY;
136 	s = socket(AF_INET, SOCK_STREAM, 0);
137 	if (s < 0)
138 		return (-1);
139 	for (;;) {
140 		sin.sin_port = htons((u_short)*alport);
141 		if (bind(s, (caddr_t)&sin, sizeof (sin), 0) >= 0)
142 			return (s);
143 		if (errno != EADDRINUSE) {
144 			(void) close(s);
145 			return (-1);
146 		}
147 		(*alport)--;
148 		if (*alport == IPPORT_RESERVED/2) {
149 			(void) close(s);
150 			errno = EAGAIN;		/* close */
151 			return (-1);
152 		}
153 	}
154 }
155 
156 ruserok(rhost, superuser, ruser, luser)
157 	char *rhost;
158 	int superuser;
159 	char *ruser, *luser;
160 {
161 	FILE *hostf;
162 	char fhost[MAXHOSTNAMELEN];
163 	char ahost[MAXHOSTNAMELEN];
164 	int first = 1;
165 	register char *sp, *p;
166 	int baselen = -1;
167 
168 	sp = rhost;
169 	p = fhost;
170 	while (*sp) {
171 		if (*sp == '.') {
172 			if (baselen == -1)
173 				baselen = sp - rhost;
174 			*p++ = *sp++;
175 		} else {
176 			*p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
177 		}
178 	}
179 	*p = '\0';
180 	hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
181 again:
182 	if (hostf) {
183 		while (fgets(ahost, sizeof (ahost), hostf)) {
184 			char *user;
185 
186 			p = ahost;
187 			while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
188 				*p++ = isupper(*p) ? tolower(*p) : *p;
189 			if (*p == ' ' || *p == '\t') {
190 				*p++ = '\0';
191 				while (*p == ' ' || *p == '\t')
192 					p++;
193 				user = p;
194 				while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
195 					p++;
196 			} else
197 				user = p;
198 			*p = '\0';
199 			if (_checkhost(fhost, ahost, baselen) &&
200 			    !strcmp(ruser, *user ? user : luser)) {
201 				(void) fclose(hostf);
202 				return (0);
203 			}
204 		}
205 		(void) fclose(hostf);
206 	}
207 	if (first == 1) {
208 		struct stat sbuf;
209 		struct passwd *pwd;
210 		char pbuf[MAXPATHLEN];
211 
212 		first = 0;
213 		if ((pwd = getpwnam(luser)) == NULL)
214 			return(-1);
215 		(void)strcpy(pbuf, pwd->pw_dir);
216 		(void)strcat(pbuf, "/.rhosts");
217 		if ((hostf = fopen(pbuf, "r")) == NULL)
218 			return(-1);
219 		(void)fstat(fileno(hostf), &sbuf);
220 		if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
221 			fclose(hostf);
222 			return(-1);
223 		}
224 		goto again;
225 	}
226 	return (-1);
227 }
228 
229 _checkhost(rhost, lhost, len)
230 char *rhost, *lhost;
231 int len;
232 {
233 	static char ldomain[MAXHOSTNAMELEN + 1];
234 	static char *domainp = NULL;
235 	register char *cp;
236 
237 	if (len == -1)
238 		return(!strcmp(rhost, lhost));
239 	if (strncmp(rhost, lhost, len))
240 		return(0);
241 	if (!strcmp(rhost, lhost))
242 		return(1);
243 	if (*(lhost + len) != '\0')
244 		return(0);
245 	if (!domainp) {
246 		if (gethostname(ldomain, sizeof(ldomain)) == -1) {
247 			domainp = (char *)1;
248 			return(0);
249 		}
250 		ldomain[MAXHOSTNAMELEN] = NULL;
251 		if ((domainp = index(ldomain, '.') + 1) == (char *)1)
252 			return(0);
253 		cp = domainp;
254 		while (*cp)
255 			*cp++ = isupper(*cp) ? tolower(*cp) : *cp;
256 	}
257 	if (domainp == (char *)1)
258 		return(0);
259 	return(!strcmp(domainp, rhost + len +1));
260 }
261