stupid mistake in execl
[unix-history] / usr / src / usr.bin / rsh / rsh.c
index 416c790..a65c3c5 100644 (file)
@@ -1,6 +1,35 @@
+
+/*
+ *     $Source: /a/staff/kfall/mit/rsh/RCS/rsh.c,v $
+ *     $Header: /a/staff/kfall/mit/rsh/RCS/rsh.c,v 5.1 89/07/31 19:28:59 kfall Exp Locker: kfall $
+ */
+
+/*
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)rsh.c      4.7 83/02/23";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rsh.c      5.12 (Berkeley) 5/11/89";
+#endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/socket.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -14,21 +43,35 @@ static char sccsid[] = "@(#)rsh.c   4.7 83/02/23";
 #include <signal.h>
 #include <pwd.h>
 #include <netdb.h>
 #include <signal.h>
 #include <pwd.h>
 #include <netdb.h>
+#include "pathnames.h"
+
+#ifdef KERBEROS
+#include <krb.h>
+char   dst_realm_buf[REALM_SZ];
+char   *dest_realm = NULL;
+int    use_kerberos = 1, encrypt = 0;
+CREDENTIALS    cred;
+Key_schedule   schedule;
+extern char    *krb_realmofhost();
+#endif /* KERBEROS */
 
 /*
  * rsh - remote shell
  */
 /* VARARGS */
 int    error();
 
 /*
  * rsh - remote shell
  */
 /* VARARGS */
 int    error();
-char   *index(), *rindex(), *malloc(), *getpass(), *sprintf(), *strcpy();
+char   *index(), *rindex(), *malloc(), *getpass(), *strcpy();
 
 struct passwd *getpwuid();
 
 int    errno;
 int    options;
 int    rfd2;
 
 struct passwd *getpwuid();
 
 int    errno;
 int    options;
 int    rfd2;
+int    nflag;
 int    sendsig();
 
 int    sendsig();
 
+#define        mask(s) (1 << ((s) - 1))
+
 main(argc, argv0)
        int argc;
        char **argv0;
 main(argc, argv0)
        int argc;
        char **argv0;
@@ -41,6 +84,7 @@ main(argc, argv0)
        int readfrom, ready;
        int one = 1;
        struct servent *sp;
        int readfrom, ready;
        int one = 1;
        struct servent *sp;
+       int omask;
 
        host = rindex(argv[0], '/');
        if (host)
 
        host = rindex(argv[0], '/');
        if (host)
@@ -61,8 +105,10 @@ another:
        }
        if (argc > 0 && !strcmp(*argv, "-n")) {
                argv++, argc--;
        }
        if (argc > 0 && !strcmp(*argv, "-n")) {
                argv++, argc--;
-               (void) close(0);
-               (void) open("/dev/null", 0);
+#ifdef KERBEROS
+               if (!encrypt)
+                       nflag++;
+#endif
                goto another;
        }
        if (argc > 0 && !strcmp(*argv, "-d")) {
                goto another;
        }
        if (argc > 0 && !strcmp(*argv, "-d")) {
@@ -71,20 +117,58 @@ another:
                goto another;
        }
        /*
                goto another;
        }
        /*
-        * Ignore the -e flag to allow aliases with rlogin
+        * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin
         * to work
         * to work
+        *
+        * There must be a better way to do this! -jmb
         */
         */
+       if (argc > 0 && !strncmp(*argv, "-L", 2)) {
+               argv++, argc--;
+               goto another;
+       }
+       if (argc > 0 && !strncmp(*argv, "-w", 2)) {
+               argv++, argc--;
+               goto another;
+       }
        if (argc > 0 && !strncmp(*argv, "-e", 2)) {
                argv++, argc--;
                goto another;
        }
        if (argc > 0 && !strncmp(*argv, "-e", 2)) {
                argv++, argc--;
                goto another;
        }
+       if (argc > 0 && !strncmp(*argv, "-8", 2)) {
+               argv++, argc--;
+               goto another;
+       }
+
+#ifdef KERBEROS
+       if(argc > 0 && !strncmp(*argv, "-x", 2)) {
+               encrypt = 1;
+               des_set_key(cred.session, schedule);
+               if (nflag)
+                       nflag = 0;
+               argv++, argc--;
+               goto another;
+       }
+
+       if(argc > 0 && !strcmp(*argv, "-k")) {
+               argv++, argc--;
+               if(argc <= 0 || (**argv == '-')) {
+                       fprintf(stderr, "-k option requires an argument\n");
+                       exit(1);
+               }
+               dest_realm = dst_realm_buf;
+               strncpy(dest_realm, *argv, REALM_SZ);
+               argv++, argc--;
+               goto another;
+       }
+#endif
+
        if (host == 0)
                goto usage;
        if (argv[0] == 0) {
                if (asrsh)
                        *argv0 = "rlogin";
        if (host == 0)
                goto usage;
        if (argv[0] == 0) {
                if (asrsh)
                        *argv0 = "rlogin";
-               execv("/usr/ucb/rlogin", argv0);
-               perror("/usr/ucb/rlogin");
+               execv(_PATH_RLOGIN, argv0);
+               perror(_PATH_RLOGIN);
                exit(1);
        }
        pwd = getpwuid(getuid());
                exit(1);
        }
        pwd = getpwuid(getuid());
@@ -103,35 +187,114 @@ another:
                if (ap[1])
                        *cp++ = ' ';
        }
                if (ap[1])
                        *cp++ = ' ';
        }
+#ifdef KERBEROS
+       sp = getservbyname((encrypt ? "ekshell" : "kshell"), "tcp");
+       if (sp == NULL) {
+               char    msgbuf[64];
+               use_kerberos = 0;
+               (void) sprintf(msgbuf, "can't get entry for %s/tcp service",
+                       (encrypt ? "ekshell" : "kshell"));
+               old_warning(msgbuf);
+               sp = getservbyname("shell", "tcp");
+       }
+#else
        sp = getservbyname("shell", "tcp");
        sp = getservbyname("shell", "tcp");
-       if (sp == 0) {
+#endif
+
+       if (sp == NULL) {
                fprintf(stderr, "rsh: shell/tcp: unknown service\n");
                exit(1);
        }
                fprintf(stderr, "rsh: shell/tcp: unknown service\n");
                exit(1);
        }
+
+#ifdef KERBEROS
+try_connect:
+       if (use_kerberos) {
+               rem = KSUCCESS;
+               errno = 0;
+               if (dest_realm == NULL)
+                       dest_realm = krb_realmofhost(host);
+
+               if (encrypt) {
+                       rem = krcmd_mutual(
+                               &host, sp->s_port,
+                               user ? user : pwd->pw_name,
+                               args,
+                               &rfd2,
+                               dest_realm,
+                               &cred, schedule);
+               } else {
+                       rem = krcmd(
+                               &host,
+                               sp->s_port,
+                               user ? user : pwd->pw_name,
+                               args,
+                               &rfd2,
+                               dest_realm);
+               }
+               if (rem < 0) {
+                       use_kerberos = 0;
+                       sp = getservbyname("shell", "tcp");
+                       if (sp == NULL) {
+                               fprintf(stderr, "unknown service shell/tcp\n");
+                               exit(1);
+                       }
+                       if (errno == ECONNREFUSED)
+                               old_warning("remote host doesn't support Kerberos");
+                       if (errno == ENOENT)
+                               old_warning("Can't provide Kerberos auth data");
+                       goto try_connect;
+               }
+       } else {
+               if (encrypt) {
+                       fprintf(stderr,"The -x flag requires Kerberos authentication\n");
+                       exit(1);
+               }
+               rem = rcmd(&host, sp->s_port, pwd->pw_name,
+                       user ? user : pwd->pw_name, args, &rfd2);
+       }
+
+#else
+                          
         rem = rcmd(&host, sp->s_port, pwd->pw_name,
         rem = rcmd(&host, sp->s_port, pwd->pw_name,
-           user ? user : pwd->pw_name, args, &rfd2);
+               user ? user : pwd->pw_name, args, &rfd2);
+#endif
+
         if (rem < 0)
                 exit(1);
         if (rem < 0)
                 exit(1);
+
        if (rfd2 < 0) {
                fprintf(stderr, "rsh: can't establish stderr\n");
                exit(2);
        }
        if (options & SO_DEBUG) {
        if (rfd2 < 0) {
                fprintf(stderr, "rsh: can't establish stderr\n");
                exit(2);
        }
        if (options & SO_DEBUG) {
-               if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+               if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0)
                        perror("setsockopt (stdin)");
                        perror("setsockopt (stdin)");
-               if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+               if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0)
                        perror("setsockopt (stderr)");
        }
        (void) setuid(getuid());
                        perror("setsockopt (stderr)");
        }
        (void) setuid(getuid());
-       sigacts(SIG_HOLD);
-        pid = fork();
-        if (pid < 0) {
-               perror("fork");
-                exit(1);
-        }
-       ioctl(rfd2, FIONBIO, &one);
-       ioctl(rem, FIONBIO, &one);
-        if (pid == 0) {
+       omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, sendsig);
+       if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+               signal(SIGQUIT, sendsig);
+       if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+               signal(SIGTERM, sendsig);
+       if (nflag == 0) {
+               pid = fork();
+               if (pid < 0) {
+                       perror("fork");
+                       exit(1);
+               }
+       }
+#ifdef KERBEROS
+       if (!encrypt)
+#endif
+       {
+               ioctl(rfd2, FIONBIO, &one);
+               ioctl(rem, FIONBIO, &one);
+       }
+        if (nflag == 0 && pid == 0) {
                char *bp; int rembits, wc;
                (void) close(rfd2);
        reread:
                char *bp; int rembits, wc;
                (void) close(rfd2);
        reread:
@@ -151,7 +314,12 @@ another:
                }
                if ((rembits & (1<<rem)) == 0)
                        goto rewrite;
                }
                if ((rembits & (1<<rem)) == 0)
                        goto rewrite;
-               wc = write(rem, bp, cc);
+#ifdef KERBEROS
+               if (encrypt)
+                       wc = des_write(rem, bp, cc);
+               else
+                       wc = write(rem, bp, cc);
+#endif
                if (wc < 0) {
                        if (errno == EWOULDBLOCK)
                                goto rewrite;
                if (wc < 0) {
                        if (errno == EWOULDBLOCK)
                                goto rewrite;
@@ -165,7 +333,7 @@ another:
                (void) shutdown(rem, 1);
                exit(0);
        }
                (void) shutdown(rem, 1);
                exit(0);
        }
-       sigacts(sendsig);
+       sigsetmask(omask);
        readfrom = (1<<rfd2) | (1<<rem);
        do {
                ready = readfrom;
        readfrom = (1<<rfd2) | (1<<rem);
        do {
                ready = readfrom;
@@ -178,7 +346,12 @@ another:
                }
                if (ready & (1<<rfd2)) {
                        errno = 0;
                }
                if (ready & (1<<rfd2)) {
                        errno = 0;
-                       cc = read(rfd2, buf, sizeof buf);
+#ifdef KERBEROS
+                       if (encrypt)
+                               cc = des_read(rfd2, buf, sizeof buf);
+                       else
+#endif
+                               cc = read(rfd2, buf, sizeof buf);
                        if (cc <= 0) {
                                if (errno != EWOULDBLOCK)
                                        readfrom &= ~(1<<rfd2);
                        if (cc <= 0) {
                                if (errno != EWOULDBLOCK)
                                        readfrom &= ~(1<<rfd2);
@@ -187,7 +360,12 @@ another:
                }
                if (ready & (1<<rem)) {
                        errno = 0;
                }
                if (ready & (1<<rem)) {
                        errno = 0;
-                       cc = read(rem, buf, sizeof buf);
+#ifdef KERBEROS
+                       if (encrypt)
+                               cc = des_read(rem, buf, sizeof buf);
+                       else
+                               cc = read(rem, buf, sizeof buf);
+#endif
                        if (cc <= 0) {
                                if (errno != EWOULDBLOCK)
                                        readfrom &= ~(1<<rem);
                        if (cc <= 0) {
                                if (errno != EWOULDBLOCK)
                                        readfrom &= ~(1<<rem);
@@ -195,26 +373,35 @@ another:
                                (void) write(1, buf, cc);
                }
         } while (readfrom);
                                (void) write(1, buf, cc);
                }
         } while (readfrom);
-        (void) kill(pid, SIGKILL);
+       if (nflag == 0)
+               (void) kill(pid, SIGKILL);
        exit(0);
 usage:
        fprintf(stderr,
        exit(0);
 usage:
        fprintf(stderr,
-           "usage: rsh host [ -l login ] [ -p passwd ] command\n");
+#ifdef KERBEROS
+           "usage: rsh host [ -l login ] [ -n ] [ -k realm ] command\n");
+#else
+           "usage: rsh host [ -l login ] [ -n ] command\n");
+#endif
        exit(1);
 }
 
        exit(1);
 }
 
-sigacts(state)
-       int (*state)();
+sendsig(signo)
+       char signo;
 {
 {
-
-       sigset(SIGINT, state);
-       sigset(SIGQUIT, state);
-       sigset(SIGTERM, state);
+#ifdef KERBEROS
+       if (encrypt)
+               (void) des_write(rfd2, &signo, 1);
+       else
+#endif
+               (void) write(rfd2, &signo, 1);
 }
 
 }
 
-sendsig(signo)
-       int signo;
+#ifdef KERBEROS
+int
+old_warning(str)
+       char    *str;
 {
 {
-
-       (void) write(rfd2, (char *)&signo, 1);
+       fprintf(stderr,"Warning: %s, using standard rsh\n", str);
 }
 }
+#endif