add -DCRYPT to get -x processing
[unix-history] / usr / src / bin / rcp / rcp.c
index 7d3661f..893129d 100644 (file)
@@ -1,28 +1,18 @@
 /*
 /*
- * Copyright (c) 1983 The Regents of the University of California.
+ * Copyright (c) 1983, 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * 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.
+ * %sccs.include.redist.c%
  */
 
 #ifndef lint
 char copyright[] =
  */
 
 #ifndef lint
 char copyright[] =
-"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)rcp.c      5.21 (Berkeley) %G%";
+static char sccsid[] = "@(#)rcp.c      5.30 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -36,29 +26,43 @@ static char sccsid[] = "@(#)rcp.c   5.21 (Berkeley) %G%";
 #include <sys/dir.h>
 #include <sys/signal.h>
 #include <netinet/in.h>
 #include <sys/dir.h>
 #include <sys/signal.h>
 #include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
 #include <pwd.h>
 #include <netdb.h>
 #include <errno.h>
 #include <pwd.h>
 #include <netdb.h>
 #include <errno.h>
-#include <strings.h>
+#include <string.h>
 #include <stdio.h>
 #include <ctype.h>
 #include "pathnames.h"
 
 #ifdef KERBEROS
 #include <stdio.h>
 #include <ctype.h>
 #include "pathnames.h"
 
 #ifdef KERBEROS
-#include <kerberos/krb.h>
-
-char krb_realm[REALM_SZ];
-int use_kerberos = 1, encrypt = 0;
-CREDENTIALS cred;
-Key_schedule schedule;
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+char   dst_realm_buf[REALM_SZ];
+char   *dest_realm = NULL;
+int    use_kerberos = 1;
+CREDENTIALS    cred;
+Key_schedule   schedule;
+extern char    *krb_realmofhost();
+#ifdef CRYPT
+int    encrypt = 0;
+#define        OPTIONS "dfkprtx"
+#else
+#define        OPTIONS "dfkprt"
+#endif
+#else
+#define        OPTIONS "dfprt"
 #endif
 
 extern int errno;
 struct passwd *pwd;
 #endif
 
 extern int errno;
 struct passwd *pwd;
-int errs, pflag, port, rem, userid;
-int iamremote, iamrecursive, targetshouldbedirectory;
+u_short        port;
+uid_t  userid;
+int errs, rem;
+int pflag, iamremote, iamrecursive, targetshouldbedirectory;
 
 
-#define        CMDNEEDS        20
+#define        CMDNEEDS        64
 char cmd[CMDNEEDS];            /* must hold "rcp -r -p -d\0" */
 
 typedef struct _buf {
 char cmd[CMDNEEDS];            /* must hold "rcp -r -p -d\0" */
 
 typedef struct _buf {
@@ -73,60 +77,45 @@ main(argc, argv)
        extern int optind;
        struct servent *sp;
        int ch, fflag, tflag;
        extern int optind;
        struct servent *sp;
        int ch, fflag, tflag;
-       char *targ, *colon();
+       char *targ, *shell, *colon();
        struct passwd *getpwuid();
        int lostconn();
 
        struct passwd *getpwuid();
        int lostconn();
 
-#ifdef KERBEROS
-       sp = getservbyname("kshell", "tcp");
-       if (sp == NULL) {
-               use_kerberos = 0;
-               old_warning("kshell service unknown");
-               sp = getservbyname("kshell", "tcp");
-       }
-#else
-       sp = getservbyname("shell", "tcp");
-#endif
-       if (!sp) {
-               (void)fprintf(stderr, "rcp: shell/tcp: unknown service\n");
-               exit(1);
-       }
-       port = sp->s_port;
-
-       if (!(pwd = getpwuid(userid = getuid()))) {
-               (void)fprintf(stderr, "rcp: unknown user %d.\n", userid);
-               exit(1);
-       }
-
        fflag = tflag = 0;
        fflag = tflag = 0;
-       while ((ch = getopt(argc, argv, "dfkprtx")) != EOF)
+       while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
                switch(ch) {
                switch(ch) {
-               case 'd':
-                       targetshouldbedirectory = 1;
-                       break;
-               case 'f':                       /* "from" */
-                       fflag = 1;
-                       break;
-#ifdef KERBEROS
-               case 'k':
-                       strncpy(krb_realm, ++argv, REALM_SZ);
-                       break;
-#endif
+               /* user-visible flags */
                case 'p':                       /* preserve access/mod times */
                        ++pflag;
                        break;
                case 'r':
                        ++iamrecursive;
                        break;
                case 'p':                       /* preserve access/mod times */
                        ++pflag;
                        break;
                case 'r':
                        ++iamrecursive;
                        break;
-               case 't':                       /* "to" */
-                       tflag = 1;
+#ifdef KERBEROS
+               case 'k':
+                       strncpy(dst_realm_buf, ++argv, REALM_SZ);
+                       dest_realm = dst_realm_buf;
                        break;
                        break;
-#ifdef KERBEROS
+#ifdef CRYPT
                case 'x':
                        encrypt = 1;
                case 'x':
                        encrypt = 1;
-                       des_set_key(cred.session, schedule);
+                       /* des_set_key(cred.session, schedule); */
                        break;
 #endif
                        break;
 #endif
+#endif
+               /* rshd-invoked options (server) */
+               case 'd':
+                       targetshouldbedirectory = 1;
+                       break;
+               case 'f':                       /* "from" */
+                       iamremote = 1;
+                       fflag = 1;
+                       break;
+               case 't':                       /* "to" */
+                       iamremote = 1;
+                       tflag = 1;
+                       break;
+
                case '?':
                default:
                        usage();
                case '?':
                default:
                        usage();
@@ -134,8 +123,37 @@ main(argc, argv)
        argc -= optind;
        argv += optind;
 
        argc -= optind;
        argv += optind;
 
+#ifdef KERBEROS
+#ifdef CRYPT
+       shell = encrypt ? "ekshell" : "kshell";
+#else
+       shell = "kshell";
+#endif
+       sp = getservbyname(shell, "tcp");
+       if (sp == NULL) {
+               char    msgbuf[64];
+               use_kerberos = 0;
+               (void) sprintf(msgbuf, "can't get entry for %s/tcp service",
+                       shell);
+               old_warning(msgbuf);
+               sp = getservbyname("shell", "tcp");
+       }
+#else
+       sp = getservbyname("shell", "tcp");
+#endif
+       if (sp == NULL) {
+               (void)fprintf(stderr, "rcp: shell/tcp: unknown service\n");
+               exit(1);
+       }
+       port = sp->s_port;
+
+       if (!(pwd = getpwuid(userid = getuid()))) {
+               (void)fprintf(stderr, "rcp: unknown user %d.\n", userid);
+               exit(1);
+       }
+
        if (fflag) {
        if (fflag) {
-               iamremote = 1;
+               /* follow "protocol", send data */
                (void)response();
                (void)setuid(userid);
                source(argc, argv);
                (void)response();
                (void)setuid(userid);
                source(argc, argv);
@@ -143,7 +161,7 @@ main(argc, argv)
        }
 
        if (tflag) {
        }
 
        if (tflag) {
-               iamremote = 1;
+               /* receive data */
                (void)setuid(userid);
                sink(argc, argv);
                exit(errs);
                (void)setuid(userid);
                sink(argc, argv);
                exit(errs);
@@ -155,15 +173,26 @@ main(argc, argv)
                targetshouldbedirectory = 1;
 
        rem = -1;
                targetshouldbedirectory = 1;
 
        rem = -1;
+       /* command to be executed on remote system using "rsh" */
+#ifdef KERBEROS
+       (void)sprintf(cmd, "rcp%s%s%s%s", iamrecursive ? " -r" : "",
+#ifdef CRYPT
+           ((encrypt && use_kerberos) ? " -x" : ""),
+#else
+           "",
+#endif
+           pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
+#else
        (void)sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "",
            pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
        (void)sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "",
            pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
+#endif
 
        (void)signal(SIGPIPE, lostconn);
 
        if (targ = colon(argv[argc - 1]))
 
        (void)signal(SIGPIPE, lostconn);
 
        if (targ = colon(argv[argc - 1]))
-               toremote(targ, argc, argv);
+               toremote(targ, argc, argv);     /* destination is remote host */
        else {
        else {
-               tolocal(argc, argv);
+               tolocal(argc, argv);            /* destination is local host */
                if (targetshouldbedirectory)
                        verifydir(argv[argc - 1]);
        }
                if (targetshouldbedirectory)
                        verifydir(argv[argc - 1]);
        }
@@ -175,7 +204,7 @@ toremote(targ, argc, argv)
        int argc;
        char **argv;
 {
        int argc;
        char **argv;
 {
-       int i;
+       int i, tos;
        char *bp, *host, *src, *suser, *thost, *tuser;
        char *colon(), *malloc();
 
        char *bp, *host, *src, *suser, *thost, *tuser;
        char *colon(), *malloc();
 
@@ -184,6 +213,7 @@ toremote(targ, argc, argv)
                targ = ".";
 
        if (thost = index(argv[argc - 1], '@')) {
                targ = ".";
 
        if (thost = index(argv[argc - 1], '@')) {
+               /* user@host */
                *thost++ = 0;
                tuser = argv[argc - 1];
                if (*tuser == '\0')
                *thost++ = 0;
                tuser = argv[argc - 1];
                if (*tuser == '\0')
@@ -235,7 +265,8 @@ toremote(targ, argc, argv)
                                host = thost;
 #ifdef KERBEROS
                                if (use_kerberos)
                                host = thost;
 #ifdef KERBEROS
                                if (use_kerberos)
-                                       kerberos(bp,
+                                       rem = kerberos(&host, bp,
+                                           pwd->pw_name,
                                            tuser ? tuser : pwd->pw_name);
                                else
 #endif
                                            tuser ? tuser : pwd->pw_name);
                                else
 #endif
@@ -244,6 +275,10 @@ toremote(targ, argc, argv)
                                            bp, 0);
                                if (rem < 0)
                                        exit(1);
                                            bp, 0);
                                if (rem < 0)
                                        exit(1);
+                               tos = IPTOS_THROUGHPUT;
+                               if (setsockopt(rem, IPPROTO_IP, IP_TOS,
+                                   (char *)&tos, sizeof(int)) < 0)
+                                       perror("rcp: setsockopt TOS (ignored)");
                                if (response() < 0)
                                        exit(1);
                                (void)free(bp);
                                if (response() < 0)
                                        exit(1);
                                (void)free(bp);
@@ -258,7 +293,7 @@ tolocal(argc, argv)
        int argc;
        char **argv;
 {
        int argc;
        char **argv;
 {
-       int i;
+       int i, tos;
        char *bp, *host, *src, *suser;
        char *colon(), *malloc();
 
        char *bp, *host, *src, *suser;
        char *colon(), *malloc();
 
@@ -294,57 +329,25 @@ tolocal(argc, argv)
                (void)sprintf(bp, "%s -f %s", cmd, src);
 #ifdef KERBEROS
                if (use_kerberos)
                (void)sprintf(bp, "%s -f %s", cmd, src);
 #ifdef KERBEROS
                if (use_kerberos)
-                       kerberos(bp, suser);
+                       rem = kerberos(&host, bp, pwd->pw_name, suser);
                else
 #endif
                        rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0);
                (void)free(bp);
                if (rem < 0)
                        continue;
                else
 #endif
                        rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0);
                (void)free(bp);
                if (rem < 0)
                        continue;
-               (void)setreuid(0, userid);
+               (void)seteuid(userid);
+               tos = IPTOS_THROUGHPUT;
+               if (setsockopt(rem, IPPROTO_IP, IP_TOS,
+                   (char *)&tos, sizeof(int)) < 0)
+                       perror("rcp: setsockopt TOS (ignored)");
                sink(1, argv + argc - 1);
                sink(1, argv + argc - 1);
-               (void)setreuid(userid, 0);
+               (void)seteuid(0);
                (void)close(rem);
                rem = -1;
        }
 }
 
                (void)close(rem);
                rem = -1;
        }
 }
 
-#ifdef KERBEROS
-kerberos(bp, user)
-       char *bp, *user;
-{
-       struct servent *sp;
-       char *host;
-
-again: rem = KSUCCESS;
-       if (krb_realm[0] == '\0')
-               rem = krb_get_lrealm(krb_realm, 1);
-       if (rem == KSUCCESS) {
-               if (encrypt)
-                       rem = krcmd_mutual(&host, port, user, bp, 0,
-                           krb_realm, &cred, schedule);
-               else
-                       rem = krcmd(&host, port, user, bp, 0, krb_realm);
-       } else {
-               (void)fprintf(stderr,
-                   "rcp: error getting local realm %s\n", krb_err_txt[rem]);
-               exit(1);
-       }
-       if (rem < 0 && errno == ECONNREFUSED) {
-               use_kerberos = 0;
-               old_warning("remote host doesn't support Kerberos");
-               sp = getservbyname("shell", "tcp");
-               if (sp == NULL) {
-                       (void)fprintf(stderr,
-                           "rcp: unknown service shell/tcp\n");
-                       exit(1);
-               }
-               port = sp->s_port;
-               goto again;
-       }
-}
-#endif /* KERBEROS */
-
 verifydir(cp)
        char *cp;
 {
 verifydir(cp)
        char *cp;
 {
@@ -395,7 +398,7 @@ susystem(s)
        char *s;
 {
        int status, pid, w;
        char *s;
 {
        int status, pid, w;
-       register int (*istat)(), (*qstat)();
+       register sig_t istat, qstat;
 
        if ((pid = vfork()) == 0) {
                (void)setuid(userid);
 
        if ((pid = vfork()) == 0) {
                (void)setuid(userid);
@@ -858,23 +861,88 @@ nospace()
        exit(1);
 }
 
        exit(1);
 }
 
-#ifdef KERBEROS
-old_warning(str)
-       char *str;
-{
-       (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str);
-}
-#endif
 
 usage()
 {
 #ifdef KERBEROS
 
 usage()
 {
 #ifdef KERBEROS
+#ifdef CRYPT
        (void)fprintf(stderr, "%s\n\t%s\n",
            "usage: rcp [-k realm] [-px] f1 f2",
            "or: rcp [-k realm] [-rpx] f1 ... fn directory");
        (void)fprintf(stderr, "%s\n\t%s\n",
            "usage: rcp [-k realm] [-px] f1 f2",
            "or: rcp [-k realm] [-rpx] f1 ... fn directory");
+#else
+       (void)fprintf(stderr, "%s\n\t%s\n",
+           "usage: rcp [-k realm] [-p] f1 f2",
+           "or: rcp [-k realm] [-rp] f1 ... fn directory");
+#endif
 #else
        (void)fprintf(stderr,
            "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n");
 #endif
        exit(1);
 }
 #else
        (void)fprintf(stderr,
            "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n");
 #endif
        exit(1);
 }
+
+#ifdef KERBEROS
+old_warning(str)
+       char *str;
+{
+       (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str);
+}
+
+int
+kerberos(host, bp, locuser, user)
+
+       char **host, *bp, *locuser, *user;
+{
+       struct servent *sp;
+
+again:
+       if (use_kerberos) {
+               rem = KSUCCESS;
+               errno = 0;
+               if (dest_realm == NULL)
+                       dest_realm = krb_realmofhost(*host);
+
+#ifdef CRYPT
+               if (encrypt)
+                       rem = krcmd_mutual(
+                               host, port,
+                               user, bp, 0,
+                               dest_realm,
+                               &cred, schedule);
+               else
+#endif
+                       rem = krcmd(
+                               host, port,
+                               user, bp, 0, dest_realm);
+
+               if (rem < 0) {
+                       use_kerberos = 0;
+                       sp = getservbyname("shell", "tcp");
+                       if (sp == NULL) {
+                               (void)fprintf(stderr,
+                                   "rcp: 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");
+                       port = sp->s_port;
+                       goto again;
+               }
+       } else {
+#ifdef CRYPT
+               if (encrypt) {
+                       fprintf(stderr,
+                           "The -x option requires Kerberos authentication\n");
+                       exit(1);
+               }
+#endif
+               rem = rcmd(host, sp->s_port, locuser, user, bp, 0);
+       }
+       return(rem);
+}
+#endif /* KERBEROS */