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