summaryrefslogtreecommitdiff
path: root/crypto/heimdal/appl/rsh/rsh.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/appl/rsh/rsh.c')
-rw-r--r--crypto/heimdal/appl/rsh/rsh.c1124
1 files changed, 0 insertions, 1124 deletions
diff --git a/crypto/heimdal/appl/rsh/rsh.c b/crypto/heimdal/appl/rsh/rsh.c
deleted file mode 100644
index 2d64d21f49fa..000000000000
--- a/crypto/heimdal/appl/rsh/rsh.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/*
- * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "rsh_locl.h"
-RCSID("$Id: rsh.c 21516 2007-07-12 12:47:23Z lha $");
-
-enum auth_method auth_method;
-#if defined(KRB4) || defined(KRB5)
-int do_encrypt = -1;
-#endif
-#ifdef KRB5
-int do_unique_tkfile = 0;
-char *unique_tkfile = NULL;
-char tkfile[MAXPATHLEN];
-int do_forward = -1;
-int do_forwardable = -1;
-krb5_context context;
-krb5_keyblock *keyblock;
-krb5_crypto crypto;
-#endif
-#ifdef KRB4
-des_key_schedule schedule;
-des_cblock iv;
-#endif
-int sock_debug = 0;
-
-#ifdef KRB4
-static int use_v4 = -1;
-#endif
-#ifdef KRB5
-static int use_v5 = -1;
-#endif
-#if defined(KRB4) || defined(KRB5)
-static int use_only_broken = 0;
-#else
-static int use_only_broken = 1;
-#endif
-static int use_broken = 1;
-static char *port_str;
-static const char *user;
-static int do_version;
-static int do_help;
-static int do_errsock = 1;
-#ifdef KRB5
-static char *protocol_version_str;
-static int protocol_version = 2;
-#endif
-
-/*
- *
- */
-
-static int input = 1; /* Read from stdin */
-
-static int
-rsh_loop (int s, int errsock)
-{
- fd_set real_readset;
- int count = 1;
-
-#ifdef KRB5
- if(auth_method == AUTH_KRB5 && protocol_version == 2)
- init_ivecs(1, errsock != -1);
-#endif
-
- if (s >= FD_SETSIZE || (errsock != -1 && errsock >= FD_SETSIZE))
- errx (1, "fd too large");
-
- FD_ZERO(&real_readset);
- FD_SET(s, &real_readset);
- if (errsock != -1) {
- FD_SET(errsock, &real_readset);
- ++count;
- }
- if(input)
- FD_SET(STDIN_FILENO, &real_readset);
-
- for (;;) {
- int ret;
- fd_set readset;
- char buf[RSH_BUFSIZ];
-
- readset = real_readset;
- ret = select (max(s, errsock) + 1, &readset, NULL, NULL, NULL);
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- else
- err (1, "select");
- }
- if (FD_ISSET(s, &readset)) {
- ret = do_read (s, buf, sizeof(buf), ivec_in[0]);
- if (ret < 0)
- err (1, "read");
- else if (ret == 0) {
- close (s);
- FD_CLR(s, &real_readset);
- if (--count == 0)
- return 0;
- } else
- net_write (STDOUT_FILENO, buf, ret);
- }
- if (errsock != -1 && FD_ISSET(errsock, &readset)) {
- ret = do_read (errsock, buf, sizeof(buf), ivec_in[1]);
- if (ret < 0)
- err (1, "read");
- else if (ret == 0) {
- close (errsock);
- FD_CLR(errsock, &real_readset);
- if (--count == 0)
- return 0;
- } else
- net_write (STDERR_FILENO, buf, ret);
- }
- if (FD_ISSET(STDIN_FILENO, &readset)) {
- ret = read (STDIN_FILENO, buf, sizeof(buf));
- if (ret < 0)
- err (1, "read");
- else if (ret == 0) {
- close (STDIN_FILENO);
- FD_CLR(STDIN_FILENO, &real_readset);
- shutdown (s, SHUT_WR);
- } else
- do_write (s, buf, ret, ivec_out[0]);
- }
- }
-}
-
-#ifdef KRB4
-static int
-send_krb4_auth(int s,
- struct sockaddr *thisaddr,
- struct sockaddr *thataddr,
- const char *hostname,
- const char *remote_user,
- const char *local_user,
- size_t cmd_len,
- const char *cmd)
-{
- KTEXT_ST text;
- CREDENTIALS cred;
- MSG_DAT msg;
- int status;
- size_t len;
-
- /* the normal default for krb4 should be to disable encryption */
- status = krb_sendauth ((do_encrypt == 1) ? KOPT_DO_MUTUAL : 0,
- s, &text, "rcmd",
- (char *)hostname, krb_realmofhost (hostname),
- getpid(), &msg, &cred, schedule,
- (struct sockaddr_in *)thisaddr,
- (struct sockaddr_in *)thataddr,
- KCMD_OLD_VERSION);
- if (status != KSUCCESS) {
- warnx("%s: %s", hostname, krb_get_err_text(status));
- return 1;
- }
- memcpy (iv, cred.session, sizeof(iv));
-
- len = strlen(remote_user) + 1;
- if (net_write (s, remote_user, len) != len) {
- warn("write");
- return 1;
- }
- if (net_write (s, cmd, cmd_len) != cmd_len) {
- warn("write");
- return 1;
- }
- return 0;
-}
-#endif /* KRB4 */
-
-#ifdef KRB5
-/*
- * Send forward information on `s' for host `hostname', them being
- * forwardable themselves if `forwardable'
- */
-
-static int
-krb5_forward_cred (krb5_auth_context auth_context,
- int s,
- const char *hostname,
- int forwardable)
-{
- krb5_error_code ret;
- krb5_ccache ccache;
- krb5_creds creds;
- krb5_kdc_flags flags;
- krb5_data out_data;
- krb5_principal principal;
-
- memset (&creds, 0, sizeof(creds));
-
- ret = krb5_cc_default (context, &ccache);
- if (ret) {
- warnx ("could not forward creds: krb5_cc_default: %s",
- krb5_get_err_text (context, ret));
- return 1;
- }
-
- ret = krb5_cc_get_principal (context, ccache, &principal);
- if (ret) {
- warnx ("could not forward creds: krb5_cc_get_principal: %s",
- krb5_get_err_text (context, ret));
- return 1;
- }
-
- creds.client = principal;
-
- ret = krb5_build_principal (context,
- &creds.server,
- strlen(principal->realm),
- principal->realm,
- "krbtgt",
- principal->realm,
- NULL);
-
- if (ret) {
- warnx ("could not forward creds: krb5_build_principal: %s",
- krb5_get_err_text (context, ret));
- return 1;
- }
-
- creds.times.endtime = 0;
-
- flags.i = 0;
- flags.b.forwarded = 1;
- flags.b.forwardable = forwardable;
-
- ret = krb5_get_forwarded_creds (context,
- auth_context,
- ccache,
- flags.i,
- hostname,
- &creds,
- &out_data);
- if (ret) {
- warnx ("could not forward creds: krb5_get_forwarded_creds: %s",
- krb5_get_err_text (context, ret));
- return 1;
- }
-
- ret = krb5_write_message (context,
- (void *)&s,
- &out_data);
- krb5_data_free (&out_data);
-
- if (ret)
- warnx ("could not forward creds: krb5_write_message: %s",
- krb5_get_err_text (context, ret));
- return 0;
-}
-
-static int sendauth_version_error;
-
-static int
-send_krb5_auth(int s,
- struct sockaddr *thisaddr,
- struct sockaddr *thataddr,
- const char *hostname,
- const char *remote_user,
- const char *local_user,
- size_t cmd_len,
- const char *cmd)
-{
- krb5_principal server;
- krb5_data cksum_data;
- int status;
- size_t len;
- krb5_auth_context auth_context = NULL;
- const char *protocol_string = NULL;
- krb5_flags ap_opts;
- char *str;
-
- status = krb5_sname_to_principal(context,
- hostname,
- "host",
- KRB5_NT_SRV_HST,
- &server);
- if (status) {
- warnx ("%s: %s", hostname, krb5_get_err_text(context, status));
- return 1;
- }
-
- if(do_encrypt == -1) {
- krb5_appdefault_boolean(context, NULL,
- krb5_principal_get_realm(context, server),
- "encrypt",
- FALSE,
- &do_encrypt);
- }
-
- cksum_data.length = asprintf (&str,
- "%u:%s%s%s",
- ntohs(socket_get_port(thataddr)),
- do_encrypt ? "-x " : "",
- cmd,
- remote_user);
- if (str == NULL) {
- warnx ("%s: failed to allocate command", hostname);
- return 1;
- }
- cksum_data.data = str;
-
- ap_opts = 0;
-
- if(do_encrypt)
- ap_opts |= AP_OPTS_MUTUAL_REQUIRED;
-
- switch(protocol_version) {
- case 2:
- ap_opts |= AP_OPTS_USE_SUBKEY;
- protocol_string = KCMD_NEW_VERSION;
- break;
- case 1:
- protocol_string = KCMD_OLD_VERSION;
- key_usage = KRB5_KU_OTHER_ENCRYPTED;
- break;
- default:
- abort();
- }
-
- status = krb5_sendauth (context,
- &auth_context,
- &s,
- protocol_string,
- NULL,
- server,
- ap_opts,
- &cksum_data,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL);
-
- /* do this while we have a principal */
- if(do_forward == -1 || do_forwardable == -1) {
- krb5_const_realm realm = krb5_principal_get_realm(context, server);
- if (do_forwardable == -1)
- krb5_appdefault_boolean(context, NULL, realm,
- "forwardable", FALSE,
- &do_forwardable);
- if (do_forward == -1)
- krb5_appdefault_boolean(context, NULL, realm,
- "forward", FALSE,
- &do_forward);
- }
-
- krb5_free_principal(context, server);
- krb5_data_free(&cksum_data);
-
- if (status) {
- if(status == KRB5_SENDAUTH_REJECTED &&
- protocol_version == 2 && protocol_version_str == NULL)
- sendauth_version_error = 1;
- else
- krb5_warn(context, status, "%s", hostname);
- return 1;
- }
-
- status = krb5_auth_con_getlocalsubkey (context, auth_context, &keyblock);
- if(keyblock == NULL)
- status = krb5_auth_con_getkey (context, auth_context, &keyblock);
- if (status) {
- warnx ("krb5_auth_con_getkey: %s", krb5_get_err_text(context, status));
- return 1;
- }
-
- status = krb5_auth_con_setaddrs_from_fd (context,
- auth_context,
- &s);
- if (status) {
- warnx("krb5_auth_con_setaddrs_from_fd: %s",
- krb5_get_err_text(context, status));
- return(1);
- }
-
- status = krb5_crypto_init(context, keyblock, 0, &crypto);
- if(status) {
- warnx ("krb5_crypto_init: %s", krb5_get_err_text(context, status));
- return 1;
- }
-
- len = strlen(remote_user) + 1;
- if (net_write (s, remote_user, len) != len) {
- warn ("write");
- return 1;
- }
- if (do_encrypt && net_write (s, "-x ", 3) != 3) {
- warn ("write");
- return 1;
- }
- if (net_write (s, cmd, cmd_len) != cmd_len) {
- warn ("write");
- return 1;
- }
-
- if (do_unique_tkfile) {
- if (net_write (s, tkfile, strlen(tkfile)) != strlen(tkfile)) {
- warn ("write");
- return 1;
- }
- }
- len = strlen(local_user) + 1;
- if (net_write (s, local_user, len) != len) {
- warn ("write");
- return 1;
- }
-
- if (!do_forward
- || krb5_forward_cred (auth_context, s, hostname, do_forwardable)) {
- /* Empty forwarding info */
-
- u_char zero[4] = {0, 0, 0, 0};
- write (s, &zero, 4);
- }
- krb5_auth_con_free (context, auth_context);
- return 0;
-}
-
-#endif /* KRB5 */
-
-static int
-send_broken_auth(int s,
- struct sockaddr *thisaddr,
- struct sockaddr *thataddr,
- const char *hostname,
- const char *remote_user,
- const char *local_user,
- size_t cmd_len,
- const char *cmd)
-{
- size_t len;
-
- len = strlen(local_user) + 1;
- if (net_write (s, local_user, len) != len) {
- warn ("write");
- return 1;
- }
- len = strlen(remote_user) + 1;
- if (net_write (s, remote_user, len) != len) {
- warn ("write");
- return 1;
- }
- if (net_write (s, cmd, cmd_len) != cmd_len) {
- warn ("write");
- return 1;
- }
- return 0;
-}
-
-static int
-proto (int s, int errsock,
- const char *hostname, const char *local_user, const char *remote_user,
- const char *cmd, size_t cmd_len,
- int (*auth_func)(int s,
- struct sockaddr *this, struct sockaddr *that,
- const char *hostname, const char *remote_user,
- const char *local_user, size_t cmd_len,
- const char *cmd))
-{
- int errsock2;
- char buf[BUFSIZ];
- char *p;
- size_t len;
- char reply;
- struct sockaddr_storage thisaddr_ss;
- struct sockaddr *thisaddr = (struct sockaddr *)&thisaddr_ss;
- struct sockaddr_storage thataddr_ss;
- struct sockaddr *thataddr = (struct sockaddr *)&thataddr_ss;
- struct sockaddr_storage erraddr_ss;
- struct sockaddr *erraddr = (struct sockaddr *)&erraddr_ss;
- socklen_t addrlen;
- int ret;
-
- addrlen = sizeof(thisaddr_ss);
- if (getsockname (s, thisaddr, &addrlen) < 0) {
- warn ("getsockname(%s)", hostname);
- return 1;
- }
- addrlen = sizeof(thataddr_ss);
- if (getpeername (s, thataddr, &addrlen) < 0) {
- warn ("getpeername(%s)", hostname);
- return 1;
- }
-
- if (errsock != -1) {
-
- addrlen = sizeof(erraddr_ss);
- if (getsockname (errsock, erraddr, &addrlen) < 0) {
- warn ("getsockname");
- return 1;
- }
-
- if (listen (errsock, 1) < 0) {
- warn ("listen");
- return 1;
- }
-
- p = buf;
- snprintf (p, sizeof(buf), "%u",
- ntohs(socket_get_port(erraddr)));
- len = strlen(buf) + 1;
- if(net_write (s, buf, len) != len) {
- warn ("write");
- close (errsock);
- return 1;
- }
-
-
- for (;;) {
- fd_set fdset;
-
- if (errsock >= FD_SETSIZE || s >= FD_SETSIZE)
- errx (1, "fd too large");
-
- FD_ZERO(&fdset);
- FD_SET(errsock, &fdset);
- FD_SET(s, &fdset);
-
- ret = select (max(errsock, s) + 1, &fdset, NULL, NULL, NULL);
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- warn ("select");
- close (errsock);
- return 1;
- }
- if (FD_ISSET(errsock, &fdset)) {
- errsock2 = accept (errsock, NULL, NULL);
- close (errsock);
- if (errsock2 < 0) {
- warn ("accept");
- return 1;
- }
- break;
- }
-
- /*
- * there should not arrive any data on this fd so if it's
- * readable it probably indicates that the other side when
- * away.
- */
-
- if (FD_ISSET(s, &fdset)) {
- warnx ("socket closed");
- close (errsock);
- errsock2 = -1;
- break;
- }
- }
- } else {
- if (net_write (s, "0", 2) != 2) {
- warn ("write");
- return 1;
- }
- errsock2 = -1;
- }
-
- if ((*auth_func)(s, thisaddr, thataddr, hostname,
- remote_user, local_user,
- cmd_len, cmd)) {
- close (errsock2);
- return 1;
- }
-
- ret = net_read (s, &reply, 1);
- if (ret < 0) {
- warn ("read");
- close (errsock2);
- return 1;
- } else if (ret == 0) {
- warnx ("unexpected EOF from %s", hostname);
- close (errsock2);
- return 1;
- }
- if (reply != 0) {
-
- warnx ("Error from rshd at %s:", hostname);
-
- while ((ret = read (s, buf, sizeof(buf))) > 0)
- write (STDOUT_FILENO, buf, ret);
- write (STDOUT_FILENO,"\n",1);
- close (errsock2);
- return 1;
- }
-
- if (sock_debug) {
- int one = 1;
- if (setsockopt(s, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(one)) < 0)
- warn("setsockopt remote");
- if (errsock2 != -1 &&
- setsockopt(errsock2, SOL_SOCKET, SO_DEBUG,
- (void *)&one, sizeof(one)) < 0)
- warn("setsockopt stderr");
- }
-
- return rsh_loop (s, errsock2);
-}
-
-/*
- * Return in `res' a copy of the concatenation of `argc, argv' into
- * malloced space. */
-
-static size_t
-construct_command (char **res, int argc, char **argv)
-{
- int i;
- size_t len = 0;
- char *tmp;
-
- for (i = 0; i < argc; ++i)
- len += strlen(argv[i]) + 1;
- len = max (1, len);
- tmp = malloc (len);
- if (tmp == NULL)
- errx (1, "malloc %lu failed", (unsigned long)len);
-
- *tmp = '\0';
- for (i = 0; i < argc - 1; ++i) {
- strlcat (tmp, argv[i], len);
- strlcat (tmp, " ", len);
- }
- if (argc > 0)
- strlcat (tmp, argv[argc-1], len);
- *res = tmp;
- return len;
-}
-
-static char *
-print_addr (const struct sockaddr *sa)
-{
- char addr_str[256];
- char *res;
- const char *as = NULL;
-
- if(sa->sa_family == AF_INET)
- as = inet_ntop (sa->sa_family, &((struct sockaddr_in*)sa)->sin_addr,
- addr_str, sizeof(addr_str));
-#ifdef HAVE_INET6
- else if(sa->sa_family == AF_INET6)
- as = inet_ntop (sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr,
- addr_str, sizeof(addr_str));
-#endif
- if(as == NULL)
- return NULL;
- res = strdup(as);
- if (res == NULL)
- errx (1, "malloc: out of memory");
- return res;
-}
-
-static int
-doit_broken (int argc,
- char **argv,
- int hostindex,
- struct addrinfo *ai,
- const char *remote_user,
- const char *local_user,
- int priv_socket1,
- int priv_socket2,
- const char *cmd,
- size_t cmd_len)
-{
- struct addrinfo *a;
-
- if (connect (priv_socket1, ai->ai_addr, ai->ai_addrlen) < 0) {
- int save_errno = errno;
-
- close(priv_socket1);
- close(priv_socket2);
-
- for (a = ai->ai_next; a != NULL; a = a->ai_next) {
- pid_t pid;
- char *adr = print_addr(a->ai_addr);
- if(adr == NULL)
- continue;
-
- pid = fork();
- if (pid < 0)
- err (1, "fork");
- else if(pid == 0) {
- char **new_argv;
- int i = 0;
-
- new_argv = malloc((argc + 2) * sizeof(*new_argv));
- if (new_argv == NULL)
- errx (1, "malloc: out of memory");
- new_argv[i] = argv[i];
- ++i;
- if (hostindex == i)
- new_argv[i++] = adr;
- new_argv[i++] = "-K";
- for(; i <= argc; ++i)
- new_argv[i] = argv[i - 1];
- if (hostindex > 1)
- new_argv[hostindex + 1] = adr;
- new_argv[argc + 1] = NULL;
- execv(PATH_RSH, new_argv);
- err(1, "execv(%s)", PATH_RSH);
- } else {
- int status;
- free(adr);
-
- while(waitpid(pid, &status, 0) < 0)
- ;
- if(WIFEXITED(status) && WEXITSTATUS(status) == 0)
- return 0;
- }
- }
- errno = save_errno;
- warn("%s", argv[hostindex]);
- return 1;
- } else {
- int ret;
-
- ret = proto (priv_socket1, priv_socket2,
- argv[hostindex],
- local_user, remote_user,
- cmd, cmd_len,
- send_broken_auth);
- return ret;
- }
-}
-
-#if defined(KRB4) || defined(KRB5)
-static int
-doit (const char *hostname,
- struct addrinfo *ai,
- const char *remote_user,
- const char *local_user,
- const char *cmd,
- size_t cmd_len,
- int (*auth_func)(int s,
- struct sockaddr *this, struct sockaddr *that,
- const char *hostname, const char *remote_user,
- const char *local_user, size_t cmd_len,
- const char *cmd))
-{
- int error;
- struct addrinfo *a;
- int socketfailed = 1;
- int ret;
-
- for (a = ai; a != NULL; a = a->ai_next) {
- int s;
- int errsock;
-
- s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
- if (s < 0)
- continue;
- socketfailed = 0;
- if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
- char addr[128];
- if(getnameinfo(a->ai_addr, a->ai_addrlen,
- addr, sizeof(addr), NULL, 0, NI_NUMERICHOST) == 0)
- warn ("connect(%s [%s])", hostname, addr);
- else
- warn ("connect(%s)", hostname);
- close (s);
- continue;
- }
- if (do_errsock) {
- struct addrinfo *ea, *eai;
- struct addrinfo hints;
-
- memset (&hints, 0, sizeof(hints));
- hints.ai_socktype = a->ai_socktype;
- hints.ai_protocol = a->ai_protocol;
- hints.ai_family = a->ai_family;
- hints.ai_flags = AI_PASSIVE;
-
- errsock = -1;
-
- error = getaddrinfo (NULL, "0", &hints, &eai);
- if (error)
- errx (1, "getaddrinfo: %s", gai_strerror(error));
- for (ea = eai; ea != NULL; ea = ea->ai_next) {
- errsock = socket (ea->ai_family, ea->ai_socktype,
- ea->ai_protocol);
- if (errsock < 0)
- continue;
- if (bind (errsock, ea->ai_addr, ea->ai_addrlen) < 0)
- err (1, "bind");
- break;
- }
- if (errsock < 0)
- err (1, "socket");
- freeaddrinfo (eai);
- } else
- errsock = -1;
-
- ret = proto (s, errsock,
- hostname,
- local_user, remote_user,
- cmd, cmd_len, auth_func);
- close (s);
- return ret;
- }
- if(socketfailed)
- warnx ("failed to contact %s", hostname);
- return -1;
-}
-#endif /* KRB4 || KRB5 */
-
-struct getargs args[] = {
-#ifdef KRB4
- { "krb4", '4', arg_flag, &use_v4, "Use Kerberos V4" },
-#endif
-#ifdef KRB5
- { "krb5", '5', arg_flag, &use_v5, "Use Kerberos V5" },
- { "forward", 'f', arg_flag, &do_forward, "Forward credentials [krb5]"},
- { "forwardable", 'F', arg_flag, &do_forwardable,
- "Forward forwardable credentials [krb5]" },
- { NULL, 'G', arg_negative_flag,&do_forward, "Don't forward credentials" },
- { "unique", 'u', arg_flag, &do_unique_tkfile,
- "Use unique remote credentials cache [krb5]" },
- { "tkfile", 'U', arg_string, &unique_tkfile,
- "Specifies remote credentials cache [krb5]" },
- { "protocol", 'P', arg_string, &protocol_version_str,
- "Protocol version [krb5]", "protocol" },
-#endif
- { "broken", 'K', arg_flag, &use_only_broken, "Use only priv port" },
-#if defined(KRB4) || defined(KRB5)
- { "encrypt", 'x', arg_flag, &do_encrypt, "Encrypt connection" },
- { NULL, 'z', arg_negative_flag, &do_encrypt,
- "Don't encrypt connection", NULL },
-#endif
- { NULL, 'd', arg_flag, &sock_debug, "Enable socket debugging" },
- { "input", 'n', arg_negative_flag, &input, "Close stdin" },
- { "port", 'p', arg_string, &port_str, "Use this port",
- "port" },
- { "user", 'l', arg_string, &user, "Run as this user", "login" },
- { "stderr", 'e', arg_negative_flag, &do_errsock, "Don't open stderr"},
-#ifdef KRB5
-#endif
- { "version", 0, arg_flag, &do_version, NULL },
- { "help", 0, arg_flag, &do_help, NULL }
-};
-
-static void
-usage (int ret)
-{
- arg_printusage (args,
- sizeof(args) / sizeof(args[0]),
- NULL,
- "[login@]host [command]");
- exit (ret);
-}
-
-/*
- *
- */
-
-int
-main(int argc, char **argv)
-{
- int priv_port1, priv_port2;
- int priv_socket1, priv_socket2;
- int argindex = 0;
- int error;
- struct addrinfo hints, *ai;
- int ret = 1;
- char *cmd;
- char *tmp;
- size_t cmd_len;
- const char *local_user;
- char *host = NULL;
- int host_index = -1;
-#ifdef KRB5
- int status;
-#endif
- uid_t uid;
-
- priv_port1 = priv_port2 = IPPORT_RESERVED-1;
- priv_socket1 = rresvport(&priv_port1);
- priv_socket2 = rresvport(&priv_port2);
- uid = getuid ();
- if (setuid (uid) || (uid != 0 && setuid(0) == 0))
- err (1, "setuid");
-
- setprogname (argv[0]);
-
- if (argc >= 2 && argv[1][0] != '-') {
- host = argv[host_index = 1];
- argindex = 1;
- }
-
- if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
- &argindex))
- usage (1);
-
- if (do_help)
- usage (0);
-
- if (do_version) {
- print_version (NULL);
- return 0;
- }
-
-#ifdef KRB5
- if(protocol_version_str != NULL) {
- if(strcasecmp(protocol_version_str, "N") == 0)
- protocol_version = 2;
- else if(strcasecmp(protocol_version_str, "O") == 0)
- protocol_version = 1;
- else {
- char *end;
- int v;
- v = strtol(protocol_version_str, &end, 0);
- if(*end != '\0' || (v != 1 && v != 2)) {
- errx(1, "unknown protocol version \"%s\"",
- protocol_version_str);
- }
- protocol_version = v;
- }
- }
-
- status = krb5_init_context (&context);
- if (status) {
- if(use_v5 == 1)
- errx(1, "krb5_init_context failed: %d", status);
- else
- use_v5 = 0;
- }
-
- /* request for forwardable on the command line means we should
- also forward */
- if (do_forwardable == 1)
- do_forward = 1;
-
-#endif
-
-#if defined(KRB4) && defined(KRB5)
- if(use_v4 == -1 && use_v5 == 1)
- use_v4 = 0;
- if(use_v5 == -1 && use_v4 == 1)
- use_v5 = 0;
-#endif
-
- if (use_only_broken) {
-#ifdef KRB4
- use_v4 = 0;
-#endif
-#ifdef KRB5
- use_v5 = 0;
-#endif
- }
-
- if(priv_socket1 < 0) {
- if (use_only_broken)
- errx (1, "unable to bind reserved port: is rsh setuid root?");
- use_broken = 0;
- }
-
-#if defined(KRB4) || defined(KRB5)
- if (do_encrypt == 1 && use_only_broken)
- errx (1, "encryption not supported with old style authentication");
-#endif
-
-
-
-#ifdef KRB5
- if (do_unique_tkfile && unique_tkfile != NULL)
- errx (1, "Only one of -u and -U allowed.");
-
- if (do_unique_tkfile)
- strlcpy(tkfile,"-u ", sizeof(tkfile));
- else if (unique_tkfile != NULL) {
- if (strchr(unique_tkfile,' ') != NULL) {
- warnx("Space is not allowed in tkfilename");
- usage(1);
- }
- do_unique_tkfile = 1;
- snprintf (tkfile, sizeof(tkfile), "-U %s ", unique_tkfile);
- }
-#endif
-
- if (host == NULL) {
- if (argc - argindex < 1)
- usage (1);
- else
- host = argv[host_index = argindex++];
- }
-
- if((tmp = strchr(host, '@')) != NULL) {
- *tmp++ = '\0';
- user = host;
- host = tmp;
- }
-
- if (argindex == argc) {
- close (priv_socket1);
- close (priv_socket2);
- argv[0] = "rlogin";
- execvp ("rlogin", argv);
- err (1, "execvp rlogin");
- }
-
- local_user = get_default_username ();
- if (local_user == NULL)
- errx (1, "who are you?");
-
- if (user == NULL)
- user = local_user;
-
- cmd_len = construct_command(&cmd, argc - argindex, argv + argindex);
-
- /*
- * Try all different authentication methods
- */
-
-#ifdef KRB5
- if (ret && use_v5) {
- memset (&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- if(port_str == NULL) {
- error = getaddrinfo(host, "kshell", &hints, &ai);
- if(error == EAI_NONAME)
- error = getaddrinfo(host, "544", &hints, &ai);
- } else
- error = getaddrinfo(host, port_str, &hints, &ai);
-
- if(error)
- errx (1, "getaddrinfo: %s", gai_strerror(error));
-
- auth_method = AUTH_KRB5;
- again:
- ret = doit (host, ai, user, local_user, cmd, cmd_len,
- send_krb5_auth);
- if(ret != 0 && sendauth_version_error &&
- protocol_version == 2) {
- protocol_version = 1;
- goto again;
- }
- freeaddrinfo(ai);
- }
-#endif
-#ifdef KRB4
- if (ret && use_v4) {
- memset (&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- if(port_str == NULL) {
- if(do_encrypt) {
- error = getaddrinfo(host, "ekshell", &hints, &ai);
- if(error == EAI_NONAME)
- error = getaddrinfo(host, "545", &hints, &ai);
- } else {
- error = getaddrinfo(host, "kshell", &hints, &ai);
- if(error == EAI_NONAME)
- error = getaddrinfo(host, "544", &hints, &ai);
- }
- } else
- error = getaddrinfo(host, port_str, &hints, &ai);
-
- if(error)
- errx (1, "getaddrinfo: %s", gai_strerror(error));
- auth_method = AUTH_KRB4;
- ret = doit (host, ai, user, local_user, cmd, cmd_len,
- send_krb4_auth);
- freeaddrinfo(ai);
- }
-#endif
- if (ret && use_broken) {
- memset (&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- if(port_str == NULL) {
- error = getaddrinfo(host, "shell", &hints, &ai);
- if(error == EAI_NONAME)
- error = getaddrinfo(host, "514", &hints, &ai);
- } else
- error = getaddrinfo(host, port_str, &hints, &ai);
-
- if(error)
- errx (1, "getaddrinfo: %s", gai_strerror(error));
-
- auth_method = AUTH_BROKEN;
- ret = doit_broken (argc, argv, host_index, ai,
- user, local_user,
- priv_socket1,
- do_errsock ? priv_socket2 : -1,
- cmd, cmd_len);
- freeaddrinfo(ai);
- }
- free(cmd);
- return ret;
-}