diff options
Diffstat (limited to 'crypto/heimdal/appl/rsh/rsh.c')
-rw-r--r-- | crypto/heimdal/appl/rsh/rsh.c | 1124 |
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 2d64d21..0000000 --- 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; -} |