xref: /freebsd/crypto/heimdal/appl/rsh/rshd.c (revision 8373020d34ceb1ac55d8f43333c1ca3680185b39)
1 /*
2  * Copyright (c) 1997-2002 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "rsh_locl.h"
35 RCSID("$Id: rshd.c,v 1.46 2002/02/18 20:02:14 joda Exp $");
36 
37 int
38 login_access( struct passwd *user, char *from);
39 
40 enum auth_method auth_method;
41 
42 #ifdef KRB5
43 krb5_context context;
44 krb5_keyblock *keyblock;
45 krb5_crypto crypto;
46 #endif
47 
48 #ifdef KRB4
49 des_key_schedule schedule;
50 des_cblock iv;
51 #endif
52 
53 #ifdef KRB5
54 krb5_ccache ccache, ccache2;
55 int kerberos_status = 0;
56 #endif
57 
58 int do_encrypt = 0;
59 
60 static int do_unique_tkfile           = 0;
61 static char tkfile[MAXPATHLEN] = "";
62 
63 static int do_inetd = 1;
64 static char *port_str;
65 static int do_rhosts = 1;
66 static int do_kerberos = 0;
67 #define DO_KRB4 2
68 #define DO_KRB5 4
69 static int do_vacuous = 0;
70 static int do_log = 1;
71 #ifdef KRB4
72 static int do_newpag = 1;
73 #endif
74 static int do_addr_verify = 0;
75 static int do_keepalive = 1;
76 static int do_version;
77 static int do_help = 0;
78 
79 #if defined(KRB5) && defined(DCE)
80 int dfsk5ok = 0;
81 int dfspag = 0;
82 int dfsfwd = 0;
83 krb5_ticket *user_ticket;
84 #endif
85 
86 static void
87 syslog_and_die (const char *m, ...)
88     __attribute__ ((format (printf, 1, 2)));
89 
90 static void
91 syslog_and_die (const char *m, ...)
92 {
93     va_list args;
94 
95     va_start(args, m);
96     vsyslog (LOG_ERR, m, args);
97     va_end(args);
98     exit (1);
99 }
100 
101 static void
102 fatal (int, const char*, const char *, ...)
103     __attribute__ ((format (printf, 3, 4)));
104 
105 static void
106 fatal (int sock, const char *what, const char *m, ...)
107 {
108     va_list args;
109     char buf[BUFSIZ];
110     size_t len;
111 
112     *buf = 1;
113     va_start(args, m);
114     len = vsnprintf (buf + 1, sizeof(buf) - 1, m, args);
115     len = min(len, sizeof(buf) - 1);
116     va_end(args);
117     if(what != NULL)
118 	syslog (LOG_ERR, "%s: %m: %s", what, buf + 1);
119     else
120 	syslog (LOG_ERR, "%s", buf + 1);
121     net_write (sock, buf, len + 1);
122     exit (1);
123 }
124 
125 static void
126 read_str (int s, char *str, size_t sz, char *expl)
127 {
128     while (sz > 0) {
129 	if (net_read (s, str, 1) != 1)
130 	    syslog_and_die ("read: %m");
131 	if (*str == '\0')
132 	    return;
133 	--sz;
134 	++str;
135     }
136     fatal (s, NULL, "%s too long", expl);
137 }
138 
139 static int
140 recv_bsd_auth (int s, u_char *buf,
141 	       struct sockaddr_in *thisaddr,
142 	       struct sockaddr_in *thataddr,
143 	       char *client_username,
144 	       char *server_username,
145 	       char *cmd)
146 {
147     struct passwd *pwd;
148 
149     read_str (s, client_username, USERNAME_SZ, "local username");
150     read_str (s, server_username, USERNAME_SZ, "remote username");
151     read_str (s, cmd, COMMAND_SZ, "command");
152     pwd = getpwnam(server_username);
153     if (pwd == NULL)
154 	fatal(s, NULL, "Login incorrect.");
155     if (iruserok(thataddr->sin_addr.s_addr, pwd->pw_uid == 0,
156 		 client_username, server_username))
157 	fatal(s, NULL, "Login incorrect.");
158     return 0;
159 }
160 
161 #ifdef KRB4
162 static int
163 recv_krb4_auth (int s, u_char *buf,
164 		struct sockaddr *thisaddr,
165 		struct sockaddr *thataddr,
166 		char *client_username,
167 		char *server_username,
168 		char *cmd)
169 {
170     int status;
171     int32_t options;
172     KTEXT_ST ticket;
173     AUTH_DAT auth;
174     char instance[INST_SZ + 1];
175     char version[KRB_SENDAUTH_VLEN + 1];
176 
177     if (memcmp (buf, KRB_SENDAUTH_VERS, 4) != 0)
178 	return -1;
179     if (net_read (s, buf + 4, KRB_SENDAUTH_VLEN - 4) !=
180 	KRB_SENDAUTH_VLEN - 4)
181 	syslog_and_die ("reading auth info: %m");
182     if (memcmp (buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN) != 0)
183 	syslog_and_die("unrecognized auth protocol: %.8s", buf);
184 
185     options = KOPT_IGNORE_PROTOCOL;
186     if (do_encrypt)
187 	options |= KOPT_DO_MUTUAL;
188     k_getsockinst (s, instance, sizeof(instance));
189     status = krb_recvauth (options,
190 			   s,
191 			   &ticket,
192 			   "rcmd",
193 			   instance,
194 			   (struct sockaddr_in *)thataddr,
195 			   (struct sockaddr_in *)thisaddr,
196 			   &auth,
197 			   "",
198 			   schedule,
199 			   version);
200     if (status != KSUCCESS)
201 	syslog_and_die ("recvauth: %s", krb_get_err_text(status));
202     if (strncmp (version, KCMD_VERSION, KRB_SENDAUTH_VLEN) != 0)
203 	syslog_and_die ("bad version: %s", version);
204 
205     read_str (s, server_username, USERNAME_SZ, "remote username");
206     if (kuserok (&auth, server_username) != 0)
207 	fatal (s, NULL, "Permission denied.");
208     read_str (s, cmd, COMMAND_SZ, "command");
209 
210     syslog(LOG_INFO|LOG_AUTH,
211 	   "kerberos v4 shell from %s on %s as %s, cmd '%.80s'",
212 	   krb_unparse_name_long(auth.pname, auth.pinst, auth.prealm),
213 
214 	   inet_ntoa(((struct sockaddr_in *)thataddr)->sin_addr),
215 	   server_username,
216 	   cmd);
217 
218     memcpy (iv, auth.session, sizeof(iv));
219 
220     return 0;
221 }
222 
223 #endif /* KRB4 */
224 
225 #ifdef KRB5
226 static int
227 save_krb5_creds (int s,
228                  krb5_auth_context auth_context,
229                  krb5_principal client)
230 
231 {
232     int ret;
233     krb5_data remote_cred;
234 
235     krb5_data_zero (&remote_cred);
236     ret= krb5_read_message (context, (void *)&s, &remote_cred);
237     if (ret) {
238 	krb5_data_free(&remote_cred);
239 	return 0;
240     }
241     if (remote_cred.length == 0)
242 	return 0;
243 
244     ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &ccache);
245     if (ret) {
246 	krb5_data_free(&remote_cred);
247 	return 0;
248     }
249 
250     krb5_cc_initialize(context,ccache,client);
251     ret = krb5_rd_cred2(context, auth_context, ccache, &remote_cred);
252     krb5_data_free (&remote_cred);
253     if (ret)
254 	return 0;
255     return 1;
256 }
257 
258 static void
259 krb5_start_session (void)
260 {
261     krb5_error_code ret;
262 
263     ret = krb5_cc_resolve (context, tkfile, &ccache2);
264     if (ret) {
265 	krb5_cc_destroy(context, ccache);
266 	return;
267     }
268 
269     ret = krb5_cc_copy_cache (context, ccache, ccache2);
270     if (ret) {
271 	krb5_cc_destroy(context, ccache);
272 	return ;
273     }
274 
275     krb5_cc_close(context, ccache2);
276     krb5_cc_destroy(context, ccache);
277     return;
278 }
279 
280 static int
281 recv_krb5_auth (int s, u_char *buf,
282 		struct sockaddr *thisaddr,
283 		struct sockaddr *thataddr,
284 		char *client_username,
285 		char *server_username,
286 		char *cmd)
287 {
288     u_int32_t len;
289     krb5_auth_context auth_context = NULL;
290     krb5_ticket *ticket;
291     krb5_error_code status;
292     krb5_data cksum_data;
293     krb5_principal server;
294 
295     if (memcmp (buf, "\x00\x00\x00\x13", 4) != 0)
296 	return -1;
297     len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
298 
299     if (net_read(s, buf, len) != len)
300 	syslog_and_die ("reading auth info: %m");
301     if (len != sizeof(KRB5_SENDAUTH_VERSION)
302 	|| memcmp (buf, KRB5_SENDAUTH_VERSION, len) != 0)
303 	syslog_and_die ("bad sendauth version: %.8s", buf);
304 
305     status = krb5_sock_to_principal (context,
306 				     s,
307 				     "host",
308 				     KRB5_NT_SRV_HST,
309 				     &server);
310     if (status)
311 	syslog_and_die ("krb5_sock_to_principal: %s",
312 			krb5_get_err_text(context, status));
313 
314     status = krb5_recvauth(context,
315 			   &auth_context,
316 			   &s,
317 			   KCMD_VERSION,
318 			   server,
319 			   KRB5_RECVAUTH_IGNORE_VERSION,
320 			   NULL,
321 			   &ticket);
322     krb5_free_principal (context, server);
323     if (status)
324 	syslog_and_die ("krb5_recvauth: %s",
325 			krb5_get_err_text(context, status));
326 
327     read_str (s, server_username, USERNAME_SZ, "remote username");
328     read_str (s, cmd, COMMAND_SZ, "command");
329     read_str (s, client_username, COMMAND_SZ, "local username");
330 
331     status = krb5_auth_con_getkey (context, auth_context, &keyblock);
332     if (status)
333        syslog_and_die ("krb5_auth_con_getkey: %s",
334                        krb5_get_err_text(context, status));
335 
336     status = krb5_crypto_init(context, keyblock, 0, &crypto);
337     if(status)
338 	syslog_and_die("krb5_crypto_init: %s",
339 		       krb5_get_err_text(context, status));
340 
341 
342     cksum_data.length = asprintf ((char **)&cksum_data.data,
343 				  "%u:%s%s",
344 				  ntohs(socket_get_port (thisaddr)),
345 				  cmd,
346 				  server_username);
347 
348     status = krb5_verify_authenticator_checksum(context,
349 						auth_context,
350 						cksum_data.data,
351 						cksum_data.length);
352 
353     if (status)
354 	syslog_and_die ("krb5_verify_authenticator_checksum: %s",
355 			krb5_get_err_text(context, status));
356 
357     free (cksum_data.data);
358 
359     if (strncmp (client_username, "-u ", 3) == 0) {
360 	do_unique_tkfile = 1;
361 	memmove (client_username, client_username + 3,
362 		 strlen(client_username) - 2);
363     }
364 
365     if (strncmp (client_username, "-U ", 3) == 0) {
366 	char *end, *temp_tkfile;
367 
368 	do_unique_tkfile = 1;
369 	if (strncmp (server_username + 3, "FILE:", 5) == 0) {
370 	    temp_tkfile = tkfile;
371 	} else {
372 	    strcpy (tkfile, "FILE:");
373 	    temp_tkfile = tkfile + 5;
374 	}
375 	end = strchr(client_username + 3,' ');
376 	strncpy(temp_tkfile, client_username + 3, end - client_username - 3);
377 	temp_tkfile[end - client_username - 3] = '\0';
378 	memmove (client_username, end +1, strlen(end+1)+1);
379     }
380 
381     kerberos_status = save_krb5_creds (s, auth_context, ticket->client);
382 
383     if(!krb5_kuserok (context,
384 		     ticket->client,
385 		     server_username))
386 	fatal (s, NULL, "Permission denied.");
387 
388     if (strncmp (cmd, "-x ", 3) == 0) {
389 	do_encrypt = 1;
390 	memmove (cmd, cmd + 3, strlen(cmd) - 2);
391     } else {
392 	if(do_encrypt)
393 	    fatal (s, NULL, "Encryption is required.");
394 	do_encrypt = 0;
395     }
396 
397     {
398 	char *name;
399 
400 	if (krb5_unparse_name (context, ticket->client, &name) == 0) {
401 	    char addr_str[256];
402 
403 	    if (inet_ntop (thataddr->sa_family,
404 			   socket_get_address (thataddr),
405 			   addr_str, sizeof(addr_str)) == NULL)
406 		strlcpy (addr_str, "unknown address",
407 				 sizeof(addr_str));
408 
409 	    syslog(LOG_INFO|LOG_AUTH,
410 		   "kerberos v5 shell from %s on %s as %s, cmd '%.80s'",
411 		   name,
412 		   addr_str,
413 		   server_username,
414 		   cmd);
415 	    free (name);
416 	}
417     }
418 
419 #if defined(DCE)
420     user_ticket = ticket;
421 #endif
422 
423     return 0;
424 }
425 #endif /* KRB5 */
426 
427 static void
428 loop (int from0, int to0,
429       int to1,   int from1,
430       int to2,   int from2)
431 {
432     fd_set real_readset;
433     int max_fd;
434     int count = 2;
435 
436     if(from0 >= FD_SETSIZE || from1 >= FD_SETSIZE || from2 >= FD_SETSIZE)
437 	errx (1, "fd too large");
438 
439     FD_ZERO(&real_readset);
440     FD_SET(from0, &real_readset);
441     FD_SET(from1, &real_readset);
442     FD_SET(from2, &real_readset);
443     max_fd = max(from0, max(from1, from2)) + 1;
444     for (;;) {
445 	int ret;
446 	fd_set readset = real_readset;
447 	char buf[RSH_BUFSIZ];
448 
449 	ret = select (max_fd, &readset, NULL, NULL, NULL);
450 	if (ret < 0) {
451 	    if (errno == EINTR)
452 		continue;
453 	    else
454 		syslog_and_die ("select: %m");
455 	}
456 	if (FD_ISSET(from0, &readset)) {
457 	    ret = do_read (from0, buf, sizeof(buf));
458 	    if (ret < 0)
459 		syslog_and_die ("read: %m");
460 	    else if (ret == 0) {
461 		close (from0);
462 		close (to0);
463 		FD_CLR(from0, &real_readset);
464 	    } else
465 		net_write (to0, buf, ret);
466 	}
467 	if (FD_ISSET(from1, &readset)) {
468 	    ret = read (from1, buf, sizeof(buf));
469 	    if (ret < 0)
470 		syslog_and_die ("read: %m");
471 	    else if (ret == 0) {
472 		close (from1);
473 		close (to1);
474 		FD_CLR(from1, &real_readset);
475 		if (--count == 0)
476 		    exit (0);
477 	    } else
478 		do_write (to1, buf, ret);
479 	}
480 	if (FD_ISSET(from2, &readset)) {
481 	    ret = read (from2, buf, sizeof(buf));
482 	    if (ret < 0)
483 		syslog_and_die ("read: %m");
484 	    else if (ret == 0) {
485 		close (from2);
486 		close (to2);
487 		FD_CLR(from2, &real_readset);
488 		if (--count == 0)
489 		    exit (0);
490 	    } else
491 		do_write (to2, buf, ret);
492 	}
493    }
494 }
495 
496 /*
497  * Used by `setup_copier' to create some pipe-like means of
498  * communcation.  Real pipes would probably be the best thing, but
499  * then the shell doesn't understand it's talking to rshd.  If
500  * socketpair doesn't work everywhere, some autoconf magic would have
501  * to be added here.
502  *
503  * If it fails creating the `pipe', it aborts by calling fatal.
504  */
505 
506 static void
507 pipe_a_like (int fd[2])
508 {
509     if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd) < 0)
510 	fatal (STDOUT_FILENO, "socketpair", "Pipe creation failed.");
511 }
512 
513 /*
514  * Start a child process and leave the parent copying data to and from it.  */
515 
516 static void
517 setup_copier (void)
518 {
519     int p0[2], p1[2], p2[2];
520     pid_t pid;
521 
522     pipe_a_like(p0);
523     pipe_a_like(p1);
524     pipe_a_like(p2);
525     pid = fork ();
526     if (pid < 0)
527 	fatal (STDOUT_FILENO, "fork", "Could not create child process.");
528     if (pid == 0) { /* child */
529 	close (p0[1]);
530 	close (p1[0]);
531 	close (p2[0]);
532 	dup2 (p0[0], STDIN_FILENO);
533 	dup2 (p1[1], STDOUT_FILENO);
534 	dup2 (p2[1], STDERR_FILENO);
535 	close (p0[0]);
536 	close (p1[1]);
537 	close (p2[1]);
538     } else { /* parent */
539 	close (p0[0]);
540 	close (p1[1]);
541 	close (p2[1]);
542 
543 	if (net_write (STDOUT_FILENO, "", 1) != 1)
544 	    fatal (STDOUT_FILENO, "net_write", "Write failure.");
545 
546 	loop (STDIN_FILENO, p0[1],
547 	      STDOUT_FILENO, p1[0],
548 	      STDERR_FILENO, p2[0]);
549     }
550 }
551 
552 /*
553  * Is `port' a ``reserverd'' port?
554  */
555 
556 static int
557 is_reserved(u_short port)
558 {
559     return ntohs(port) < IPPORT_RESERVED;
560 }
561 
562 /*
563  * Set the necessary part of the environment in `env'.
564  */
565 
566 static void
567 setup_environment (char ***env, const struct passwd *pwd)
568 {
569     int i, j, path;
570     char **e;
571 
572     i = 0;
573     path = 0;
574     *env = NULL;
575 
576     i = read_environment(_PATH_ETC_ENVIRONMENT, env);
577     e = *env;
578     for (j = 0; j < i; j++) {
579 	if (!strncmp(e[j], "PATH=", 5)) {
580 	    path = 1;
581 	}
582     }
583 
584     e = *env;
585     e = realloc(e, (i + 7) * sizeof(char *));
586 
587     asprintf (&e[i++], "USER=%s",  pwd->pw_name);
588     asprintf (&e[i++], "HOME=%s",  pwd->pw_dir);
589     asprintf (&e[i++], "SHELL=%s", pwd->pw_shell);
590     if (! path) {
591 	asprintf (&e[i++], "PATH=%s",  _PATH_DEFPATH);
592     }
593     asprintf (&e[i++], "SSH_CLIENT=only_to_make_bash_happy");
594 #if defined(DCE)
595     if (getenv("KRB5CCNAME"))
596 	asprintf (&e[i++], "KRB5CCNAME=%s",  getenv("KRB5CCNAME"));
597 #else
598     if (do_unique_tkfile)
599 	asprintf (&e[i++], "KRB5CCNAME=%s", tkfile);
600 #endif
601     e[i++] = NULL;
602     *env = e;
603 }
604 
605 static void
606 doit (void)
607 {
608     u_char buf[BUFSIZ];
609     u_char *p;
610     struct sockaddr_storage thisaddr_ss;
611     struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss;
612     struct sockaddr_storage thataddr_ss;
613     struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss;
614     struct sockaddr_storage erraddr_ss;
615     struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss;
616     socklen_t thisaddr_len, thataddr_len;
617     int port;
618     int errsock = -1;
619     char client_user[COMMAND_SZ], server_user[USERNAME_SZ];
620     char cmd[COMMAND_SZ];
621     struct passwd *pwd;
622     int s = STDIN_FILENO;
623     char **env;
624     int ret;
625     char that_host[NI_MAXHOST];
626 
627     thisaddr_len = sizeof(thisaddr_ss);
628     if (getsockname (s, thisaddr, &thisaddr_len) < 0)
629 	syslog_and_die("getsockname: %m");
630     thataddr_len = sizeof(thataddr_ss);
631     if (getpeername (s, thataddr, &thataddr_len) < 0)
632 	syslog_and_die ("getpeername: %m");
633 
634     /* check for V4MAPPED addresses? */
635 
636     if (do_kerberos == 0 && !is_reserved(socket_get_port(thataddr)))
637 	fatal(s, NULL, "Permission denied.");
638 
639     p = buf;
640     port = 0;
641     for(;;) {
642 	if (net_read (s, p, 1) != 1)
643 	    syslog_and_die ("reading port number: %m");
644 	if (*p == '\0')
645 	    break;
646 	else if (isdigit(*p))
647 	    port = port * 10 + *p - '0';
648 	else
649 	    syslog_and_die ("non-digit in port number: %c", *p);
650     }
651 
652     if (do_kerberos  == 0 && !is_reserved(htons(port)))
653 	fatal(s, NULL, "Permission denied.");
654 
655     if (port) {
656 	int priv_port = IPPORT_RESERVED - 1;
657 
658 	/*
659 	 * There's no reason to require a ``privileged'' port number
660 	 * here, but for some reason the brain dead rsh clients
661 	 * do... :-(
662 	 */
663 
664 	erraddr->sa_family = thataddr->sa_family;
665 	socket_set_address_and_port (erraddr,
666 				     socket_get_address (thataddr),
667 				     htons(port));
668 
669 	/*
670 	 * we only do reserved port for IPv4
671 	 */
672 
673 	if (erraddr->sa_family == AF_INET)
674 	    errsock = rresvport (&priv_port);
675 	else
676 	    errsock = socket (erraddr->sa_family, SOCK_STREAM, 0);
677 	if (errsock < 0)
678 	    syslog_and_die ("socket: %m");
679 	if (connect (errsock,
680 		     erraddr,
681 		     socket_sockaddr_size (erraddr)) < 0) {
682 	    syslog (LOG_WARNING, "connect: %m");
683 	    close (errsock);
684 	}
685     }
686 
687     if(do_kerberos) {
688 	if (net_read (s, buf, 4) != 4)
689 	    syslog_and_die ("reading auth info: %m");
690 
691 #ifdef KRB4
692 	if ((do_kerberos & DO_KRB4) &&
693 	    recv_krb4_auth (s, buf, thisaddr, thataddr,
694 			    client_user,
695 			    server_user,
696 			    cmd) == 0)
697 	    auth_method = AUTH_KRB4;
698 	else
699 #endif /* KRB4 */
700 #ifdef KRB5
701 	    if((do_kerberos & DO_KRB5) &&
702 	       recv_krb5_auth (s, buf, thisaddr, thataddr,
703 			       client_user,
704 			       server_user,
705 			       cmd) == 0)
706 		auth_method = AUTH_KRB5;
707 	    else
708 #endif /* KRB5 */
709 		syslog_and_die ("unrecognized auth protocol: %x %x %x %x",
710 				buf[0], buf[1], buf[2], buf[3]);
711     } else {
712 	if(recv_bsd_auth (s, buf,
713 			  (struct sockaddr_in *)thisaddr,
714 			  (struct sockaddr_in *)thataddr,
715 			  client_user,
716 			  server_user,
717 			  cmd) == 0) {
718 	    auth_method = AUTH_BROKEN;
719 	    if(do_vacuous) {
720 		printf("Remote host requires Kerberos authentication\n");
721 		exit(0);
722 	    }
723 	} else
724 	    syslog_and_die("recv_bsd_auth failed");
725     }
726 
727 #if defined(DCE) && defined(_AIX)
728     esetenv("AUTHSTATE", "DCE", 1);
729 #endif
730 
731     pwd = getpwnam (server_user);
732     if (pwd == NULL)
733 	fatal (s, NULL, "Login incorrect.");
734 
735     if (*pwd->pw_shell == '\0')
736 	pwd->pw_shell = _PATH_BSHELL;
737 
738     if (pwd->pw_uid != 0 && access (_PATH_NOLOGIN, F_OK) == 0)
739 	fatal (s, NULL, "Login disabled.");
740 
741 
742     ret = getnameinfo_verified (thataddr, thataddr_len,
743 				that_host, sizeof(that_host),
744 				NULL, 0, 0);
745     if (ret)
746 	fatal (s, NULL, "getnameinfo: %s", gai_strerror(ret));
747 
748     if (login_access(pwd, that_host) == 0) {
749 	syslog(LOG_NOTICE, "Kerberos rsh denied to %s from %s",
750 	       server_user, that_host);
751 	fatal(s, NULL, "Permission denied.");
752     }
753 
754 #ifdef HAVE_GETSPNAM
755     {
756 	struct spwd *sp;
757 	long    today;
758 
759 	sp = getspnam(server_user);
760 	if (sp != NULL) {
761 	    today = time(0)/(24L * 60 * 60);
762 	    if (sp->sp_expire > 0)
763 		if (today > sp->sp_expire)
764 		    fatal(s, NULL, "Account has expired.");
765 	}
766     }
767 #endif
768 
769 
770 #ifdef KRB5
771     {
772 	int fd;
773 
774 	if (!do_unique_tkfile)
775 	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_%u",pwd->pw_uid);
776 	else if (*tkfile=='\0') {
777 	    snprintf(tkfile,sizeof(tkfile),"FILE:/tmp/krb5cc_XXXXXX");
778 	    fd = mkstemp(tkfile+5);
779 	    close(fd);
780 	    unlink(tkfile+5);
781 	}
782 
783 	if (kerberos_status)
784 	    krb5_start_session();
785     }
786     chown(tkfile + 5, pwd->pw_uid, -1);
787 
788 #if defined(DCE)
789     if (kerberos_status) {
790 	esetenv("KRB5CCNAME", tkfile, 1);
791 	dfspag = krb5_dfs_pag(context, kerberos_status, user_ticket->client, server_user);
792     }
793 #endif
794 
795 #endif
796 
797 #ifdef HAVE_SETLOGIN
798     if (setlogin(pwd->pw_name) < 0)
799 	syslog(LOG_ERR, "setlogin() failed: %m");
800 #endif
801 
802 #ifdef HAVE_SETPCRED
803     if (setpcred (pwd->pw_name, NULL) == -1)
804 	syslog(LOG_ERR, "setpcred() failure: %m");
805 #endif /* HAVE_SETPCRED */
806 
807     if (initgroups (pwd->pw_name, pwd->pw_gid) < 0)
808 	fatal (s, "initgroups", "Login incorrect.");
809 
810     if (setgid(pwd->pw_gid) < 0)
811 	fatal (s, "setgid", "Login incorrect.");
812 
813     if (setuid (pwd->pw_uid) < 0)
814 	fatal (s, "setuid", "Login incorrect.");
815 
816     if (chdir (pwd->pw_dir) < 0)
817 	fatal (s, "chdir", "Remote directory.");
818 
819     if (errsock >= 0) {
820 	if (dup2 (errsock, STDERR_FILENO) < 0)
821 	    fatal (s, "dup2", "Cannot dup stderr.");
822 	close (errsock);
823     }
824 
825     setup_environment (&env, pwd);
826 
827     if (do_encrypt) {
828 	setup_copier ();
829     } else {
830 	if (net_write (s, "", 1) != 1)
831 	    fatal (s, "net_write", "write failed");
832     }
833 
834 #ifdef KRB4
835     if(k_hasafs()) {
836 	char cell[64];
837 
838 	if(do_newpag)
839 	    k_setpag();
840 	if (k_afs_cell_of_file (pwd->pw_dir, cell, sizeof(cell)) == 0)
841 	    krb_afslog_uid_home (cell, NULL, pwd->pw_uid, pwd->pw_dir);
842 
843 	krb_afslog_uid_home(NULL, NULL, pwd->pw_uid, pwd->pw_dir);
844 
845 #ifdef KRB5
846 	/* XXX */
847        if (kerberos_status) {
848 	   krb5_ccache ccache;
849 	   krb5_error_code status;
850 
851 	   status = krb5_cc_resolve (context, tkfile, &ccache);
852 	   if (!status) {
853 	       krb5_afslog_uid_home(context,ccache,NULL,NULL,
854 				    pwd->pw_uid, pwd->pw_dir);
855 	       krb5_cc_close (context, ccache);
856 	   }
857        }
858 #endif /* KRB5 */
859     }
860 #endif /* KRB4 */
861     execle (pwd->pw_shell, pwd->pw_shell, "-c", cmd, NULL, env);
862     err(1, "exec %s", pwd->pw_shell);
863 }
864 
865 struct getargs args[] = {
866     { NULL,		'a',	arg_flag,	&do_addr_verify },
867     { "keepalive",	'n',	arg_negative_flag,	&do_keepalive },
868     { "inetd",		'i',	arg_negative_flag,	&do_inetd,
869       "Not started from inetd" },
870 #if defined(KRB4) || defined(KRB5)
871     { "kerberos",	'k',	arg_flag,	&do_kerberos,
872       "Implement kerberised services" },
873     { "encrypt",	'x',	arg_flag,		&do_encrypt,
874       "Implement encrypted service" },
875 #endif
876     { "rhosts",		'l',	arg_negative_flag, &do_rhosts,
877       "Don't check users .rhosts" },
878     { "port",		'p',	arg_string,	&port_str,	"Use this port",
879       "port" },
880     { "vacuous",	'v',	arg_flag, &do_vacuous,
881       "Don't accept non-kerberised connections" },
882 #ifdef KRB4
883     { NULL,		'P',	arg_negative_flag, &do_newpag,
884       "Don't put process in new PAG" },
885 #endif
886     /* compatibility flag: */
887     { NULL,		'L',	arg_flag, &do_log },
888     { "version",	0, 	arg_flag,		&do_version },
889     { "help",		0, 	arg_flag,		&do_help }
890 };
891 
892 static void
893 usage (int ret)
894 {
895     if(isatty(STDIN_FILENO))
896 	arg_printusage (args,
897 			sizeof(args) / sizeof(args[0]),
898 			NULL,
899 			"");
900     else
901 	syslog (LOG_ERR, "Usage: %s [-ikxlvPL] [-p port]", getprogname());
902     exit (ret);
903 }
904 
905 
906 int
907 main(int argc, char **argv)
908 {
909     int optind = 0;
910     int on = 1;
911 
912     setprogname (argv[0]);
913     roken_openlog ("rshd", LOG_ODELAY | LOG_PID, LOG_AUTH);
914 
915     if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv,
916 	       &optind))
917 	usage(1);
918 
919     if(do_help)
920 	usage (0);
921 
922     if (do_version) {
923 	print_version(NULL);
924 	exit(0);
925     }
926 
927 #if defined(KRB4) || defined(KRB5)
928     if (do_encrypt)
929 	do_kerberos = 1;
930 
931     if(do_kerberos)
932 	do_kerberos = DO_KRB4 | DO_KRB5;
933 #endif
934 
935     if (do_keepalive &&
936 	setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
937 		   sizeof(on)) < 0)
938 	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
939 
940     /* set SO_LINGER? */
941 
942 #ifdef KRB5
943     if((do_kerberos & DO_KRB5) && krb5_init_context (&context) != 0)
944 	do_kerberos &= ~DO_KRB5;
945 #endif
946 
947     if (!do_inetd) {
948 	int error;
949 	struct addrinfo *ai = NULL, hints;
950 	char portstr[NI_MAXSERV];
951 
952 	memset (&hints, 0, sizeof(hints));
953 	hints.ai_flags    = AI_PASSIVE;
954 	hints.ai_socktype = SOCK_STREAM;
955 	hints.ai_family   = PF_UNSPEC;
956 
957 	if(port_str != NULL) {
958 	    error = getaddrinfo (NULL, port_str, &hints, &ai);
959 	    if (error)
960 		errx (1, "getaddrinfo: %s", gai_strerror (error));
961 	}
962 	if (ai == NULL) {
963 #if defined(KRB4) || defined(KRB5)
964 	    if (do_kerberos) {
965 		if (do_encrypt) {
966 		    error = getaddrinfo(NULL, "ekshell", &hints, &ai);
967 		    if(error == EAI_NONAME) {
968 			snprintf(portstr, sizeof(portstr), "%d", 545);
969 			error = getaddrinfo(NULL, portstr, &hints, &ai);
970 		    }
971 		    if(error)
972 			errx (1, "getaddrinfo: %s", gai_strerror (error));
973 		} else {
974 		    error = getaddrinfo(NULL, "kshell", &hints, &ai);
975 		    if(error == EAI_NONAME) {
976 			snprintf(portstr, sizeof(portstr), "%d", 544);
977 			error = getaddrinfo(NULL, portstr, &hints, &ai);
978 		    }
979 		    if(error)
980 			errx (1, "getaddrinfo: %s", gai_strerror (error));
981 		}
982 	    } else
983 #endif
984 		{
985 		    error = getaddrinfo(NULL, "shell", &hints, &ai);
986 		    if(error == EAI_NONAME) {
987 			snprintf(portstr, sizeof(portstr), "%d", 514);
988 			error = getaddrinfo(NULL, portstr, &hints, &ai);
989 		    }
990 		    if(error)
991 			errx (1, "getaddrinfo: %s", gai_strerror (error));
992 		}
993 	}
994 	mini_inetd_addrinfo (ai);
995 	freeaddrinfo(ai);
996     }
997 
998     signal (SIGPIPE, SIG_IGN);
999 
1000     doit ();
1001     return 0;
1002 }
1003