Commit | Line | Data |
---|---|---|
ccb7ffcd | 1 | /*- |
8b0826c1 | 2 | * Copyright (c) 1988, 1989, 1992, 1993, 1994 |
2e9feff0 | 3 | * The Regents of the University of California. All rights reserved. |
780d12ad | 4 | * |
836fe169 | 5 | * %sccs.include.redist.c% |
8c5eec2f DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
2e9feff0 | 9 | static char copyright[] = |
8b0826c1 | 10 | "@(#) Copyright (c) 1988, 1989, 1992, 1993, 1994\n\ |
2e9feff0 | 11 | The Regents of the University of California. All rights reserved.\n"; |
780d12ad | 12 | #endif /* not lint */ |
8c5eec2f | 13 | |
1d68cba5 | 14 | #ifndef lint |
8b0826c1 | 15 | static char sccsid[] = "@(#)rshd.c 8.2 (Berkeley) %G%"; |
780d12ad | 16 | #endif /* not lint */ |
1d68cba5 | 17 | |
bb933cc2 MK |
18 | /* |
19 | * remote shell server: | |
046a4121 | 20 | * [port]\0 |
bb933cc2 MK |
21 | * remuser\0 |
22 | * locuser\0 | |
23 | * command\0 | |
24 | * data | |
25 | */ | |
1d68cba5 | 26 | #include <sys/param.h> |
046a4121 | 27 | #include <sys/ioctl.h> |
d4413a13 | 28 | #include <sys/time.h> |
ccb7ffcd | 29 | #include <sys/socket.h> |
5492e445 | 30 | |
e7d6d17a | 31 | #include <netinet/in.h> |
4c99408e | 32 | #include <arpa/inet.h> |
ccb7ffcd | 33 | #include <netdb.h> |
4c99408e | 34 | |
8b0826c1 | 35 | #include <errno.h> |
5492e445 | 36 | #include <fcntl.h> |
8b0826c1 | 37 | #include <paths.h> |
1d68cba5 | 38 | #include <pwd.h> |
8b0826c1 | 39 | #include <signal.h> |
ccb7ffcd KB |
40 | #include <stdio.h> |
41 | #include <stdlib.h> | |
42 | #include <string.h> | |
8b0826c1 JSP |
43 | #include <syslog.h> |
44 | #include <unistd.h> | |
1d68cba5 | 45 | |
e0ffdf97 | 46 | int keepalive = 1; |
56940953 | 47 | int check_all = 0; |
5492e445 AC |
48 | int check_all; |
49 | int log_success; /* If TRUE, log all successful accesses */ | |
56940953 | 50 | int sent_null; |
beaa2897 | 51 | int sent_null; |
bb933cc2 | 52 | |
5492e445 AC |
53 | void doit __P((struct sockaddr_in *)); |
54 | void error __P((const char *, ...)); | |
55 | void getstr __P((char *, int, char *)); | |
56 | int local_domain __P((char *)); | |
57 | char *topdomain __P((char *)); | |
58 | void usage __P((void)); | |
59 | ||
60 | int | |
1d68cba5 BJ |
61 | main(argc, argv) |
62 | int argc; | |
5492e445 | 63 | char *argv[]; |
1d68cba5 | 64 | { |
5492e445 | 65 | extern int __check_rhosts_file; |
bcb894cb | 66 | struct linger linger; |
10869b2d | 67 | int ch, on = 1, fromlen; |
1d68cba5 | 68 | struct sockaddr_in from; |
3f5b52bc | 69 | |
0d097e0d | 70 | openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON); |
10869b2d KB |
71 | |
72 | opterr = 0; | |
56940953 MK |
73 | switch (ch) { |
74 | case 'a': | |
75 | check_all = 1; | |
76 | break; | |
10869b2d | 77 | case 'l': |
5492e445 | 78 | __check_rhosts_file = 0; |
10869b2d | 79 | break; |
e0ffdf97 KB |
80 | case 'n': |
81 | keepalive = 0; | |
82 | break; | |
10869b2d KB |
83 | case '?': |
84 | default: | |
0d097e0d | 85 | usage(); |
8b0826c1 | 86 | break; |
10869b2d | 87 | } |
26c5bd5e | 88 | |
10869b2d KB |
89 | argc -= optind; |
90 | argv += optind; | |
91 | ||
bb933cc2 | 92 | fromlen = sizeof (from); |
ccb7ffcd | 93 | if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { |
56940953 | 94 | syslog(LOG_ERR, "getpeername: %m"); |
bb933cc2 | 95 | _exit(1); |
3f5b52bc | 96 | } |
e0ffdf97 KB |
97 | if (keepalive && |
98 | setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, | |
99 | sizeof(on)) < 0) | |
3f99c0f7 | 100 | syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); |
bcb894cb SL |
101 | linger.l_onoff = 1; |
102 | linger.l_linger = 60; /* XXX */ | |
d4413a13 JL |
103 | if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger, |
104 | sizeof (linger)) < 0) | |
3f99c0f7 | 105 | syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); |
4c1b6a2b | 106 | doit(&from); |
5492e445 | 107 | /* NOTREACHED */ |
a8e3386b SL |
108 | } |
109 | ||
1d68cba5 BJ |
110 | char username[20] = "USER="; |
111 | char homedir[64] = "HOME="; | |
112 | char shell[64] = "SHELL="; | |
e515a157 | 113 | char path[100] = "PATH="; |
1d68cba5 | 114 | char *envinit[] = |
e515a157 | 115 | {homedir, shell, path, username, 0}; |
1d68cba5 BJ |
116 | char **environ; |
117 | ||
5492e445 | 118 | void |
4c1b6a2b | 119 | doit(fromp) |
1d68cba5 BJ |
120 | struct sockaddr_in *fromp; |
121 | { | |
5492e445 | 122 | extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */ |
3f5b52bc | 123 | struct hostent *hp; |
5492e445 | 124 | struct passwd *pwd; |
dec47a22 | 125 | u_short port; |
046a4121 | 126 | fd_set ready, readfrom; |
5492e445 | 127 | int cc, nfd, pv[2], pid, s; |
1d68cba5 | 128 | int one = 1; |
5492e445 AC |
129 | char *hostname, *errorstr, *errorhost; |
130 | char *cp, sig, buf[BUFSIZ]; | |
131 | char cmdbuf[NCARGS+1], locuser[16], remuser[16]; | |
046a4121 | 132 | char remotehost[2 * MAXHOSTNAMELEN + 1]; |
26c5bd5e | 133 | |
1d68cba5 BJ |
134 | (void) signal(SIGINT, SIG_DFL); |
135 | (void) signal(SIGQUIT, SIG_DFL); | |
136 | (void) signal(SIGTERM, SIG_DFL); | |
27890867 | 137 | #ifdef DEBUG |
b52175dc | 138 | { int t = open(_PATH_TTY, 2); |
1d68cba5 BJ |
139 | if (t >= 0) { |
140 | ioctl(t, TIOCNOTTY, (char *)0); | |
141 | (void) close(t); | |
142 | } | |
143 | } | |
144 | #endif | |
1d68cba5 | 145 | fromp->sin_port = ntohs((u_short)fromp->sin_port); |
c7299f34 | 146 | if (fromp->sin_family != AF_INET) { |
1e9b0900 MK |
147 | syslog(LOG_ERR, "malformed \"from\" address (af %d)\n", |
148 | fromp->sin_family); | |
1d68cba5 | 149 | exit(1); |
d173f55d | 150 | } |
4c1b6a2b MK |
151 | #ifdef IP_OPTIONS |
152 | { | |
153 | u_char optbuf[BUFSIZ/3], *cp; | |
154 | char lbuf[BUFSIZ], *lp; | |
155 | int optsize = sizeof(optbuf), ipproto; | |
156 | struct protoent *ip; | |
cf9611a9 MK |
157 | #ifdef IP_OPTIONS |
158 | { | |
159 | u_char optbuf[BUFSIZ/3], *cp; | |
160 | char lbuf[BUFSIZ], *lp; | |
161 | int optsize = sizeof(optbuf), ipproto; | |
162 | struct protoent *ip; | |
163 | ||
164 | if ((ip = getprotobyname("ip")) != NULL) | |
165 | ipproto = ip->p_proto; | |
166 | else | |
167 | ipproto = IPPROTO_IP; | |
168 | if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) == 0 && | |
169 | optsize != 0) { | |
170 | lp = lbuf; | |
171 | for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) | |
172 | sprintf(lp, " %2.2x", *cp); | |
173 | syslog(LOG_NOTICE, | |
174 | "Connection received using IP options (ignored):%s", lbuf); | |
175 | if (setsockopt(0, ipproto, IP_OPTIONS, | |
176 | (char *)NULL, &optsize) != 0) { | |
177 | syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); | |
178 | exit(1); | |
179 | } | |
180 | } | |
181 | } | |
182 | #endif | |
4c1b6a2b MK |
183 | |
184 | if ((ip = getprotobyname("ip")) != NULL) | |
185 | ipproto = ip->p_proto; | |
186 | else | |
187 | ipproto = IPPROTO_IP; | |
5416610d | 188 | if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) && |
4c1b6a2b MK |
189 | optsize != 0) { |
190 | lp = lbuf; | |
191 | for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) | |
192 | sprintf(lp, " %2.2x", *cp); | |
193 | syslog(LOG_NOTICE, | |
1e9b0900 MK |
194 | "Connection received from %s using IP options (ignored):%s", |
195 | inet_ntoa(fromp->sin_addr), lbuf); | |
4c1b6a2b | 196 | if (setsockopt(0, ipproto, IP_OPTIONS, |
ccb7ffcd | 197 | (char *)NULL, optsize) != 0) { |
4c1b6a2b MK |
198 | syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); |
199 | exit(1); | |
200 | } | |
201 | } | |
202 | } | |
203 | #endif | |
26c5bd5e | 204 | |
cee3e39b KF |
205 | #ifdef KERBEROS |
206 | if (!use_kerberos) | |
26c5bd5e | 207 | |
1d68cba5 BJ |
208 | (void) alarm(60); |
209 | port = 0; | |
210 | for (;;) { | |
211 | char c; | |
cf5b24dd | 212 | if ((cc = read(STDIN_FILENO, &c, 1)) != 1) { |
c7299f34 MK |
213 | if (cc < 0) |
214 | syslog(LOG_NOTICE, "read: %m"); | |
4c1b6a2b | 215 | shutdown(0, 1+1); |
1d68cba5 | 216 | exit(1); |
d173f55d | 217 | } |
1d68cba5 BJ |
218 | port = port * 10 + c - '0'; |
219 | } | |
26c5bd5e | 220 | |
1d68cba5 BJ |
221 | (void) alarm(0); |
222 | if (port != 0) { | |
d4413a13 | 223 | int lport = IPPORT_RESERVED - 1; |
3b0e7dec | 224 | s = rresvport(&lport); |
d173f55d | 225 | if (s < 0) { |
3f99c0f7 | 226 | syslog(LOG_ERR, "can't get stderr port: %m"); |
d173f55d SL |
227 | exit(1); |
228 | } | |
cee3e39b KF |
229 | #ifdef KERBEROS |
230 | if (!use_kerberos) | |
dec47a22 | 231 | fromp->sin_port = htons(port); |
ccb7ffcd | 232 | if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { |
5492e445 | 233 | syslog(LOG_INFO, "connect second port %d: %m", port); |
1d68cba5 | 234 | exit(1); |
d173f55d | 235 | } |
1d68cba5 | 236 | } |
26c5bd5e | 237 | |
046a4121 | 238 | #ifdef notdef |
4c1b6a2b | 239 | /* from inetd, socket is already on 0, 1, 2 */ |
d173f55d SL |
240 | dup2(f, 0); |
241 | dup2(f, 1); | |
242 | dup2(f, 2); | |
046a4121 | 243 | #endif |
5492e445 | 244 | errorstr = NULL; |
d4413a13 | 245 | hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), |
3f5b52bc | 246 | fromp->sin_family); |
26c5bd5e | 247 | if (hp) { |
046a4121 MK |
248 | /* |
249 | * If name returned by gethostbyaddr is in our domain, | |
250 | * attempt to verify that we haven't been fooled by someone | |
251 | * in a remote net; look up the name and check that this | |
252 | * address corresponds to the name. | |
253 | */ | |
25a61f03 | 254 | hostname = hp->h_name; |
1e9b0900 MK |
255 | #ifdef KERBEROS |
256 | if (!use_kerberos) | |
257 | #endif | |
258 | if (check_all || local_domain(hp->h_name)) { | |
046a4121 MK |
259 | strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); |
260 | remotehost[sizeof(remotehost) - 1] = 0; | |
1e9b0900 | 261 | errorhost = remotehost; |
26c5bd5e | 262 | hp = gethostbyname(remotehost); |
046a4121 MK |
263 | if (hp == NULL) { |
264 | syslog(LOG_INFO, | |
265 | "Couldn't look up address for %s", | |
266 | remotehost); | |
dec47a22 | 267 | errorstr = |
1e9b0900 MK |
268 | "Couldn't look up address for your host (%s)\n"; |
269 | hostname = inet_ntoa(fromp->sin_addr); | |
beaa2897 MK |
270 | } |
271 | #ifdef h_addr /* 4.2 hack */ | |
272 | for (; ; hp->h_addr_list++) { | |
046a4121 MK |
273 | if (hp->h_addr_list[0] == NULL) { |
274 | syslog(LOG_NOTICE, | |
275 | "Host addr %s not listed for host %s", | |
276 | inet_ntoa(fromp->sin_addr), | |
277 | hp->h_name); | |
1e9b0900 MK |
278 | errorstr = |
279 | "Host address mismatch for %s\n"; | |
280 | hostname = inet_ntoa(fromp->sin_addr); | |
281 | break; | |
26c5bd5e | 282 | } |
5416610d KB |
283 | if (!bcmp(hp->h_addr_list[0], |
284 | (caddr_t)&fromp->sin_addr, | |
1e9b0900 MK |
285 | sizeof(fromp->sin_addr))) { |
286 | hostname = hp->h_name; | |
5416610d | 287 | break; |
1e9b0900 | 288 | } |
26c5bd5e | 289 | } |
beaa2897 MK |
290 | #else |
291 | if (bcmp(hp->h_addr, (caddr_t)&fromp->sin_addr, | |
292 | sizeof(fromp->sin_addr))) { | |
293 | syslog(LOG_NOTICE, | |
294 | "Host addr %s not listed for host %s", | |
295 | inet_ntoa(fromp->sin_addr), | |
296 | hp->h_name); | |
297 | error("Host address mismatch\n"); | |
298 | exit(1); | |
299 | } | |
300 | #endif | |
26c5bd5e | 301 | } |
046a4121 | 302 | } else |
1e9b0900 | 303 | errorhost = hostname = inet_ntoa(fromp->sin_addr); |
26c5bd5e | 304 | |
0d23e75d | 305 | getstr(remuser, sizeof(remuser), "remuser"); |
1d68cba5 BJ |
306 | getstr(locuser, sizeof(locuser), "locuser"); |
307 | getstr(cmdbuf, sizeof(cmdbuf), "command"); | |
308 | setpwent(); | |
309 | pwd = getpwnam(locuser); | |
310 | if (pwd == NULL) { | |
5492e445 AC |
311 | syslog(LOG_INFO|LOG_AUTH, |
312 | "%s@%s as %s: unknown login. cmd='%.80s'", | |
313 | remuser, hostname, locuser, cmdbuf); | |
1e9b0900 MK |
314 | if (errorstr == NULL) |
315 | errorstr = "Login incorrect.\n"; | |
316 | goto fail; | |
1d68cba5 | 317 | } |
1d68cba5 | 318 | if (chdir(pwd->pw_dir) < 0) { |
d4413a13 | 319 | (void) chdir("/"); |
bb933cc2 | 320 | #ifdef notdef |
5492e445 AC |
321 | syslog(LOG_INFO|LOG_AUTH, |
322 | "%s@%s as %s: no home directory. cmd='%.80s'", | |
323 | remuser, hostname, locuser, cmdbuf); | |
1d68cba5 BJ |
324 | error("No remote directory.\n"); |
325 | exit(1); | |
bb933cc2 | 326 | #endif |
1d68cba5 | 327 | } |
26c5bd5e | 328 | |
0d23e75d MK |
329 | if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && |
330 | ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) { | |
331 | error("Permission denied.\n"); | |
332 | exit(1); | |
333 | } | |
26c5bd5e | 334 | |
17ccb086 | 335 | if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) { |
c9db37f1 KB |
336 | error("Logins currently disabled.\n"); |
337 | exit(1); | |
338 | } | |
beaa2897 | 339 | |
cf5b24dd | 340 | (void) write(STDERR_FILENO, "\0", 1); |
56940953 | 341 | sent_null = 1; |
beaa2897 | 342 | sent_null = 1; |
26c5bd5e | 343 | |
1d68cba5 BJ |
344 | if (port) { |
345 | if (pipe(pv) < 0) { | |
346 | error("Can't make pipe.\n"); | |
347 | exit(1); | |
348 | } | |
349 | pid = fork(); | |
350 | if (pid == -1) { | |
56940953 | 351 | error("Can't fork; try again.\n"); |
1d68cba5 BJ |
352 | exit(1); |
353 | } | |
354 | if (pid) { | |
d6dd6df6 | 355 | { |
5492e445 AC |
356 | (void) close(0); |
357 | (void) close(1); | |
d6dd6df6 | 358 | } |
5492e445 AC |
359 | (void) close(2); |
360 | (void) close(pv[1]); | |
d6dd6df6 | 361 | |
046a4121 MK |
362 | FD_ZERO(&readfrom); |
363 | FD_SET(s, &readfrom); | |
364 | FD_SET(pv[0], &readfrom); | |
56940953 MK |
365 | if (pv[0] > s) |
366 | nfd = pv[0]; | |
367 | else | |
368 | nfd = s; | |
d6dd6df6 KF |
369 | ioctl(pv[0], FIONBIO, (char *)&one); |
370 | ||
1d68cba5 | 371 | /* should set s nbio! */ |
56940953 | 372 | nfd++; |
1d68cba5 BJ |
373 | do { |
374 | ready = readfrom; | |
d6dd6df6 | 375 | if (select(nfd, &ready, (fd_set *)0, |
dec47a22 | 376 | (fd_set *)0, (struct timeval *)0) < 0) |
d6dd6df6 | 377 | break; |
046a4121 | 378 | if (FD_ISSET(s, &ready)) { |
d6dd6df6 | 379 | int ret; |
d6dd6df6 KF |
380 | ret = read(s, &sig, 1); |
381 | if (ret <= 0) | |
046a4121 | 382 | FD_CLR(s, &readfrom); |
1d68cba5 BJ |
383 | else |
384 | killpg(pid, sig); | |
385 | } | |
046a4121 | 386 | if (FD_ISSET(pv[0], &ready)) { |
fadc6b8f | 387 | errno = 0; |
d6dd6df6 | 388 | cc = read(pv[0], buf, sizeof(buf)); |
1d68cba5 | 389 | if (cc <= 0) { |
ff24c640 | 390 | shutdown(s, 1+1); |
046a4121 | 391 | FD_CLR(pv[0], &readfrom); |
d6dd6df6 | 392 | } else { |
d6dd6df6 KF |
393 | (void) |
394 | write(s, buf, cc); | |
395 | } | |
396 | } | |
d6dd6df6 | 397 | |
046a4121 MK |
398 | } while (FD_ISSET(s, &readfrom) || |
399 | FD_ISSET(pv[0], &readfrom)); | |
1d68cba5 BJ |
400 | exit(0); |
401 | } | |
402 | setpgrp(0, getpid()); | |
5492e445 AC |
403 | (void) close(s); |
404 | (void) close(pv[0]); | |
1d68cba5 | 405 | dup2(pv[1], 2); |
389cc7a4 | 406 | close(pv[1]); |
beaa2897 | 407 | close(pv[1]); |
1d68cba5 BJ |
408 | } |
409 | if (*pwd->pw_shell == '\0') | |
17ccb086 | 410 | pwd->pw_shell = _PATH_BSHELL; |
d6dd6df6 | 411 | #if BSD > 43 |
56940953 MK |
412 | if (setlogin(pwd->pw_name) < 0) |
413 | syslog(LOG_ERR, "setlogin() failed: %m"); | |
d6dd6df6 | 414 | #endif |
56940953 MK |
415 | (void) setgid((gid_t)pwd->pw_gid); |
416 | initgroups(pwd->pw_name, pwd->pw_gid); | |
d4413a13 | 417 | (void) setuid((uid_t)pwd->pw_uid); |
1d68cba5 BJ |
418 | environ = envinit; |
419 | strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); | |
e515a157 | 420 | strcat(path, _PATH_DEFPATH); |
1d68cba5 BJ |
421 | strncat(shell, pwd->pw_shell, sizeof(shell)-7); |
422 | strncat(username, pwd->pw_name, sizeof(username)-6); | |
8b0826c1 | 423 | cp = strrchr(pwd->pw_shell, '/'); |
1d68cba5 BJ |
424 | if (cp) |
425 | cp++; | |
426 | else | |
427 | cp = pwd->pw_shell; | |
cee3e39b | 428 | endpwent(); |
beaa2897 MK |
429 | if (pwd->pw_uid == 0) |
430 | syslog(LOG_INFO|LOG_AUTH, "ROOT shell from %s@%s, comm: %s\n", | |
431 | remuser, hostname, cmdbuf); | |
432 | endpwent(); | |
5492e445 | 433 | if (log_success || pwd->pw_uid == 0) { |
49114004 KF |
434 | #ifdef KERBEROS |
435 | if (use_kerberos) | |
5492e445 AC |
436 | syslog(LOG_INFO|LOG_AUTH, |
437 | "Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'", | |
438 | kdata->pname, kdata->pinst, kdata->prealm, | |
439 | hostname, locuser, cmdbuf); | |
49114004 KF |
440 | else |
441 | #endif | |
5492e445 AC |
442 | syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", |
443 | remuser, hostname, locuser, cmdbuf); | |
49114004 | 444 | } |
1d68cba5 BJ |
445 | execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); |
446 | perror(pwd->pw_shell); | |
447 | exit(1); | |
1d68cba5 BJ |
448 | } |
449 | ||
beaa2897 MK |
450 | /* |
451 | * Report error to client. | |
452 | * Note: can't be used until second socket has connected | |
453 | * to client, or older clients will hang waiting | |
454 | * for that connection first. | |
455 | */ | |
56940953 | 456 | /* |
5492e445 AC |
457 | * Report error to client. Note: can't be used until second socket has |
458 | * connected to client, or older clients will hang waiting for that | |
459 | * connection first. | |
56940953 | 460 | */ |
5492e445 AC |
461 | #if __STDC__ |
462 | #include <stdarg.h> | |
463 | #else | |
464 | #include <varargs.h> | |
465 | #endif | |
466 | ||
467 | void | |
468 | #if __STDC__ | |
469 | error(const char *fmt, ...) | |
470 | #else | |
471 | error(fmt, va_alist) | |
1d68cba5 | 472 | char *fmt; |
5492e445 AC |
473 | va_dcl |
474 | #endif | |
1d68cba5 | 475 | { |
5492e445 AC |
476 | va_list ap; |
477 | int len; | |
478 | char *bp, buf[BUFSIZ]; | |
479 | #if __STDC__ | |
480 | va_start(ap, fmt); | |
481 | #else | |
482 | va_start(ap); | |
483 | #endif | |
484 | bp = buf; | |
485 | if (sent_null == 0) { | |
56940953 | 486 | *bp++ = 1; |
5492e445 AC |
487 | len = 1; |
488 | } else | |
489 | len = 0; | |
2dbdf5a9 KB |
490 | (void)vsnprintf(bp, sizeof(buf) - 1, fmt, ap); |
491 | (void)write(STDERR_FILENO, buf, len + strlen(bp)); | |
1d68cba5 BJ |
492 | } |
493 | ||
5492e445 | 494 | void |
1d68cba5 | 495 | getstr(buf, cnt, err) |
5492e445 | 496 | char *buf, *err; |
1d68cba5 | 497 | int cnt; |
1d68cba5 BJ |
498 | { |
499 | char c; | |
500 | ||
501 | do { | |
cf5b24dd | 502 | if (read(STDIN_FILENO, &c, 1) != 1) |
1d68cba5 BJ |
503 | exit(1); |
504 | *buf++ = c; | |
505 | if (--cnt == 0) { | |
506 | error("%s too long\n", err); | |
507 | exit(1); | |
508 | } | |
509 | } while (c != 0); | |
510 | } | |
26c5bd5e | 511 | |
046a4121 MK |
512 | /* |
513 | * Check whether host h is in our local domain, | |
56940953 MK |
514 | * defined as sharing the last two components of the domain part, |
515 | * or the entire domain part if the local domain has only one component. | |
046a4121 MK |
516 | * If either name is unqualified (contains no '.'), |
517 | * assume that the host is local, as it will be | |
518 | * interpreted as such. | |
519 | */ | |
5492e445 | 520 | int |
046a4121 MK |
521 | local_domain(h) |
522 | char *h; | |
26c5bd5e | 523 | { |
046a4121 | 524 | char localhost[MAXHOSTNAMELEN]; |
5492e445 | 525 | char *p1, *p2; |
046a4121 | 526 | |
beaa2897 | 527 | localhost[0] = 0; |
56940953 | 528 | localhost[0] = 0; |
046a4121 | 529 | (void) gethostname(localhost, sizeof(localhost)); |
56940953 MK |
530 | p1 = topdomain(localhost); |
531 | p2 = topdomain(h); | |
046a4121 | 532 | if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) |
5492e445 AC |
533 | return (1); |
534 | return (0); | |
26c5bd5e | 535 | } |
0d097e0d | 536 | |
56940953 MK |
537 | char * |
538 | topdomain(h) | |
539 | char *h; | |
540 | { | |
541 | register char *p; | |
542 | char *maybe = NULL; | |
543 | int dots = 0; | |
544 | ||
545 | for (p = h + strlen(h); p >= h; p--) { | |
546 | if (*p == '.') { | |
547 | if (++dots == 2) | |
548 | return (p); | |
549 | maybe = p; | |
550 | } | |
551 | } | |
552 | return (maybe); | |
553 | } | |
554 | ||
beaa2897 MK |
555 | char * |
556 | topdomain(h) | |
557 | char *h; | |
558 | { | |
8b0826c1 | 559 | char *p, *maybe = NULL; |
beaa2897 MK |
560 | int dots = 0; |
561 | ||
562 | for (p = h + strlen(h); p >= h; p--) { | |
563 | if (*p == '.') { | |
564 | if (++dots == 2) | |
565 | return (p); | |
566 | maybe = p; | |
567 | } | |
568 | } | |
569 | return (maybe); | |
570 | } | |
571 | ||
5492e445 | 572 | void |
0d097e0d KF |
573 | usage() |
574 | { | |
8b0826c1 | 575 | |
8ae69711 | 576 | syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS); |
8b0826c1 | 577 | exit(2); |
0d097e0d | 578 | } |