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 |
29cf7b1d | 25 | static char sccsid[] = "@(#)rshd.c 5.30 (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(); |
1e9b0900 | 100 | exit(2); |
10869b2d | 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; |
1e9b0900 | 138 | char *hostname, *errorstr = NULL, *errorhost; |
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) { |
1e9b0900 MK |
160 | syslog(LOG_ERR, "malformed \"from\" address (af %d)\n", |
161 | fromp->sin_family); | |
1d68cba5 | 162 | exit(1); |
d173f55d | 163 | } |
4c1b6a2b MK |
164 | #ifdef IP_OPTIONS |
165 | { | |
166 | u_char optbuf[BUFSIZ/3], *cp; | |
167 | char lbuf[BUFSIZ], *lp; | |
168 | int optsize = sizeof(optbuf), ipproto; | |
169 | struct protoent *ip; | |
cf9611a9 MK |
170 | #ifdef IP_OPTIONS |
171 | { | |
172 | u_char optbuf[BUFSIZ/3], *cp; | |
173 | char lbuf[BUFSIZ], *lp; | |
174 | int optsize = sizeof(optbuf), ipproto; | |
175 | struct protoent *ip; | |
176 | ||
177 | if ((ip = getprotobyname("ip")) != NULL) | |
178 | ipproto = ip->p_proto; | |
179 | else | |
180 | ipproto = IPPROTO_IP; | |
181 | if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) == 0 && | |
182 | optsize != 0) { | |
183 | lp = lbuf; | |
184 | for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) | |
185 | sprintf(lp, " %2.2x", *cp); | |
186 | syslog(LOG_NOTICE, | |
187 | "Connection received using IP options (ignored):%s", lbuf); | |
188 | if (setsockopt(0, ipproto, IP_OPTIONS, | |
189 | (char *)NULL, &optsize) != 0) { | |
190 | syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); | |
191 | exit(1); | |
192 | } | |
193 | } | |
194 | } | |
195 | #endif | |
4c1b6a2b MK |
196 | |
197 | if ((ip = getprotobyname("ip")) != NULL) | |
198 | ipproto = ip->p_proto; | |
199 | else | |
200 | ipproto = IPPROTO_IP; | |
5416610d | 201 | if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) && |
4c1b6a2b MK |
202 | optsize != 0) { |
203 | lp = lbuf; | |
204 | for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) | |
205 | sprintf(lp, " %2.2x", *cp); | |
206 | syslog(LOG_NOTICE, | |
1e9b0900 MK |
207 | "Connection received from %s using IP options (ignored):%s", |
208 | inet_ntoa(fromp->sin_addr), lbuf); | |
4c1b6a2b MK |
209 | if (setsockopt(0, ipproto, IP_OPTIONS, |
210 | (char *)NULL, &optsize) != 0) { | |
211 | syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); | |
212 | exit(1); | |
213 | } | |
214 | } | |
215 | } | |
216 | #endif | |
26c5bd5e | 217 | |
cee3e39b KF |
218 | #ifdef KERBEROS |
219 | if (!use_kerberos) | |
26c5bd5e | 220 | |
1d68cba5 BJ |
221 | (void) alarm(60); |
222 | port = 0; | |
223 | for (;;) { | |
224 | char c; | |
4c1b6a2b | 225 | if ((cc = read(0, &c, 1)) != 1) { |
c7299f34 MK |
226 | if (cc < 0) |
227 | syslog(LOG_NOTICE, "read: %m"); | |
4c1b6a2b | 228 | shutdown(0, 1+1); |
1d68cba5 | 229 | exit(1); |
d173f55d | 230 | } |
1d68cba5 BJ |
231 | port = port * 10 + c - '0'; |
232 | } | |
26c5bd5e | 233 | |
1d68cba5 BJ |
234 | (void) alarm(0); |
235 | if (port != 0) { | |
d4413a13 | 236 | int lport = IPPORT_RESERVED - 1; |
3b0e7dec | 237 | s = rresvport(&lport); |
d173f55d | 238 | if (s < 0) { |
3f99c0f7 | 239 | syslog(LOG_ERR, "can't get stderr port: %m"); |
d173f55d SL |
240 | exit(1); |
241 | } | |
cee3e39b KF |
242 | #ifdef KERBEROS |
243 | if (!use_kerberos) | |
e23c0837 | 244 | fromp->sin_port = htons((u_short)port); |
d4413a13 | 245 | if (connect(s, fromp, sizeof (*fromp)) < 0) { |
7ad57ed0 | 246 | syslog(LOG_INFO, "connect second port: %m"); |
1d68cba5 | 247 | exit(1); |
d173f55d | 248 | } |
1d68cba5 | 249 | } |
26c5bd5e | 250 | |
046a4121 | 251 | #ifdef notdef |
4c1b6a2b | 252 | /* from inetd, socket is already on 0, 1, 2 */ |
d173f55d SL |
253 | dup2(f, 0); |
254 | dup2(f, 1); | |
255 | dup2(f, 2); | |
046a4121 | 256 | #endif |
d4413a13 | 257 | hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), |
3f5b52bc | 258 | fromp->sin_family); |
26c5bd5e | 259 | if (hp) { |
046a4121 MK |
260 | /* |
261 | * If name returned by gethostbyaddr is in our domain, | |
262 | * attempt to verify that we haven't been fooled by someone | |
263 | * in a remote net; look up the name and check that this | |
264 | * address corresponds to the name. | |
265 | */ | |
1e9b0900 MK |
266 | #ifdef KERBEROS |
267 | if (!use_kerberos) | |
268 | #endif | |
269 | if (check_all || local_domain(hp->h_name)) { | |
046a4121 MK |
270 | strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); |
271 | remotehost[sizeof(remotehost) - 1] = 0; | |
1e9b0900 | 272 | errorhost = remotehost; |
26c5bd5e | 273 | hp = gethostbyname(remotehost); |
046a4121 MK |
274 | if (hp == NULL) { |
275 | syslog(LOG_INFO, | |
276 | "Couldn't look up address for %s", | |
277 | remotehost); | |
1e9b0900 MK |
278 | errorstr = |
279 | "Couldn't look up address for your host (%s)\n"; | |
280 | hostname = inet_ntoa(fromp->sin_addr); | |
beaa2897 MK |
281 | } |
282 | #ifdef h_addr /* 4.2 hack */ | |
283 | for (; ; hp->h_addr_list++) { | |
046a4121 MK |
284 | if (hp->h_addr_list[0] == NULL) { |
285 | syslog(LOG_NOTICE, | |
286 | "Host addr %s not listed for host %s", | |
287 | inet_ntoa(fromp->sin_addr), | |
288 | hp->h_name); | |
1e9b0900 MK |
289 | errorstr = |
290 | "Host address mismatch for %s\n"; | |
291 | hostname = inet_ntoa(fromp->sin_addr); | |
292 | break; | |
26c5bd5e | 293 | } |
5416610d KB |
294 | if (!bcmp(hp->h_addr_list[0], |
295 | (caddr_t)&fromp->sin_addr, | |
1e9b0900 MK |
296 | sizeof(fromp->sin_addr))) { |
297 | hostname = hp->h_name; | |
5416610d | 298 | break; |
1e9b0900 | 299 | } |
26c5bd5e | 300 | } |
beaa2897 MK |
301 | #else |
302 | if (bcmp(hp->h_addr, (caddr_t)&fromp->sin_addr, | |
303 | sizeof(fromp->sin_addr))) { | |
304 | syslog(LOG_NOTICE, | |
305 | "Host addr %s not listed for host %s", | |
306 | inet_ntoa(fromp->sin_addr), | |
307 | hp->h_name); | |
308 | error("Host address mismatch\n"); | |
309 | exit(1); | |
310 | } | |
311 | #endif | |
26c5bd5e | 312 | } |
046a4121 | 313 | } else |
1e9b0900 | 314 | errorhost = hostname = inet_ntoa(fromp->sin_addr); |
26c5bd5e | 315 | |
0d23e75d | 316 | getstr(remuser, sizeof(remuser), "remuser"); |
1d68cba5 BJ |
317 | getstr(locuser, sizeof(locuser), "locuser"); |
318 | getstr(cmdbuf, sizeof(cmdbuf), "command"); | |
319 | setpwent(); | |
320 | pwd = getpwnam(locuser); | |
321 | if (pwd == NULL) { | |
1e9b0900 MK |
322 | if (errorstr == NULL) |
323 | errorstr = "Login incorrect.\n"; | |
324 | goto fail; | |
1d68cba5 | 325 | } |
1d68cba5 | 326 | if (chdir(pwd->pw_dir) < 0) { |
d4413a13 | 327 | (void) chdir("/"); |
bb933cc2 | 328 | #ifdef notdef |
1d68cba5 BJ |
329 | error("No remote directory.\n"); |
330 | exit(1); | |
bb933cc2 | 331 | #endif |
1d68cba5 | 332 | } |
26c5bd5e | 333 | |
0d23e75d MK |
334 | if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && |
335 | ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) { | |
336 | error("Permission denied.\n"); | |
337 | exit(1); | |
338 | } | |
26c5bd5e | 339 | |
17ccb086 | 340 | if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) { |
c9db37f1 KB |
341 | error("Logins currently disabled.\n"); |
342 | exit(1); | |
343 | } | |
beaa2897 | 344 | |
1d68cba5 | 345 | (void) write(2, "\0", 1); |
56940953 | 346 | sent_null = 1; |
beaa2897 | 347 | sent_null = 1; |
26c5bd5e | 348 | |
1d68cba5 BJ |
349 | if (port) { |
350 | if (pipe(pv) < 0) { | |
351 | error("Can't make pipe.\n"); | |
352 | exit(1); | |
353 | } | |
d6dd6df6 KF |
354 | #ifdef KERBEROS |
355 | if (encrypt) { | |
356 | if (pipe(pv1) < 0) { | |
357 | error("Can't make 2nd pipe.\n"); | |
358 | exit(1); | |
359 | } | |
360 | if (pipe(pv2) < 0) { | |
361 | error("Can't make 3rd pipe.\n"); | |
362 | exit(1); | |
363 | } | |
364 | } | |
365 | #endif | |
1d68cba5 BJ |
366 | pid = fork(); |
367 | if (pid == -1) { | |
56940953 | 368 | error("Can't fork; try again.\n"); |
1d68cba5 BJ |
369 | exit(1); |
370 | } | |
371 | if (pid) { | |
d6dd6df6 KF |
372 | #ifdef KERBEROS |
373 | if (encrypt) { | |
374 | static char msg[] = SECURE_MESSAGE; | |
56940953 MK |
375 | (void) close(pv1[1]); |
376 | (void) close(pv2[1]); | |
d6dd6df6 KF |
377 | des_write(s, msg, sizeof(msg)); |
378 | ||
379 | } else | |
380 | #endif | |
381 | { | |
382 | (void) close(0); (void) close(1); | |
d6dd6df6 | 383 | } |
56940953 | 384 | (void) close(2); (void) close(pv[1]); |
d6dd6df6 | 385 | |
046a4121 MK |
386 | FD_ZERO(&readfrom); |
387 | FD_SET(s, &readfrom); | |
388 | FD_SET(pv[0], &readfrom); | |
56940953 MK |
389 | if (pv[0] > s) |
390 | nfd = pv[0]; | |
391 | else | |
392 | nfd = s; | |
d6dd6df6 KF |
393 | #ifdef KERBEROS |
394 | if (encrypt) { | |
395 | FD_ZERO(&writeto); | |
396 | FD_SET(pv2[0], &writeto); | |
397 | FD_SET(pv1[0], &readfrom); | |
398 | ||
399 | nfd = MAX(nfd, pv2[0]); | |
400 | nfd = MAX(nfd, pv1[0]); | |
401 | } else | |
402 | #endif | |
403 | ioctl(pv[0], FIONBIO, (char *)&one); | |
404 | ||
1d68cba5 | 405 | /* should set s nbio! */ |
56940953 | 406 | nfd++; |
1d68cba5 BJ |
407 | do { |
408 | ready = readfrom; | |
d6dd6df6 KF |
409 | #ifdef KERBEROS |
410 | if (encrypt) { | |
411 | wready = writeto; | |
412 | if (select(nfd, &ready, | |
413 | &wready, (fd_set *) 0, | |
414 | (struct timeval *) 0) < 0) | |
415 | break; | |
416 | } else | |
417 | #endif | |
418 | if (select(nfd, &ready, (fd_set *)0, | |
419 | (fd_set *)0, (struct timeval *)0) < 0) | |
420 | break; | |
046a4121 | 421 | if (FD_ISSET(s, &ready)) { |
d6dd6df6 KF |
422 | int ret; |
423 | #ifdef KERBEROS | |
424 | if (encrypt) | |
425 | ret = des_read(s, &sig, 1); | |
426 | else | |
427 | #endif | |
428 | ret = read(s, &sig, 1); | |
429 | if (ret <= 0) | |
046a4121 | 430 | FD_CLR(s, &readfrom); |
1d68cba5 BJ |
431 | else |
432 | killpg(pid, sig); | |
433 | } | |
046a4121 | 434 | if (FD_ISSET(pv[0], &ready)) { |
fadc6b8f | 435 | errno = 0; |
d6dd6df6 | 436 | cc = read(pv[0], buf, sizeof(buf)); |
1d68cba5 | 437 | if (cc <= 0) { |
ff24c640 | 438 | shutdown(s, 1+1); |
046a4121 | 439 | FD_CLR(pv[0], &readfrom); |
d6dd6df6 KF |
440 | } else { |
441 | #ifdef KERBEROS | |
442 | if (encrypt) | |
443 | (void) | |
444 | des_write(s, buf, cc); | |
445 | else | |
446 | #endif | |
447 | (void) | |
448 | write(s, buf, cc); | |
449 | } | |
450 | } | |
451 | #ifdef KERBEROS | |
452 | ||
453 | if (encrypt && FD_ISSET(pv1[0], &ready)) { | |
454 | errno = 0; | |
455 | cc = read(pv1[0], buf, sizeof(buf)); | |
456 | if (cc <= 0) { | |
457 | shutdown(pv1[0], 1+1); | |
458 | FD_CLR(pv1[0], &readfrom); | |
459 | } else | |
460 | (void) des_write(1, buf, cc); | |
461 | } | |
462 | ||
463 | if (encrypt && FD_ISSET(pv2[0], &wready)) { | |
464 | errno = 0; | |
465 | cc = des_read(0, buf, sizeof(buf)); | |
466 | if (cc <= 0) { | |
467 | shutdown(pv2[0], 1+1); | |
468 | FD_CLR(pv2[0], &writeto); | |
1d68cba5 | 469 | } else |
d6dd6df6 | 470 | (void) write(pv2[0], buf, cc); |
1d68cba5 | 471 | } |
d6dd6df6 KF |
472 | #endif |
473 | ||
046a4121 | 474 | } while (FD_ISSET(s, &readfrom) || |
d6dd6df6 KF |
475 | #ifdef KERBEROS |
476 | (encrypt && FD_ISSET(pv1[0], &readfrom)) || | |
477 | #endif | |
046a4121 | 478 | FD_ISSET(pv[0], &readfrom)); |
1d68cba5 BJ |
479 | exit(0); |
480 | } | |
481 | setpgrp(0, getpid()); | |
482 | (void) close(s); (void) close(pv[0]); | |
d6dd6df6 KF |
483 | #ifdef KERBEROS |
484 | if (encrypt) { | |
485 | close(pv1[0]); close(pv2[0]); | |
486 | dup2(pv1[1], 1); | |
487 | dup2(pv2[1], 0); | |
488 | close(pv1[1]); | |
489 | close(pv2[1]); | |
490 | } | |
491 | #endif | |
1d68cba5 | 492 | dup2(pv[1], 2); |
389cc7a4 | 493 | close(pv[1]); |
beaa2897 | 494 | close(pv[1]); |
1d68cba5 BJ |
495 | } |
496 | if (*pwd->pw_shell == '\0') | |
17ccb086 | 497 | pwd->pw_shell = _PATH_BSHELL; |
d6dd6df6 | 498 | #if BSD > 43 |
56940953 MK |
499 | if (setlogin(pwd->pw_name) < 0) |
500 | syslog(LOG_ERR, "setlogin() failed: %m"); | |
d6dd6df6 | 501 | #endif |
56940953 MK |
502 | (void) setgid((gid_t)pwd->pw_gid); |
503 | initgroups(pwd->pw_name, pwd->pw_gid); | |
d4413a13 | 504 | (void) setuid((uid_t)pwd->pw_uid); |
1d68cba5 BJ |
505 | environ = envinit; |
506 | strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); | |
507 | strncat(shell, pwd->pw_shell, sizeof(shell)-7); | |
508 | strncat(username, pwd->pw_name, sizeof(username)-6); | |
509 | cp = rindex(pwd->pw_shell, '/'); | |
510 | if (cp) | |
511 | cp++; | |
512 | else | |
513 | cp = pwd->pw_shell; | |
cee3e39b | 514 | endpwent(); |
beaa2897 MK |
515 | if (pwd->pw_uid == 0) |
516 | syslog(LOG_INFO|LOG_AUTH, "ROOT shell from %s@%s, comm: %s\n", | |
517 | remuser, hostname, cmdbuf); | |
518 | endpwent(); | |
56940953 | 519 | if (pwd->pw_uid == 0) { |
49114004 KF |
520 | #ifdef KERBEROS |
521 | if (use_kerberos) | |
56940953 | 522 | syslog(LOG_INFO|LOG_AUTH, |
49114004 KF |
523 | "ROOT Kerberos shell from %s.%s@%s on %s, comm: %s\n", |
524 | kdata->pname, kdata->pinst, kdata->prealm, | |
525 | hostname, cmdbuf); | |
526 | else | |
527 | #endif | |
56940953 | 528 | syslog(LOG_INFO|LOG_AUTH, |
49114004 KF |
529 | "ROOT shell from %s@%s, comm: %s\n", |
530 | remuser, hostname, cmdbuf); | |
531 | } | |
1d68cba5 BJ |
532 | execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); |
533 | perror(pwd->pw_shell); | |
534 | exit(1); | |
1d68cba5 BJ |
535 | } |
536 | ||
beaa2897 MK |
537 | /* |
538 | * Report error to client. | |
539 | * Note: can't be used until second socket has connected | |
540 | * to client, or older clients will hang waiting | |
541 | * for that connection first. | |
542 | */ | |
56940953 MK |
543 | /* |
544 | * Report error to client. | |
545 | * Note: can't be used until second socket has connected | |
546 | * to client, or older clients will hang waiting | |
547 | * for that connection first. | |
548 | */ | |
d4413a13 | 549 | /*VARARGS1*/ |
35db6ea0 | 550 | error(fmt, a1, a2, a3) |
1d68cba5 | 551 | char *fmt; |
35db6ea0 | 552 | int a1, a2, a3; |
1d68cba5 | 553 | { |
56940953 | 554 | char buf[BUFSIZ], *bp = buf; |
1d68cba5 | 555 | |
56940953 MK |
556 | if (sent_null == 0) |
557 | *bp++ = 1; | |
558 | (void) sprintf(bp, fmt, a1, a2, a3); | |
1d68cba5 BJ |
559 | (void) write(2, buf, strlen(buf)); |
560 | } | |
561 | ||
562 | getstr(buf, cnt, err) | |
563 | char *buf; | |
564 | int cnt; | |
565 | char *err; | |
566 | { | |
567 | char c; | |
568 | ||
569 | do { | |
570 | if (read(0, &c, 1) != 1) | |
571 | exit(1); | |
572 | *buf++ = c; | |
573 | if (--cnt == 0) { | |
574 | error("%s too long\n", err); | |
575 | exit(1); | |
576 | } | |
577 | } while (c != 0); | |
578 | } | |
26c5bd5e | 579 | |
046a4121 MK |
580 | /* |
581 | * Check whether host h is in our local domain, | |
56940953 MK |
582 | * defined as sharing the last two components of the domain part, |
583 | * or the entire domain part if the local domain has only one component. | |
046a4121 MK |
584 | * If either name is unqualified (contains no '.'), |
585 | * assume that the host is local, as it will be | |
586 | * interpreted as such. | |
587 | */ | |
588 | local_domain(h) | |
589 | char *h; | |
26c5bd5e | 590 | { |
046a4121 | 591 | char localhost[MAXHOSTNAMELEN]; |
56940953 | 592 | char *p1, *p2, *topdomain(); |
046a4121 | 593 | |
beaa2897 | 594 | localhost[0] = 0; |
56940953 | 595 | localhost[0] = 0; |
046a4121 | 596 | (void) gethostname(localhost, sizeof(localhost)); |
56940953 MK |
597 | p1 = topdomain(localhost); |
598 | p2 = topdomain(h); | |
046a4121 | 599 | if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) |
26c5bd5e KF |
600 | return(1); |
601 | return(0); | |
602 | } | |
0d097e0d | 603 | |
56940953 MK |
604 | char * |
605 | topdomain(h) | |
606 | char *h; | |
607 | { | |
608 | register char *p; | |
609 | char *maybe = NULL; | |
610 | int dots = 0; | |
611 | ||
612 | for (p = h + strlen(h); p >= h; p--) { | |
613 | if (*p == '.') { | |
614 | if (++dots == 2) | |
615 | return (p); | |
616 | maybe = p; | |
617 | } | |
618 | } | |
619 | return (maybe); | |
620 | } | |
621 | ||
beaa2897 MK |
622 | char * |
623 | topdomain(h) | |
624 | char *h; | |
625 | { | |
626 | register char *p; | |
627 | char *maybe = NULL; | |
628 | int dots = 0; | |
629 | ||
630 | for (p = h + strlen(h); p >= h; p--) { | |
631 | if (*p == '.') { | |
632 | if (++dots == 2) | |
633 | return (p); | |
634 | maybe = p; | |
635 | } | |
636 | } | |
637 | return (maybe); | |
638 | } | |
639 | ||
0d097e0d KF |
640 | usage() |
641 | { | |
642 | #ifdef KERBEROS | |
56940953 | 643 | syslog(LOG_ERR, "usage: rshd [-aln]"); |
d6dd6df6 | 644 | #else |
56940953 | 645 | syslog(LOG_ERR, "usage: rshd [-alknvx]"); |
0d097e0d KF |
646 | #endif |
647 | } |