2 * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
35 #include "login_locl.h"
39 login_access( struct passwd
*user
, char *from
);
41 read_limits_conf(const char *file
, const struct passwd
*pwd
);
43 #ifdef NEED_IRUSEROK_PROTO
44 int iruserok(uint32_t, int, const char *, const char *);
47 enum auth_method auth_method
;
51 krb5_keyblock
*keyblock
;
56 krb5_ccache ccache
, ccache2
;
57 int kerberos_status
= 0;
62 static int do_unique_tkfile
= 0;
63 static char tkfile
[MAXPATHLEN
] = "";
65 static int do_inetd
= 1;
66 static char *port_str
;
67 static int do_rhosts
= 1;
68 static int do_kerberos
= 0;
70 static int do_vacuous
= 0;
71 static int do_log
= 1;
72 static int do_newpag
= 1;
73 static int do_addr_verify
= 0;
74 static int do_keepalive
= 1;
75 static int do_version
;
76 static int do_help
= 0;
79 syslog_and_die (const char *m
, ...)
80 __attribute__ ((format (printf
, 1, 2)));
83 syslog_and_die (const char *m
, ...)
88 vsyslog (LOG_ERR
, m
, args
);
94 fatal (int, const char*, const char *, ...)
95 __attribute__ ((noreturn
, format (printf
, 3, 4)));
98 fatal (int sock
, const char *what
, const char *m
, ...)
106 len
= vsnprintf (buf
+ 1, sizeof(buf
) - 1, m
, args
);
107 len
= min(len
, sizeof(buf
) - 1);
110 syslog (LOG_ERR
, "%s: %s: %s", what
, strerror(errno
), buf
+ 1);
112 syslog (LOG_ERR
, "%s", buf
+ 1);
113 net_write (sock
, buf
, len
+ 1);
118 read_str (int s
, size_t sz
, char *expl
)
120 char *str
= malloc(sz
);
123 fatal(s
, NULL
, "%s too long", expl
);
124 while(p
< str
+ sz
) {
125 if(net_read(s
, p
, 1) != 1)
126 syslog_and_die("read: %s", strerror(errno
));
131 fatal(s
, NULL
, "%s too long", expl
);
135 recv_bsd_auth (int s
, u_char
*buf
,
136 struct sockaddr_in
*thisaddr
,
137 struct sockaddr_in
*thataddr
,
138 char **client_username
,
139 char **server_username
,
144 *client_username
= read_str (s
, USERNAME_SZ
, "local username");
145 *server_username
= read_str (s
, USERNAME_SZ
, "remote username");
146 *cmd
= read_str (s
, ARG_MAX
+ 1, "command");
147 pwd
= getpwnam(*server_username
);
149 fatal(s
, NULL
, "Login incorrect.");
150 if (iruserok(thataddr
->sin_addr
.s_addr
, pwd
->pw_uid
== 0,
151 *client_username
, *server_username
))
152 fatal(s
, NULL
, "Login incorrect.");
158 save_krb5_creds (int s
,
159 krb5_auth_context auth_context
,
160 krb5_principal client
)
164 krb5_data remote_cred
;
167 krb5_data_zero (&remote_cred
);
168 ret
= krb5_read_message (context
, (void *)&s
, &remote_cred
);
170 krb5_data_free(&remote_cred
);
173 if (remote_cred
.length
== 0)
176 ret
= krb5_cc_new_unique(context
, krb5_cc_type_memory
, NULL
, &ccache
);
178 krb5_data_free(&remote_cred
);
182 krb5_cc_initialize(context
,ccache
,client
);
183 ret
= krb5_rd_cred2(context
, auth_context
, ccache
, &remote_cred
);
185 estr
= krb5_get_error_message(context
, ret
);
186 syslog(LOG_INFO
|LOG_AUTH
, "reading creds: %s", estr
);
187 krb5_free_error_message(context
, estr
);
189 krb5_data_free (&remote_cred
);
196 krb5_start_session (void)
201 ret
= krb5_cc_resolve (context
, tkfile
, &ccache2
);
203 estr
= krb5_get_error_message(context
, ret
);
204 syslog(LOG_WARNING
, "resolve cred cache %s: %s",
206 estr
? estr
: "could not get error string");
207 krb5_free_error_message(context
, estr
);
208 krb5_cc_destroy(context
, ccache
);
212 ret
= krb5_cc_copy_cache (context
, ccache
, ccache2
);
214 estr
= krb5_get_error_message(context
, ret
);
215 syslog(LOG_WARNING
, "storing credentials: %s", estr
);
216 krb5_free_error_message(context
, estr
);
217 krb5_cc_destroy(context
, ccache
);
221 krb5_cc_close(context
, ccache2
);
222 krb5_cc_destroy(context
, ccache
);
226 static int protocol_version
;
229 match_kcmd_version(const void *data
, const char *version
)
231 if(strcmp(version
, KCMD_NEW_VERSION
) == 0) {
232 protocol_version
= 2;
235 if(strcmp(version
, KCMD_OLD_VERSION
) == 0) {
236 protocol_version
= 1;
237 key_usage
= KRB5_KU_OTHER_ENCRYPTED
;
245 recv_krb5_auth (int s
, u_char
*buf
,
246 struct sockaddr
*thisaddr
,
247 struct sockaddr
*thataddr
,
248 char **client_username
,
249 char **server_username
,
253 krb5_auth_context auth_context
= NULL
;
255 krb5_error_code status
;
256 krb5_data cksum_data
;
257 krb5_principal server
;
261 if (memcmp (buf
, "\x00\x00\x00\x13", 4) != 0)
263 len
= (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | (buf
[3]);
265 if (net_read(s
, buf
, len
) != len
)
266 syslog_and_die ("reading auth info: %s", strerror(errno
));
267 if (len
!= sizeof(KRB5_SENDAUTH_VERSION
)
268 || memcmp (buf
, KRB5_SENDAUTH_VERSION
, len
) != 0)
269 syslog_and_die ("bad sendauth version: %.8s", buf
);
271 status
= krb5_sock_to_principal (context
,
277 estr
= krb5_get_error_message(context
, status
);
278 syslog_and_die ("krb5_sock_to_principal: %s", estr
);
279 krb5_free_error_message(context
, estr
);
282 status
= krb5_recvauth_match_version(context
,
288 KRB5_RECVAUTH_IGNORE_VERSION
,
291 krb5_free_principal (context
, server
);
293 estr
= krb5_get_error_message(context
, status
);
294 syslog_and_die ("krb5_recvauth: %s", estr
);
295 krb5_free_error_message(context
, estr
);
298 *server_username
= read_str (s
, USERNAME_SZ
, "remote username");
299 *cmd
= read_str (s
, ARG_MAX
+ 1, "command");
300 *client_username
= read_str (s
, ARG_MAX
+ 1, "local username");
302 if(protocol_version
== 2) {
303 status
= krb5_auth_con_getremotesubkey(context
, auth_context
,
305 if(status
!= 0 || keyblock
== NULL
)
306 syslog_and_die("failed to get remote subkey");
307 } else if(protocol_version
== 1) {
308 status
= krb5_auth_con_getkey (context
, auth_context
, &keyblock
);
309 if(status
!= 0 || keyblock
== NULL
)
310 syslog_and_die("failed to get key");
312 if (status
!= 0 || keyblock
== NULL
) {
313 estr
= krb5_get_error_message(context
, status
);
314 syslog_and_die ("krb5_auth_con_getkey: %s", estr
);
315 krb5_free_error_message(context
, estr
);
318 status
= krb5_crypto_init(context
, keyblock
, 0, &crypto
);
320 estr
= krb5_get_error_message(context
, status
);
321 syslog_and_die("krb5_crypto_init: %s", estr
);
322 krb5_free_error_message(context
, estr
);
326 cksum_data
.length
= asprintf (&str
,
328 ntohs(socket_get_port (thisaddr
)),
332 syslog_and_die ("asprintf: out of memory");
333 cksum_data
.data
= str
;
335 status
= krb5_verify_authenticator_checksum(context
,
341 estr
= krb5_get_error_message(context
, status
);
342 syslog_and_die ("krb5_verify_authenticator_checksum: %s", estr
);
343 krb5_free_error_message(context
, estr
);
346 free (cksum_data
.data
);
348 if (strncmp (*client_username
, "-u ", 3) == 0) {
349 do_unique_tkfile
= 1;
350 memmove (*client_username
, *client_username
+ 3,
351 strlen(*client_username
) - 2);
354 if (strncmp (*client_username
, "-U ", 3) == 0) {
355 char *end
, *temp_tkfile
;
357 do_unique_tkfile
= 1;
358 if (strncmp (*client_username
+ 3, "FILE:", 5) == 0) {
359 temp_tkfile
= tkfile
;
361 strlcpy (tkfile
, "FILE:", sizeof(tkfile
));
362 temp_tkfile
= tkfile
+ 5;
364 end
= strchr(*client_username
+ 3,' ');
366 syslog_and_die("missing argument after -U");
367 snprintf(temp_tkfile
, sizeof(tkfile
) - (temp_tkfile
- tkfile
),
369 (int)(end
- *client_username
- 3),
370 *client_username
+ 3);
371 memmove (*client_username
, end
+ 1, strlen(end
+1)+1);
374 kerberos_status
= save_krb5_creds (s
, auth_context
, ticket
->client
);
376 if(!krb5_kuserok (context
,
379 fatal (s
, NULL
, "Permission denied.");
381 if (strncmp (*cmd
, "-x ", 3) == 0) {
383 memmove (*cmd
, *cmd
+ 3, strlen(*cmd
) - 2);
386 fatal (s
, NULL
, "Encryption is required.");
393 if (krb5_unparse_name (context
, ticket
->client
, &name
) == 0) {
396 if (inet_ntop (thataddr
->sa_family
,
397 socket_get_address (thataddr
),
398 addr_str
, sizeof(addr_str
)) == NULL
)
399 strlcpy (addr_str
, "unknown address",
402 syslog(LOG_INFO
|LOG_AUTH
,
403 "kerberos v5 shell from %s on %s as %s, cmd '%.80s'",
412 krb5_auth_con_free(context
, auth_context
);
419 rshd_loop (int from0
, int to0
,
429 if(from0
>= FD_SETSIZE
|| from1
>= FD_SETSIZE
|| from2
>= FD_SETSIZE
)
430 errx (1, "fd too large");
433 if(auth_method
== AUTH_KRB5
&& protocol_version
== 2)
434 init_ivecs(0, have_errsock
);
437 FD_ZERO(&real_readset
);
438 FD_SET(from0
, &real_readset
);
439 FD_SET(from1
, &real_readset
);
440 FD_SET(from2
, &real_readset
);
441 max_fd
= max(from0
, max(from1
, from2
)) + 1;
443 buf
= malloc(max(RSHD_BUFSIZ
, RSH_BUFSIZ
));
445 syslog_and_die("out of memory");
449 fd_set readset
= real_readset
;
451 ret
= select (max_fd
, &readset
, NULL
, NULL
, NULL
);
456 syslog_and_die ("select: %s", strerror(errno
));
458 if (FD_ISSET(from0
, &readset
)) {
459 ret
= do_read (from0
, buf
, RSHD_BUFSIZ
, ivec_in
[0]);
461 syslog_and_die ("read: %s", strerror(errno
));
465 FD_CLR(from0
, &real_readset
);
467 net_write (to0
, buf
, ret
);
469 if (FD_ISSET(from1
, &readset
)) {
470 ret
= read (from1
, buf
, RSH_BUFSIZ
);
472 syslog_and_die ("read: %s", strerror(errno
));
476 FD_CLR(from1
, &real_readset
);
480 do_write (to1
, buf
, ret
, ivec_out
[0]);
482 if (FD_ISSET(from2
, &readset
)) {
483 ret
= read (from2
, buf
, RSH_BUFSIZ
);
485 syslog_and_die ("read: %s", strerror(errno
));
489 FD_CLR(from2
, &real_readset
);
493 do_write (to2
, buf
, ret
, ivec_out
[1]);
499 * Used by `setup_copier' to create some pipe-like means of
500 * communcation. Real pipes would probably be the best thing, but
501 * then the shell doesn't understand it's talking to rshd. If
502 * socketpair doesn't work everywhere, some autoconf magic would have
505 * If it fails creating the `pipe', it aborts by calling fatal.
509 pipe_a_like (int fd
[2])
511 if (socketpair (AF_UNIX
, SOCK_STREAM
, 0, fd
) < 0)
512 fatal (STDOUT_FILENO
, "socketpair", "Pipe creation failed.");
516 * Start a child process and leave the parent copying data to and from it. */
519 setup_copier (int have_errsock
)
521 int p0
[2], p1
[2], p2
[2];
529 fatal (STDOUT_FILENO
, "fork", "Could not create child process.");
530 if (pid
== 0) { /* child */
534 dup2 (p0
[0], STDIN_FILENO
);
535 dup2 (p1
[1], STDOUT_FILENO
);
536 dup2 (p2
[1], STDERR_FILENO
);
540 } else { /* parent */
545 if (net_write (STDOUT_FILENO
, "", 1) != 1)
546 fatal (STDOUT_FILENO
, "net_write", "Write failure.");
548 rshd_loop (STDIN_FILENO
, p0
[1],
549 STDOUT_FILENO
, p1
[0],
550 STDERR_FILENO
, p2
[0],
556 * Is `port' a ``reserverd'' port?
560 is_reserved(u_short port
)
562 return ntohs(port
) < IPPORT_RESERVED
;
566 * Set the necessary part of the environment in `env'.
570 setup_environment (char ***env
, const struct passwd
*pwd
)
579 i
= read_environment(_PATH_ETC_ENVIRONMENT
, env
);
581 for (j
= 0; j
< i
; j
++) {
582 if (!strncmp(e
[j
], "PATH=", 5)) {
588 e
= realloc(e
, (i
+ 7) * sizeof(char *));
590 if (asprintf (&e
[i
++], "USER=%s", pwd
->pw_name
) == -1)
591 syslog_and_die ("asprintf: out of memory");
592 if (asprintf (&e
[i
++], "HOME=%s", pwd
->pw_dir
) == -1)
593 syslog_and_die ("asprintf: out of memory");
594 if (asprintf (&e
[i
++], "SHELL=%s", pwd
->pw_shell
) == -1)
595 syslog_and_die ("asprintf: out of memory");
597 if (asprintf (&e
[i
++], "PATH=%s", _PATH_DEFPATH
) == -1)
598 syslog_and_die ("asprintf: out of memory");
600 asprintf (&e
[i
++], "SSH_CLIENT=only_to_make_bash_happy");
601 if (do_unique_tkfile
)
602 if (asprintf (&e
[i
++], "KRB5CCNAME=%s", tkfile
) == -1)
603 syslog_and_die ("asprintf: out of memory");
613 struct sockaddr_storage thisaddr_ss
;
614 struct sockaddr
*thisaddr
= (struct sockaddr
*)&thisaddr_ss
;
615 struct sockaddr_storage thataddr_ss
;
616 struct sockaddr
*thataddr
= (struct sockaddr
*)&thataddr_ss
;
617 struct sockaddr_storage erraddr_ss
;
618 struct sockaddr
*erraddr
= (struct sockaddr
*)&erraddr_ss
;
619 socklen_t thisaddr_len
, thataddr_len
;
622 char *client_user
= NULL
, *server_user
= NULL
, *cmd
= NULL
;
624 int s
= STDIN_FILENO
;
627 char that_host
[NI_MAXHOST
];
629 thisaddr_len
= sizeof(thisaddr_ss
);
630 if (getsockname (s
, thisaddr
, &thisaddr_len
) < 0)
631 syslog_and_die("getsockname: %s", strerror(errno
));
632 thataddr_len
= sizeof(thataddr_ss
);
633 if (getpeername (s
, thataddr
, &thataddr_len
) < 0)
634 syslog_and_die ("getpeername: %s", strerror(errno
));
636 /* check for V4MAPPED addresses? */
638 if (do_kerberos
== 0 && !is_reserved(socket_get_port(thataddr
)))
639 fatal(s
, NULL
, "Permission denied.");
644 if (net_read (s
, p
, 1) != 1)
645 syslog_and_die ("reading port number: %s", strerror(errno
));
648 else if (isdigit(*p
))
649 port
= port
* 10 + *p
- '0';
651 syslog_and_die ("non-digit in port number: %c", *p
);
654 if (do_kerberos
== 0 && !is_reserved(htons(port
)))
655 fatal(s
, NULL
, "Permission denied.");
658 int priv_port
= IPPORT_RESERVED
- 1;
661 * There's no reason to require a ``privileged'' port number
662 * here, but for some reason the brain dead rsh clients
666 erraddr
->sa_family
= thataddr
->sa_family
;
667 socket_set_address_and_port (erraddr
,
668 socket_get_address (thataddr
),
672 * we only do reserved port for IPv4
675 if (erraddr
->sa_family
== AF_INET
)
676 errsock
= rresvport (&priv_port
);
678 errsock
= socket (erraddr
->sa_family
, SOCK_STREAM
, 0);
680 syslog_and_die ("socket: %s", strerror(errno
));
681 if (connect (errsock
,
683 socket_sockaddr_size (erraddr
)) < 0) {
684 syslog (LOG_WARNING
, "connect: %s", strerror(errno
));
690 if (net_read (s
, buf
, 4) != 4)
691 syslog_and_die ("reading auth info: %s", strerror(errno
));
694 if((do_kerberos
& DO_KRB5
) &&
695 recv_krb5_auth (s
, buf
, thisaddr
, thataddr
,
699 auth_method
= AUTH_KRB5
;
702 syslog_and_die ("unrecognized auth protocol: %x %x %x %x",
703 buf
[0], buf
[1], buf
[2], buf
[3]);
705 if(recv_bsd_auth (s
, buf
,
706 (struct sockaddr_in
*)thisaddr
,
707 (struct sockaddr_in
*)thataddr
,
711 auth_method
= AUTH_BROKEN
;
713 printf("Remote host requires Kerberos authentication\n");
717 syslog_and_die("recv_bsd_auth failed");
720 if (client_user
== NULL
|| server_user
== NULL
|| cmd
== NULL
)
721 syslog_and_die("mising client/server/cmd");
723 pwd
= getpwnam (server_user
);
725 fatal (s
, NULL
, "Login incorrect.");
727 if (*pwd
->pw_shell
== '\0')
728 pwd
->pw_shell
= _PATH_BSHELL
;
730 if (pwd
->pw_uid
!= 0 && access (_PATH_NOLOGIN
, F_OK
) == 0)
731 fatal (s
, NULL
, "Login disabled.");
734 ret
= getnameinfo_verified (thataddr
, thataddr_len
,
735 that_host
, sizeof(that_host
),
738 fatal (s
, NULL
, "getnameinfo: %s", gai_strerror(ret
));
740 if (login_access(pwd
, that_host
) == 0) {
741 syslog(LOG_NOTICE
, "Kerberos rsh denied to %s from %s",
742 server_user
, that_host
);
743 fatal(s
, NULL
, "Permission denied.");
751 sp
= getspnam(server_user
);
753 today
= time(0)/(24L * 60 * 60);
754 if (sp
->sp_expire
> 0)
755 if (today
> sp
->sp_expire
)
756 fatal(s
, NULL
, "Account has expired.");
763 if (setlogin(pwd
->pw_name
) < 0)
764 syslog(LOG_ERR
, "setlogin() failed: %s", strerror(errno
));
768 if (setpcred (pwd
->pw_name
, NULL
) == -1)
769 syslog(LOG_ERR
, "setpcred() failure: %s", strerror(errno
));
770 #endif /* HAVE_SETPCRED */
772 /* Apply limits if not root */
773 if(pwd
->pw_uid
!= 0) {
774 const char *file
= _PATH_LIMITS_CONF
;
775 read_limits_conf(file
, pwd
);
778 if (initgroups (pwd
->pw_name
, pwd
->pw_gid
) < 0)
779 fatal (s
, "initgroups", "Login incorrect.");
781 if (setgid(pwd
->pw_gid
) < 0)
782 fatal (s
, "setgid", "Login incorrect.");
784 if (setuid (pwd
->pw_uid
) < 0)
785 fatal (s
, "setuid", "Login incorrect.");
787 if (chdir (pwd
->pw_dir
) < 0)
788 fatal (s
, "chdir", "Remote directory.");
791 if (dup2 (errsock
, STDERR_FILENO
) < 0)
792 fatal (s
, "dup2", "Cannot dup stderr.");
795 if (dup2 (STDOUT_FILENO
, STDERR_FILENO
) < 0)
796 fatal (s
, "dup2", "Cannot dup stderr.");
803 if (!do_unique_tkfile
)
804 snprintf(tkfile
,sizeof(tkfile
),"FILE:/tmp/krb5cc_%lu",
805 (unsigned long)pwd
->pw_uid
);
806 else if (*tkfile
=='\0') {
807 snprintf(tkfile
,sizeof(tkfile
),"FILE:/tmp/krb5cc_XXXXXX");
808 fd
= mkstemp(tkfile
+5);
814 krb5_start_session();
818 setup_environment (&env
, pwd
);
821 setup_copier (errsock
>= 0);
823 if (net_write (s
, "", 1) != 1)
824 fatal (s
, "net_write", "write failed");
835 if (kerberos_status
) {
837 krb5_error_code status
;
839 status
= krb5_cc_resolve (context
, tkfile
, &ccache
);
841 if (k_afs_cell_of_file (pwd
->pw_dir
, cell
, sizeof(cell
)) == 0)
842 krb5_afslog_uid_home(context
, ccache
, cell
, NULL
,
843 pwd
->pw_uid
, pwd
->pw_dir
);
844 krb5_afslog_uid_home(context
, ccache
, NULL
, NULL
,
845 pwd
->pw_uid
, pwd
->pw_dir
);
846 krb5_cc_close (context
, ccache
);
851 execle (pwd
->pw_shell
, pwd
->pw_shell
, "-c", cmd
, NULL
, env
);
852 err(1, "exec %s", pwd
->pw_shell
);
855 struct getargs args
[] = {
856 { NULL
, 'a', arg_flag
, &do_addr_verify
},
857 { "keepalive", 'n', arg_negative_flag
, &do_keepalive
},
858 { "inetd", 'i', arg_negative_flag
, &do_inetd
,
859 "Not started from inetd" },
861 { "kerberos", 'k', arg_flag
, &do_kerberos
,
862 "Implement kerberised services" },
863 { "encrypt", 'x', arg_flag
, &do_encrypt
,
864 "Implement encrypted service" },
866 { "rhosts", 'l', arg_negative_flag
, &do_rhosts
,
867 "Don't check users .rhosts" },
868 { "port", 'p', arg_string
, &port_str
, "Use this port",
870 { "vacuous", 'v', arg_flag
, &do_vacuous
,
871 "Don't accept non-kerberised connections" },
873 { NULL
, 'P', arg_negative_flag
, &do_newpag
,
874 "Don't put process in new PAG" },
876 /* compatibility flag: */
877 { NULL
, 'L', arg_flag
, &do_log
},
878 { "version", 0, arg_flag
, &do_version
},
879 { "help", 0, arg_flag
, &do_help
}
885 if(isatty(STDIN_FILENO
))
886 arg_printusage (args
,
887 sizeof(args
) / sizeof(args
[0]),
891 syslog (LOG_ERR
, "Usage: %s [-ikxlvPL] [-p port]", getprogname());
897 main(int argc
, char **argv
)
902 setprogname (argv
[0]);
903 roken_openlog ("rshd", LOG_ODELAY
| LOG_PID
, LOG_AUTH
);
905 if (getarg(args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
,
922 do_kerberos
= DO_KRB5
;
926 if((do_kerberos
& DO_KRB5
) && krb5_init_context (&context
) != 0)
927 do_kerberos
&= ~DO_KRB5
;
932 struct addrinfo
*ai
= NULL
, hints
;
933 char portstr
[NI_MAXSERV
];
935 memset (&hints
, 0, sizeof(hints
));
936 hints
.ai_flags
= AI_PASSIVE
;
937 hints
.ai_socktype
= SOCK_STREAM
;
938 hints
.ai_family
= PF_UNSPEC
;
940 if(port_str
!= NULL
) {
941 error
= getaddrinfo (NULL
, port_str
, &hints
, &ai
);
943 errx (1, "getaddrinfo: %s", gai_strerror (error
));
949 error
= getaddrinfo(NULL
, "ekshell", &hints
, &ai
);
950 if(error
== EAI_NONAME
) {
951 snprintf(portstr
, sizeof(portstr
), "%d", 545);
952 error
= getaddrinfo(NULL
, portstr
, &hints
, &ai
);
955 errx (1, "getaddrinfo: %s", gai_strerror (error
));
957 error
= getaddrinfo(NULL
, "kshell", &hints
, &ai
);
958 if(error
== EAI_NONAME
) {
959 snprintf(portstr
, sizeof(portstr
), "%d", 544);
960 error
= getaddrinfo(NULL
, portstr
, &hints
, &ai
);
963 errx (1, "getaddrinfo: %s", gai_strerror (error
));
968 error
= getaddrinfo(NULL
, "shell", &hints
, &ai
);
969 if(error
== EAI_NONAME
) {
970 snprintf(portstr
, sizeof(portstr
), "%d", 514);
971 error
= getaddrinfo(NULL
, portstr
, &hints
, &ai
);
974 errx (1, "getaddrinfo: %s", gai_strerror (error
));
977 mini_inetd_addrinfo (ai
, NULL
);
982 setsockopt(0, SOL_SOCKET
, SO_KEEPALIVE
, (char *)&on
,
984 syslog(LOG_WARNING
, "setsockopt (SO_KEEPALIVE): %s", strerror(errno
));
988 signal (SIGPIPE
, SIG_IGN
);