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