*** empty log message ***
[heimdal.git] / appl / rsh / rsh.c
blobd350b088c280df8ab5cc581ebabcd0ace909d1da
1 /*
2 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include "rsh_locl.h"
35 RCSID("$Id$");
37 enum auth_method auth_method;
38 int do_encrypt;
39 int do_forward;
40 int do_forwardable;
41 int do_unique_tkfile = 0;
42 char *unique_tkfile = NULL;
43 char tkfile[MAXPATHLEN];
44 krb5_context context;
45 krb5_keyblock *keyblock;
46 krb5_crypto crypto;
47 des_key_schedule schedule;
48 des_cblock iv;
55 static int input = 1; /* Read from stdin */
57 static int
58 loop (int s, int errsock)
60 fd_set real_readset;
61 int count = 1;
63 FD_ZERO(&real_readset);
64 FD_SET(s, &real_readset);
65 if (errsock != -1) {
66 FD_SET(errsock, &real_readset);
67 ++count;
69 if(input)
70 FD_SET(STDIN_FILENO, &real_readset);
72 for (;;) {
73 int ret;
74 fd_set readset;
75 char buf[RSH_BUFSIZ];
77 readset = real_readset;
78 ret = select (max(s, errsock) + 1, &readset, NULL, NULL, NULL);
79 if (ret < 0) {
80 if (errno == EINTR)
81 continue;
82 else
83 err (1, "select");
85 if (FD_ISSET(s, &readset)) {
86 ret = do_read (s, buf, sizeof(buf));
87 if (ret < 0)
88 err (1, "read");
89 else if (ret == 0) {
90 close (s);
91 FD_CLR(s, &real_readset);
92 if (--count == 0)
93 return 0;
94 } else
95 net_write (STDOUT_FILENO, buf, ret);
97 if (errsock != -1 && FD_ISSET(errsock, &readset)) {
98 ret = do_read (errsock, buf, sizeof(buf));
99 if (ret < 0)
100 err (1, "read");
101 else if (ret == 0) {
102 close (errsock);
103 FD_CLR(errsock, &real_readset);
104 if (--count == 0)
105 return 0;
106 } else
107 net_write (STDERR_FILENO, buf, ret);
109 if (FD_ISSET(STDIN_FILENO, &readset)) {
110 ret = read (STDIN_FILENO, buf, sizeof(buf));
111 if (ret < 0)
112 err (1, "read");
113 else if (ret == 0) {
114 close (STDIN_FILENO);
115 FD_CLR(STDIN_FILENO, &real_readset);
116 shutdown (s, SHUT_WR);
117 } else
118 do_write (s, buf, ret);
123 #ifdef KRB4
124 static int
125 send_krb4_auth(int s,
126 struct sockaddr *thisaddr,
127 struct sockaddr *thataddr,
128 const char *hostname,
129 const char *remote_user,
130 const char *local_user,
131 size_t cmd_len,
132 const char *cmd)
134 KTEXT_ST text;
135 CREDENTIALS cred;
136 MSG_DAT msg;
137 int status;
138 size_t len;
140 status = krb_sendauth (do_encrypt ? KOPT_DO_MUTUAL : 0,
141 s, &text, "rcmd",
142 (char *)hostname, krb_realmofhost (hostname),
143 getpid(), &msg, &cred, schedule,
144 (struct sockaddr_in *)thisaddr,
145 (struct sockaddr_in *)thataddr,
146 KCMD_VERSION);
147 if (status != KSUCCESS) {
148 warnx ("%s: %s", hostname, krb_get_err_text(status));
149 return 1;
151 memcpy (iv, cred.session, sizeof(iv));
153 len = strlen(remote_user) + 1;
154 if (net_write (s, remote_user, len) != len) {
155 warn("write");
156 return 1;
158 if (net_write (s, cmd, cmd_len) != cmd_len) {
159 warn("write");
160 return 1;
162 return 0;
164 #endif /* KRB4 */
167 * Send forward information on `s' for host `hostname', them being
168 * forwardable themselves if `forwardable'
171 static int
172 krb5_forward_cred (krb5_auth_context auth_context,
173 int s,
174 const char *hostname,
175 int forwardable)
177 krb5_error_code ret;
178 krb5_ccache ccache;
179 krb5_creds creds;
180 krb5_kdc_flags flags;
181 krb5_data out_data;
182 krb5_principal principal;
184 memset (&creds, 0, sizeof(creds));
186 ret = krb5_cc_default (context, &ccache);
187 if (ret) {
188 warnx ("could not forward creds: krb5_cc_default: %s",
189 krb5_get_err_text (context, ret));
190 return 1;
193 ret = krb5_cc_get_principal (context, ccache, &principal);
194 if (ret) {
195 warnx ("could not forward creds: krb5_cc_get_principal: %s",
196 krb5_get_err_text (context, ret));
197 return 1;
200 creds.client = principal;
202 ret = krb5_build_principal (context,
203 &creds.server,
204 strlen(principal->realm),
205 principal->realm,
206 "krbtgt",
207 principal->realm,
208 NULL);
210 if (ret) {
211 warnx ("could not forward creds: krb5_build_principal: %s",
212 krb5_get_err_text (context, ret));
213 return 1;
216 creds.times.endtime = 0;
218 flags.i = 0;
219 flags.b.forwarded = 1;
220 flags.b.forwardable = forwardable;
222 ret = krb5_get_forwarded_creds (context,
223 auth_context,
224 ccache,
225 flags.i,
226 hostname,
227 &creds,
228 &out_data);
229 if (ret) {
230 warnx ("could not forward creds: krb5_get_forwarded_creds: %s",
231 krb5_get_err_text (context, ret));
232 return 1;
235 ret = krb5_write_message (context,
236 (void *)&s,
237 &out_data);
238 krb5_data_free (&out_data);
240 if (ret)
241 warnx ("could not forward creds: krb5_write_message: %s",
242 krb5_get_err_text (context, ret));
243 return 0;
246 static int
247 send_krb5_auth(int s,
248 struct sockaddr *thisaddr,
249 struct sockaddr *thataddr,
250 const char *hostname,
251 const char *remote_user,
252 const char *local_user,
253 size_t cmd_len,
254 const char *cmd)
256 krb5_principal server;
257 krb5_data cksum_data;
258 int status;
259 size_t len;
260 krb5_auth_context auth_context = NULL;
262 status = krb5_sname_to_principal(context,
263 hostname,
264 "host",
265 KRB5_NT_SRV_HST,
266 &server);
267 if (status) {
268 warnx ("%s: %s", hostname, krb5_get_err_text(context, status));
269 return 1;
272 cksum_data.length = asprintf ((char **)&cksum_data.data,
273 "%u:%s%s%s",
274 ntohs(socket_get_port(thataddr)),
275 do_encrypt ? "-x " : "",
276 cmd,
277 remote_user);
279 status = krb5_sendauth (context,
280 &auth_context,
282 KCMD_VERSION,
283 NULL,
284 server,
285 do_encrypt ? AP_OPTS_MUTUAL_REQUIRED : 0,
286 &cksum_data,
287 NULL,
288 NULL,
289 NULL,
290 NULL,
291 NULL);
292 if (status) {
293 warnx ("%s: %s", hostname, krb5_get_err_text(context, status));
294 return 1;
297 status = krb5_auth_con_getkey (context, auth_context, &keyblock);
298 if (status) {
299 warnx ("krb5_auth_con_getkey: %s", krb5_get_err_text(context, status));
300 return 1;
303 status = krb5_auth_con_setaddrs_from_fd (context,
304 auth_context,
305 &s);
306 if (status) {
307 warnx("krb5_auth_con_setaddrs_from_fd: %s",
308 krb5_get_err_text(context, status));
309 return(1);
312 status = krb5_crypto_init(context, keyblock, 0, &crypto);
313 if(status) {
314 warnx ("krb5_crypto_init: %s", krb5_get_err_text(context, status));
315 return 1;
318 len = strlen(remote_user) + 1;
319 if (net_write (s, remote_user, len) != len) {
320 warn ("write");
321 return 1;
323 if (do_encrypt && net_write (s, "-x ", 3) != 3) {
324 warn ("write");
325 return 1;
327 if (net_write (s, cmd, cmd_len) != cmd_len) {
328 warn ("write");
329 return 1;
332 if (do_unique_tkfile) {
333 if (net_write (s, tkfile, strlen(tkfile)) != strlen(tkfile)) {
334 warn ("write");
335 return 1;
338 len = strlen(local_user) + 1;
339 if (net_write (s, local_user, len) != len) {
340 warn ("write");
341 return 1;
344 if (!do_forward
345 || krb5_forward_cred (auth_context, s, hostname, do_forwardable)) {
346 /* Empty forwarding info */
348 u_char zero[4] = {0, 0, 0, 0};
349 write (s, &zero, 4);
351 krb5_auth_con_free (context, auth_context);
352 return 0;
355 static int
356 send_broken_auth(int s,
357 struct sockaddr *thisaddr,
358 struct sockaddr *thataddr,
359 const char *hostname,
360 const char *remote_user,
361 const char *local_user,
362 size_t cmd_len,
363 const char *cmd)
365 size_t len;
367 len = strlen(local_user) + 1;
368 if (net_write (s, local_user, len) != len) {
369 warn ("write");
370 return 1;
372 len = strlen(remote_user) + 1;
373 if (net_write (s, remote_user, len) != len) {
374 warn ("write");
375 return 1;
377 if (net_write (s, cmd, cmd_len) != cmd_len) {
378 warn ("write");
379 return 1;
381 return 0;
384 static int
385 proto (int s, int errsock,
386 const char *hostname, const char *local_user, const char *remote_user,
387 const char *cmd, size_t cmd_len,
388 int (*auth_func)(int s,
389 struct sockaddr *this, struct sockaddr *that,
390 const char *hostname, const char *remote_user,
391 const char *local_user, size_t cmd_len,
392 const char *cmd))
394 int errsock2;
395 char buf[BUFSIZ];
396 char *p;
397 size_t len;
398 char reply;
399 struct sockaddr_storage thisaddr_ss;
400 struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss;
401 struct sockaddr_storage thataddr_ss;
402 struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss;
403 struct sockaddr_storage erraddr_ss;
404 struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss;
405 int addrlen;
406 int ret;
408 addrlen = sizeof(thisaddr_ss);
409 if (getsockname (s, thisaddr, &addrlen) < 0) {
410 warn ("getsockname(%s)", hostname);
411 return 1;
413 addrlen = sizeof(thataddr_ss);
414 if (getpeername (s, thataddr, &addrlen) < 0) {
415 warn ("getpeername(%s)", hostname);
416 return 1;
419 if (errsock != -1) {
421 addrlen = sizeof(erraddr_ss);
422 if (getsockname (errsock, erraddr, &addrlen) < 0) {
423 warn ("getsockname");
424 return 1;
427 if (listen (errsock, 1) < 0) {
428 warn ("listen");
429 return 1;
432 p = buf;
433 snprintf (p, sizeof(buf), "%u",
434 ntohs(socket_get_port(erraddr)));
435 len = strlen(buf) + 1;
436 if(net_write (s, buf, len) != len) {
437 warn ("write");
438 close (errsock);
439 return 1;
442 errsock2 = accept (errsock, NULL, NULL);
443 if (errsock2 < 0) {
444 warn ("accept");
445 close (errsock);
446 return 1;
448 close (errsock);
450 } else {
451 if (net_write (s, "0", 2) != 2) {
452 warn ("write");
453 return 1;
455 errsock2 = -1;
458 if ((*auth_func)(s, thisaddr, thataddr, hostname,
459 remote_user, local_user,
460 cmd_len, cmd)) {
461 close (errsock2);
462 return 1;
465 ret = net_read (s, &reply, 1);
466 if (ret < 0) {
467 warn ("read");
468 close (errsock2);
469 return 1;
470 } else if (ret == 0) {
471 warnx ("unexpected EOF from %s", hostname);
472 close (errsock2);
473 return 1;
475 if (reply != 0) {
477 warnx ("Error from rshd at %s:", hostname);
479 while ((ret = read (s, buf, sizeof(buf))) > 0)
480 write (STDOUT_FILENO, buf, ret);
481 write (STDOUT_FILENO,"\n",1);
482 close (errsock2);
483 return 1;
486 return loop (s, errsock2);
490 * Return in `res' a copy of the concatenation of `argc, argv' into
491 * malloced space.
494 static size_t
495 construct_command (char **res, int argc, char **argv)
497 int i;
498 size_t len = 0;
499 char *tmp;
501 for (i = 0; i < argc; ++i)
502 len += strlen(argv[i]) + 1;
503 len = max (1, len);
504 tmp = malloc (len);
505 if (tmp == NULL)
506 errx (1, "malloc %u failed", len);
508 *tmp = '\0';
509 for (i = 0; i < argc - 1; ++i) {
510 strcat (tmp, argv[i]);
511 strcat (tmp, " ");
513 if (argc > 0)
514 strcat (tmp, argv[argc-1]);
515 *res = tmp;
516 return len;
519 static char *
520 print_addr (const struct sockaddr_in *sin)
522 char addr_str[256];
523 char *res;
525 inet_ntop (AF_INET, &sin->sin_addr, addr_str, sizeof(addr_str));
526 res = strdup(addr_str);
527 if (res == NULL)
528 errx (1, "malloc: out of memory");
529 return res;
532 static int
533 doit_broken (int argc,
534 char **argv,
535 int optind,
536 const char *host,
537 const char *remote_user,
538 const char *local_user,
539 int port,
540 int priv_socket1,
541 int priv_socket2,
542 const char *cmd,
543 size_t cmd_len)
545 struct addrinfo *ai, *a;
546 struct addrinfo hints;
547 int error;
548 char portstr[NI_MAXSERV];
550 if (priv_socket1 < 0) {
551 warnx ("unable to bind reserved port: is rsh setuid root?");
552 return 1;
555 memset (&hints, 0, sizeof(hints));
556 hints.ai_socktype = SOCK_STREAM;
557 hints.ai_protocol = IPPROTO_TCP;
558 hints.ai_family = AF_INET;
560 snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
562 error = getaddrinfo (host, portstr, &hints, &ai);
563 if (error) {
564 warnx ("%s: %s", host, gai_strerror(error));
565 return 1;
568 if (connect (priv_socket1, ai->ai_addr, ai->ai_addrlen) < 0) {
569 if (ai->ai_next == NULL) {
570 freeaddrinfo (ai);
571 return 1;
574 close(priv_socket1);
575 close(priv_socket2);
577 for (a = ai->ai_next; a != NULL; a = a->ai_next) {
578 pid_t pid;
580 pid = fork();
581 if (pid < 0)
582 err (1, "fork");
583 else if(pid == 0) {
584 char **new_argv;
585 int i = 0;
586 struct sockaddr_in *sin = (struct sockaddr_in *)a->ai_addr;
588 new_argv = malloc((argc + 2) * sizeof(*new_argv));
589 if (new_argv == NULL)
590 errx (1, "malloc: out of memory");
591 new_argv[i] = argv[i];
592 ++i;
593 if (optind == i)
594 new_argv[i++] = print_addr (sin);
595 new_argv[i++] = "-K";
596 for(; i <= argc; ++i)
597 new_argv[i] = argv[i - 1];
598 if (optind > 1)
599 new_argv[optind + 1] = print_addr(sin);
600 new_argv[argc + 1] = NULL;
601 execv(PATH_RSH, new_argv);
602 err(1, "execv(%s)", PATH_RSH);
603 } else {
604 int status;
606 freeaddrinfo (ai);
608 while(waitpid(pid, &status, 0) < 0)
610 if(WIFEXITED(status) && WEXITSTATUS(status) == 0)
611 return 0;
614 return 1;
615 } else {
616 int ret;
618 freeaddrinfo (ai);
620 ret = proto (priv_socket1, priv_socket2,
621 argv[optind],
622 local_user, remote_user,
623 cmd, cmd_len,
624 send_broken_auth);
625 return ret;
629 static int
630 doit (const char *hostname,
631 const char *remote_user,
632 const char *local_user,
633 int port,
634 const char *cmd,
635 size_t cmd_len,
636 int do_errsock,
637 int (*auth_func)(int s,
638 struct sockaddr *this, struct sockaddr *that,
639 const char *hostname, const char *remote_user,
640 const char *local_user, size_t cmd_len,
641 const char *cmd))
643 struct addrinfo *ai, *a;
644 struct addrinfo hints;
645 int error;
646 char portstr[NI_MAXSERV];
647 int ret;
649 memset (&hints, 0, sizeof(hints));
650 hints.ai_socktype = SOCK_STREAM;
651 hints.ai_protocol = IPPROTO_TCP;
653 snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
655 error = getaddrinfo (hostname, portstr, &hints, &ai);
656 if (error) {
657 errx (1, "%s: %s", hostname, gai_strerror(error));
658 return -1;
661 for (a = ai; a != NULL; a = a->ai_next) {
662 int s;
663 int errsock;
665 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
666 if (s < 0)
667 continue;
668 if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
669 warn ("connect(%s)", hostname);
670 close (s);
671 continue;
673 if (do_errsock) {
674 struct addrinfo *ea;
675 struct addrinfo hints;
677 memset (&hints, 0, sizeof(hints));
678 hints.ai_socktype = a->ai_socktype;
679 hints.ai_protocol = a->ai_protocol;
680 hints.ai_family = a->ai_family;
681 hints.ai_flags = AI_PASSIVE;
683 error = getaddrinfo (NULL, "0", &hints, &ea);
684 if (error)
685 errx (1, "getaddrinfo: %s", gai_strerror(error));
686 errsock = socket (ea->ai_family, ea->ai_socktype, ea->ai_protocol);
687 if (errsock < 0)
688 err (1, "socket");
689 if (bind (errsock, ea->ai_addr, ea->ai_addrlen) < 0)
690 err (1, "bind");
691 freeaddrinfo (ea);
692 } else
693 errsock = -1;
695 freeaddrinfo (ai);
696 ret = proto (s, errsock,
697 hostname,
698 local_user, remote_user,
699 cmd, cmd_len, auth_func);
700 close (s);
701 return ret;
703 warnx ("failed to contact %s", hostname);
704 freeaddrinfo (ai);
705 return -1;
708 #ifdef KRB4
709 static int use_v4 = -1;
710 #endif
711 static int use_v5 = -1;
712 static int use_only_broken = 0;
713 static int use_broken = 1;
714 static char *port_str;
715 static const char *user;
716 static int do_version;
717 static int do_help;
718 static int do_errsock = 1;
720 struct getargs args[] = {
721 #ifdef KRB4
722 { "krb4", '4', arg_flag, &use_v4, "Use Kerberos V4",
723 NULL },
724 #endif
725 { "krb5", '5', arg_flag, &use_v5, "Use Kerberos V5",
726 NULL },
727 { "broken", 'K', arg_flag, &use_only_broken, "Use priv port",
728 NULL },
729 { "input", 'n', arg_negative_flag, &input, "Close stdin",
730 NULL },
731 { "encrypt", 'x', arg_flag, &do_encrypt, "Encrypt connection",
732 NULL },
733 { "encrypt", 'z', arg_negative_flag, &do_encrypt,
734 "Don't encrypt connection", NULL },
735 { "forward", 'f', arg_flag, &do_forward, "Forward credentials",
736 NULL },
737 { "forward", 'G', arg_negative_flag,&do_forward, "Forward credentials",
738 NULL },
739 { "forwardable", 'F', arg_flag, &do_forwardable,
740 "Forward forwardable credentials", NULL },
741 { "unique", 'u', arg_flag, &do_unique_tkfile,
742 "Use unique remote tkfile", NULL },
743 { "tkfile", 'U', arg_string, &unique_tkfile,
744 "Use that remote tkfile", NULL },
745 { "port", 'p', arg_string, &port_str, "Use this port",
746 "number-or-service" },
747 { "user", 'l', arg_string, &user, "Run as this user",
748 NULL },
749 { "stderr", 'e', arg_negative_flag, &do_errsock, "don't open stderr"},
750 { "version", 0, arg_flag, &do_version, "Print version",
751 NULL },
752 { "help", 0, arg_flag, &do_help, NULL,
753 NULL }
756 static void
757 usage (int ret)
759 arg_printusage (args,
760 sizeof(args) / sizeof(args[0]),
761 NULL,
762 "host [command]");
763 exit (ret);
771 main(int argc, char **argv)
773 int priv_port1, priv_port2;
774 int priv_socket1, priv_socket2;
775 int port = 0;
776 int optind = 0;
777 int ret = 1;
778 char *cmd;
779 size_t cmd_len;
780 const char *local_user;
781 char *host = NULL;
782 int host_index = -1;
783 int status;
785 priv_port1 = priv_port2 = IPPORT_RESERVED-1;
786 priv_socket1 = rresvport(&priv_port1);
787 priv_socket2 = rresvport(&priv_port2);
788 setuid(getuid());
790 set_progname (argv[0]);
792 if (argc >= 2 && argv[1][0] != '-') {
793 host = argv[host_index = 1];
794 optind = 1;
797 status = krb5_init_context (&context);
798 if (status)
799 errx(1, "krb5_init_context failed: %u", status);
801 do_forwardable = krb5_config_get_bool (context, NULL,
802 "libdefaults",
803 "forwardable",
804 NULL);
806 do_forward = krb5_config_get_bool (context, NULL,
807 "libdefaults",
808 "forward",
809 NULL);
811 do_encrypt = krb5_config_get_bool (context, NULL,
812 "libdefaults",
813 "encrypt",
814 NULL);
816 if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
817 &optind))
818 usage (1);
820 if (do_forwardable)
821 do_forward = 1;
823 #if defined(KRB4) && defined(KRB5)
824 if(use_v4 == -1 && use_v5 == 1)
825 use_v4 = 0;
826 if(use_v5 == -1 && use_v4 == 1)
827 use_v5 = 0;
828 #endif
830 if (use_only_broken) {
831 #ifdef KRB4
832 use_v4 = 0;
833 #endif
834 use_v5 = 0;
837 if (do_help)
838 usage (0);
840 if (do_version) {
841 print_version (NULL);
842 return 0;
845 if (do_unique_tkfile && unique_tkfile != NULL)
846 errx (1, "Only one of -u and -U allowed.");
848 if (do_unique_tkfile)
849 strcpy(tkfile,"-u ");
850 else if (unique_tkfile != NULL) {
851 if (strchr(unique_tkfile,' ') != NULL) {
852 warnx("Space is not allowed in tkfilename");
853 usage(1);
855 do_unique_tkfile = 1;
856 snprintf (tkfile, sizeof(tkfile), "-U %s ", unique_tkfile);
859 if (host == NULL) {
860 if (argc - optind < 1)
861 usage (1);
862 else
863 host = argv[host_index = optind++];
866 if (optind == argc) {
867 close (priv_socket1);
868 close (priv_socket2);
869 argv[0] = "rlogin";
870 execvp ("rlogin", argv);
871 err (1, "execvp rlogin");
874 if (port_str) {
875 struct servent *s = roken_getservbyname (port_str, "tcp");
877 if (s)
878 port = s->s_port;
879 else {
880 char *ptr;
882 port = strtol (port_str, &ptr, 10);
883 if (port == 0 && ptr == port_str)
884 errx (1, "Bad port `%s'", port_str);
885 port = htons(port);
889 local_user = get_default_username ();
890 if (local_user == NULL)
891 errx (1, "who are you?");
893 if (user == NULL)
894 user = local_user;
896 cmd_len = construct_command(&cmd, argc - optind, argv + optind);
899 * Try all different authentication methods
902 if (ret && use_v5) {
903 int tmp_port;
905 if (port)
906 tmp_port = port;
907 else
908 tmp_port = krb5_getportbyname (context, "kshell", "tcp", 544);
910 auth_method = AUTH_KRB5;
911 ret = doit (host, user, local_user, tmp_port, cmd, cmd_len,
912 do_errsock,
913 send_krb5_auth);
915 #ifdef KRB4
916 if (ret && use_v4) {
917 int tmp_port;
919 if (port)
920 tmp_port = port;
921 else if (do_encrypt)
922 tmp_port = krb5_getportbyname (context, "ekshell", "tcp", 545);
923 else
924 tmp_port = krb5_getportbyname (context, "kshell", "tcp", 544);
926 auth_method = AUTH_KRB4;
927 ret = doit (host, user, local_user, tmp_port, cmd, cmd_len,
928 do_errsock,
929 send_krb4_auth);
931 #endif
932 if (ret && use_broken) {
933 int tmp_port;
935 if(port)
936 tmp_port = port;
937 else
938 tmp_port = krb5_getportbyname(context, "shell", "tcp", 514);
939 auth_method = AUTH_BROKEN;
940 ret = doit_broken (argc, argv, host_index, host,
941 user, local_user,
942 tmp_port,
943 priv_socket1,
944 do_errsock ? priv_socket2 : -1,
945 cmd, cmd_len);
947 return ret;