summaryrefslogtreecommitdiffstats
path: root/src/appl/bsd/krcp.c
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2009-11-22 14:58:54 +0000
committerGreg Hudson <ghudson@mit.edu>2009-11-22 14:58:54 +0000
commit14590b7c281e1fbf68afec2f3f4104b87e6010f4 (patch)
treee3f6c44278d9a69c45fbabd4b93146a99aa29244 /src/appl/bsd/krcp.c
parent829462f1ae36623021b57a03aa1e4e6bb2dfbb6d (diff)
downloadkrb5-14590b7c281e1fbf68afec2f3f4104b87e6010f4.tar.gz
krb5-14590b7c281e1fbf68afec2f3f4104b87e6010f4.tar.xz
krb5-14590b7c281e1fbf68afec2f3f4104b87e6010f4.zip
Unbundle applications into separate repository
Remove libpty, gssftp, telnet, and the bsd applications from the source tree, build system, and tests. Docs still need to be updated to remove mentions of the applications. The build system should be simplified now that we're down to one configure script and don't need some of the functionality currently in aclocal.m4. ticket: 6583 status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23305 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/appl/bsd/krcp.c')
-rw-r--r--src/appl/bsd/krcp.c1363
1 files changed, 0 insertions, 1363 deletions
diff --git a/src/appl/bsd/krcp.c b/src/appl/bsd/krcp.c
deleted file mode 100644
index 0d9089a476..0000000000
--- a/src/appl/bsd/krcp.c
+++ /dev/null
@@ -1,1363 +0,0 @@
-/*
- * appl/bsd/krcp.c
- */
-
-/*
- * 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-char copyright[] =
- "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-/* based on @(#)rcp.c 5.10 (Berkeley) 9/20/88 */
-
- /*
- * rcp
- */
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <sys/param.h>
-#ifndef _TYPES_
-#include <sys/types.h>
-#define _TYPES_
-#endif
-#include <sys/file.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-
-#include <netinet/in.h>
-
-#include <stdio.h>
-#include <signal.h>
-#include <pwd.h>
-#include <ctype.h>
-#include <netdb.h>
-#include <errno.h>
-#include <string.h>
-#ifdef HAVE_VFORK_H
-#include <vfork.h>
-#endif
-#include <stdarg.h>
-#include <sys/wait.h>
-
-#ifdef KERBEROS
-#include "k5-int.h"
-#include <k5-util.h>
-#include <com_err.h>
-
-#include "defines.h"
-
-#define RCP_BUFSIZ 4096
-
-int sock;
-char *krb_realm = NULL;
-char *krb_cache = NULL;
-char *krb_config = NULL;
-krb5_encrypt_block eblock; /* eblock for encrypt/decrypt */
-krb5_context bsd_context;
-
-void try_normal(char **);
-char **save_argv(int, char **);
-#ifndef HAVE_STRSAVE
-char *strsave();
-#endif
-int rcmd_stream_write(), rcmd_stream_read();
-void usage(void), sink(int, char **),
- source(int, char **), rsource(char *, struct stat *), verifydir(char *),
- answer_auth(char *, char *);
-int response(void), hosteq(char *, char *), okname(char *),
- susystem(char *);
-int encryptflag = 0;
-
-#ifndef UCB_RCP
-#define UCB_RCP "/bin/rcp"
-#endif
-
-#endif /* KERBEROS */
-
-int rem;
-char *colon(char *);
-int errs;
-krb5_sigtype lostconn(int);
-int iamremote, targetshouldbedirectory;
-int iamrecursive;
-int pflag;
-int forcenet;
-struct passwd *pwd;
-int userid;
-int port = 0;
-
-struct buffer {
- unsigned int cnt;
- char *buf;
-};
-
-struct buffer *allocbuf(struct buffer *, int, int);
-
-#define NULLBUF (struct buffer *) 0
-
-void error (char *fmt, ...)
-#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
- __attribute__ ((__format__ (__printf__, 1, 2)))
-#endif
- ;
-
-#define ga() (void) rcmd_stream_write(rem, "", 1, 0)
-
-int main(argc, argv)
- int argc;
- char **argv;
-{
- char *targ, *host, *src;
- char *suser, *tuser, *thost;
- int i;
- char buf[RCP_BUFSIZ], cmdbuf[30];
- char *cmd = cmdbuf;
- struct servent *sp;
- static char curhost[256];
-#ifdef POSIX_SIGNALS
- struct sigaction sa;
-#endif
-#ifdef KERBEROS
- krb5_flags authopts;
- krb5_error_code status;
- int euid;
- char **orig_argv = save_argv(argc, argv);
- krb5_auth_context auth_context;
- enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
-
- status = krb5_init_context(&bsd_context);
- if (status) {
- com_err(argv[0], status, "while initializing krb5");
- exit(1);
- }
-#endif
-
- pwd = getpwuid(userid = getuid());
- if (pwd == 0) {
- fprintf(stderr, "who are you?\n");
- exit(1);
- }
-
- for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
- (*argv)++;
- while (**argv) switch (*(*argv)++) {
-
- case 'r':
- iamrecursive++;
- break;
-
- case 'p': /* preserve mtimes and atimes */
- pflag++;
- break;
-
- case 'D':
- argc--, argv++;
- if (argc == 0)
- usage();
- port = htons(atoi(*argv));
- goto next_arg;
-
- case 'N':
- forcenet++;
- break;
-
-#ifdef KERBEROS
- case 'x':
- encryptflag++;
- break;
- case 'k': /* Change kerberos realm */
- argc--, argv++;
- if (argc == 0)
- usage();
- if(!(krb_realm = strdup(*argv))){
- fprintf(stderr, "rcp: Cannot malloc.\n");
- exit(1);
- }
- goto next_arg;
- case 'c': /* Change default ccache file */
- argc--, argv++;
- if (argc == 0)
- usage();
- if(!(krb_cache = strdup(*argv))){
- fprintf(stderr, "rcp: Cannot malloc.\n");
- exit(1);
- }
- goto next_arg;
- case 'C': /* Change default config file */
- argc--, argv++;
- if (argc == 0)
- usage();
- if(!(krb_config = strdup(*argv))){
- fprintf(stderr, "rcp: Cannot malloc.\n");
- exit(1);
- }
- goto next_arg;
- case 'P':
- if (!strcmp (*argv, "O"))
- kcmd_proto = KCMD_OLD_PROTOCOL;
- else if (!strcmp (*argv, "N"))
- kcmd_proto = KCMD_NEW_PROTOCOL;
- else
- usage ();
- goto next_arg;
-#endif /* KERBEROS */
- /* The rest of these are not for users. */
- case 'd':
- targetshouldbedirectory = 1;
- break;
-
- case 'f': /* "from" */
- iamremote = 1;
- rcmd_stream_init_normal();
-#if defined(KERBEROS)
- if (encryptflag)
- answer_auth(krb_config, krb_cache);
-#endif /* KERBEROS */
-
- (void) response();
- source(--argc, ++argv);
- exit(errs);
-
- case 't': /* "to" */
- iamremote = 1;
- rcmd_stream_init_normal();
-#if defined(KERBEROS)
- if (encryptflag)
- answer_auth(krb_config, krb_cache);
-#endif /* KERBEROS */
-
- sink(--argc, ++argv);
- exit(errs);
-
- default:
- usage();
- }
- next_arg: ;
- }
-
- if (argc < 2)
- usage();
- if (argc > 2)
- targetshouldbedirectory = 1;
- rem = -1;
-
-
- if (port == 0) {
-#ifdef KERBEROS
- sp = getservbyname("kshell", "tcp");
-#else
- sp = getservbyname("shell", "tcp");
-#endif /* KERBEROS */
-
- if (sp == NULL) {
-#ifdef KERBEROS
- fprintf(stderr, "rcp: kshell/tcp: unknown service\n");
- try_normal(orig_argv);
-#else
- fprintf(stderr, "rcp: shell/tcp: unknown service\n");
- exit(1);
-#endif /* KERBEROS */
- }
- port = sp->s_port;
- }
-
-#ifdef KERBEROS
- if (asprintf(&cmd, "%srcp %s%s%s%s%s%s%s%s%s",
- encryptflag ? "-x " : "",
-
- iamrecursive ? " -r" : "", pflag ? " -p" : "",
- targetshouldbedirectory ? " -d" : "",
- krb_realm != NULL ? " -k " : "",
- krb_realm != NULL ? krb_realm : "",
- krb_cache != NULL ? " -c " : "",
- krb_cache != NULL ? krb_cache : "",
- krb_config != NULL ? " -C " : "",
- krb_config != NULL ? krb_config : "") < 0) {
- fprintf(stderr, "rcp: Cannot malloc.\n");
- exit(1);
- }
-
-#else /* !KERBEROS */
- (void) snprintf(cmd, sizeof(cmdbuf), "rcp%s%s%s",
- iamrecursive ? " -r" : "", pflag ? " -p" : "",
- targetshouldbedirectory ? " -d" : "");
-#endif /* KERBEROS */
-
-#ifdef POSIX_SIGNALS
- (void) sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = lostconn;
- (void) sigaction(SIGPIPE, &sa, (struct sigaction *)0);
-#else
- (void) signal(SIGPIPE, lostconn);
-#endif
- targ = colon(argv[argc - 1]);
-
- /* Check if target machine is the current machine. */
-
- gethostname(curhost, sizeof(curhost));
- if (targ) { /* ... to remote */
- *targ++ = 0;
- if (hosteq(argv[argc - 1], curhost)) {
-
- /* If so, pretend there wasn't even one given
- * check for an argument of just "host:", it
- * should become "."
- */
-
- if (*targ == 0) {
- targ = ".";
- argv[argc - 1] = targ;
- }
- else
- argv[argc - 1] = targ;
- targ = 0;
- }
- }
- if (targ) {
- /* Target machine is some remote machine */
- if (*targ == 0)
- targ = ".";
- thost = strchr(argv[argc - 1], '@');
- if (thost) {
- *thost++ = 0;
- tuser = argv[argc - 1];
- if (*tuser == '\0')
- tuser = NULL;
- else if (!okname(tuser))
- exit(1);
- } else {
- thost = argv[argc - 1];
- tuser = NULL;
- }
- for (i = 0; i < argc - 1; i++) {
- src = colon(argv[i]);
- if (src) { /* remote to remote */
- *src++ = 0;
- if (*src == 0)
- src = ".";
- host = strchr(argv[i], '@');
- if (host) {
- *host++ = 0;
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
- continue;
- (void) snprintf(buf, sizeof(buf),
-#if defined(hpux) || defined(__hpux)
- "remsh %s -l %s -n %s %s '%s%s%s:%s'",
-#else
- "rsh %s -l %s -n %s %s '%s%s%s:%s'",
-#endif
- host, suser, cmd, src,
- tuser ? tuser : "",
- tuser ? "@" : "",
- thost, targ);
- } else
- (void) snprintf(buf, sizeof(buf),
-#if defined(hpux) || defined(__hpux)
- "remsh %s -n %s %s '%s%s%s:%s'",
-#else
- "rsh %s -n %s %s '%s%s%s:%s'",
-#endif
- argv[i], cmd, src,
- tuser ? tuser : "",
- tuser ? "@" : "",
- thost, targ);
- (void) susystem(buf);
- } else { /* local to remote */
- krb5_creds *cred;
- if (rem == -1) {
- (void) snprintf(buf, sizeof(buf), "%s -t %s",
- cmd, targ);
- host = thost;
-#ifdef KERBEROS
- authopts = AP_OPTS_MUTUAL_REQUIRED;
- status = kcmd(&sock, &host,
- port,
- pwd->pw_name,
- tuser ? tuser :
- pwd->pw_name,
- buf,
- 0,
- "host",
- krb_realm,
- &cred,
- 0, /* No seq # */
- 0, /* No server seq # */
- (struct sockaddr_in *) 0,
- (struct sockaddr_in *) 0,
- &auth_context, authopts,
- 0, /* Not any port # */
- 0,
- &kcmd_proto);
- if (status) {
- if (kcmd_proto == KCMD_NEW_PROTOCOL)
- /* Don't fall back to less safe methods. */
- exit (1);
- try_normal(orig_argv);
- }
- else {
- krb5_boolean similar;
- krb5_keyblock *key = &cred->keyblock;
-
- status = krb5_c_enctype_compare(bsd_context,
- ENCTYPE_DES_CBC_CRC,
- cred->keyblock.enctype,
- &similar);
- if (status)
- try_normal(orig_argv); /* doesn't return */
-
- if (!similar) {
- status = krb5_auth_con_getsendsubkey (bsd_context,
- auth_context,
- &key);
- if ((status || !key) && encryptflag)
- try_normal(orig_argv);
- }
- if (key == 0)
- key = &cred->keyblock;
-
- rcmd_stream_init_krb5(key, encryptflag, 0, 1,
- kcmd_proto);
- }
- rem = sock;
-#else
- rem = rcmd(&host, port, pwd->pw_name,
- tuser ? tuser : pwd->pw_name,
- buf, 0);
- if (rem < 0)
- exit(1);
-#endif /* KERBEROS */
- if (response() < 0)
- exit(1);
- }
- source(1, argv+i);
- }
- }
- } else { /* ... to local */
- if (targetshouldbedirectory)
- verifydir(argv[argc - 1]);
- for (i = 0; i < argc - 1; i++) {
- src = colon(argv[i]);
- /* Check if source machine is current machine */
- if (src) {
- *src++ = 0;
- if (hosteq(argv[i], curhost)) {
-
- /* If so, pretend src machine never given */
-
- if (*src == 0) {
- error("rcp: no path given in arg: %s:\n",
- argv[i]);
- errs++;
- continue;
- }
- argv[i] = src;
- src = 0;
- } else {
- /* not equiv, return colon */
- *(--src) = ':';
- }
- }
- if (src == 0) { /* local to local */
- (void) snprintf(buf, sizeof(buf), "/bin/cp%s%s %s %s",
- iamrecursive ? " -r" : "",
- pflag ? " -p" : "",
- argv[i], argv[argc - 1]);
- (void) susystem(buf);
- } else { /* remote to local */
- krb5_creds *cred;
- *src++ = 0;
- if (*src == 0)
- src = ".";
- host = strchr(argv[i], '@');
- if (host) {
- *host++ = 0;
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
- continue;
- } else {
- host = argv[i];
- suser = pwd->pw_name;
- }
- (void) snprintf(buf, sizeof(buf), "%s -f %s", cmd, src);
-#ifdef KERBEROS
- authopts = AP_OPTS_MUTUAL_REQUIRED;
- status = kcmd(&sock, &host,
- port,
- pwd->pw_name, suser,
- buf,
- 0,
- "host",
- krb_realm,
- &cred,
- 0, /* No seq # */
- 0, /* No server seq # */
- (struct sockaddr_in *) 0,
- (struct sockaddr_in *) 0,
- &auth_context, authopts,
- 0, /* Not any port # */
- 0,
- &kcmd_proto);
- if (status) {
- if (kcmd_proto == KCMD_NEW_PROTOCOL)
- /* Don't fall back to less safe methods. */
- exit (1);
- try_normal(orig_argv);
- } else {
- krb5_keyblock *key = &cred->keyblock;
-
- if (kcmd_proto == KCMD_NEW_PROTOCOL) {
- status = krb5_auth_con_getsendsubkey (bsd_context,
- auth_context,
- &key);
- if (status) {
- com_err (argv[0], status,
- "determining subkey for session");
- exit (1);
- }
- if (!key) {
- com_err (argv[0], 0,
- "no subkey negotiated for connection");
- exit (1);
- }
- }
-
- rcmd_stream_init_krb5(key, encryptflag, 0, 1, kcmd_proto);
- }
- rem = sock;
-
- euid = geteuid();
- if (euid == 0) {
- if (setuid(0)) {
- perror("rcp setuid 0"); errs++; exit(errs);
- }
- if(krb5_seteuid(userid)) {
- perror("rcp seteuid user"); errs++; exit(errs);
- }
- }
- sink(1, argv+argc-1);
- if (euid == 0) {
- if(krb5_seteuid(0)) {
- perror("rcp seteuid 0"); errs++; exit(errs);
- }
- }
-#else
- rem = rcmd(&host, port, pwd->pw_name, suser,
- buf, 0);
- if (rem < 0)
- continue;
- rcmd_stream_init_normal();
-#ifdef HAVE_SETREUID
- if (setreuid(0, userid)) {
- perror("rcp setreuid 0,user"); errs++; exit(errs);
- }
- sink(1, argv+argc-1);
- if (setreuid(userid, 0)) {
- perror("rcp setreuid user,0"); errs++; exit(errs);
- }
-#else
- if (setuid(0)) {
- perror("rcp setuid 0"); errs++; exit(errs);
- }
- if(seteuid(userid)) {
- perror("rcp seteuid user"); errs++; exit(errs);
- }
- sink(1, argv+argc-1);
- if(seteuid(0)) {
- perror("rcp seteuid 0"); errs++; exit(errs);
- }
-#endif
-#endif /* KERBEROS */
- (void) close(rem);
- rem = -1;
- }
- }
- }
- exit(errs);
-}
-
-
-
-void verifydir(cp)
- char *cp;
-{
- struct stat stb;
-
- if (stat(cp, &stb) >= 0) {
- if ((stb.st_mode & S_IFMT) == S_IFDIR)
- return;
- errno = ENOTDIR;
- }
- error("rcp: %s: %s.\n", cp, error_message(errno));
- exit(1);
-}
-
-
-
-char *colon(cp)
- char *cp;
-{
-
- while (*cp) {
- if (*cp == ':')
- return (cp);
- if (*cp == '/')
- return (0);
- cp++;
- }
- return (0);
-}
-
-
-
-int okname(cp0)
- char *cp0;
-{
- register char *cp = cp0;
- register int c;
-
- do {
- c = *cp;
- if (c & 0200)
- goto bad;
- if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
- goto bad;
- cp++;
- } while (*cp);
- return (1);
- bad:
- fprintf(stderr, "rcp: invalid user name %s\n", cp0);
- return (0);
-}
-
-
-
-int susystem(s)
- char *s;
-{
- int status;
- pid_t pid, w;
-#ifdef POSIX_SIGNALS
- struct sigaction sa, isa, qsa;
-#else
- register krb5_sigtype (bsd_context, *istat)(), (*qstat)();
-#endif
-
- if ((pid = vfork()) == 0) {
- execl("/bin/sh", "sh", "-c", s, (char *)0);
- _exit(127);
- }
-
-#ifdef POSIX_SIGNALS
- (void) sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = SIG_IGN;
- (void) sigaction(SIGINT, &sa, &isa);
- (void) sigaction(SIGQUIT, &sa, &qsa);
-#else
- istat = signal(SIGINT, SIG_IGN);
- qstat = signal(SIGQUIT, SIG_IGN);
-#endif
-
-#ifdef HAVE_WAITPID
- w = waitpid(pid, &status, 0);
-#else
- while ((w = wait(&status)) != pid && w != -1) /*void*/ ;
-#endif
- if (w == (pid_t)-1)
- status = -1;
-
-#ifdef POSIX_SIGNALS
- (void) sigaction(SIGINT, &isa, (struct sigaction *)0);
- (void) sigaction(SIGQUIT, &qsa, (struct sigaction *)0);
-#else
- (void) signal(SIGINT, istat);
- (void) signal(SIGQUIT, qstat);
-#endif
-
- return (status);
-}
-
-void source(argc, argv)
- int argc;
- char **argv;
-{
- char *last, *name;
- struct stat stb;
- static struct buffer buffer;
- struct buffer *bp;
- int x, readerr, f;
- unsigned int amt;
- off_t i;
- char buf[RCP_BUFSIZ];
-
- for (x = 0; x < argc; x++) {
- name = argv[x];
- if ((f = open(name, 0)) < 0) {
- error("rcp: %s: %s\n", name, error_message(errno));
- continue;
- }
- if (fstat(f, &stb) < 0)
- goto notreg;
- switch (stb.st_mode&S_IFMT) {
-
- case S_IFREG:
- break;
-
- case S_IFDIR:
- if (iamrecursive) {
- (void) close(f);
- rsource(name, &stb);
- continue;
- }
- /* fall into ... */
- default:
- notreg:
- (void) close(f);
- error("rcp: %s: not a plain file\n", name);
- continue;
- }
- last = strrchr(name, '/');
- if (last == 0)
- last = name;
- else
- last++;
- if (pflag) {
- /*
- * Make it compatible with possible future
- * versions expecting microseconds.
- */
- (void) snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
- stb.st_mtime, stb.st_atime);
- (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
- if (response() < 0) {
- (void) close(f);
- continue;
- }
- }
- (void) snprintf(buf, sizeof(buf), "C%04o %ld %s\n",
- (int) stb.st_mode&07777, (long ) stb.st_size, last);
- (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
- if (response() < 0) {
- (void) close(f);
- continue;
- }
- if ((bp = allocbuf(&buffer, f, RCP_BUFSIZ)) == NULLBUF) {
- (void) close(f);
- continue;
- }
- readerr = 0;
- for (i = 0; i < stb.st_size; i += bp->cnt) {
- amt = bp->cnt;
- if (i + amt > stb.st_size)
- amt = stb.st_size - i;
- if (readerr == 0 && read(f, bp->buf, amt) != amt)
- readerr = errno;
- (void) rcmd_stream_write(rem, bp->buf, amt, 0);
- }
- (void) close(f);
- if (readerr == 0)
- ga();
- else
- error("rcp: %s: %s\n", name, error_message(readerr));
- (void) response();
- }
-}
-
-
-
-#ifndef USE_DIRENT_H
-#include <sys/dir.h>
-#else
-#include <dirent.h>
-#endif
-
-void rsource(name, statp)
- char *name;
- struct stat *statp;
-{
- DIR *d = opendir(name);
- char *last;
-#ifdef USE_DIRENT_H
- struct dirent *dp;
-#else
- struct direct *dp;
-#endif
- char buf[RCP_BUFSIZ];
- char *bufv[1];
-
- if (d == 0) {
- error("rcp: %s: %s\n", name, error_message(errno));
- return;
- }
- last = strrchr(name, '/');
- if (last == 0)
- last = name;
- else
- last++;
- if (pflag) {
- (void) snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
- statp->st_mtime, statp->st_atime);
- (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
- if (response() < 0) {
- closedir(d);
- return;
- }
- }
- (void) snprintf(buf, sizeof(buf), "D%04lo %d %s\n",
- (long) statp->st_mode&07777, 0, last);
- (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
- if (response() < 0) {
- closedir(d);
- return;
- }
- while ((dp = readdir(d)) != NULL) {
- if (dp->d_ino == 0)
- continue;
- if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
- continue;
- if (strlen(name) + 1 + strlen(dp->d_name) >= RCP_BUFSIZ - 1) {
- error("%s/%s: Name too long.\n", name, dp->d_name);
- continue;
- }
- (void) snprintf(buf, sizeof(buf), "%s/%s", name, dp->d_name);
- bufv[0] = buf;
- source(1, bufv);
- }
- closedir(d);
- (void) rcmd_stream_write(rem, "E\n", 2, 0);
- (void) response();
-}
-
-
-
-int response()
-{
- char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
- if (rcmd_stream_read(rem, &resp, 1, 0) != 1)
- lostconn(0);
- switch (resp) {
-
- case 0: /* ok */
- return (0);
-
- default:
- *cp++ = resp;
- /* fall into... */
- case 1: /* error, followed by err msg */
- case 2: /* fatal error, "" */
- do {
- if (rcmd_stream_read(rem, &c, 1, 0) != 1)
- lostconn(0);
- *cp++ = c;
- } while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
- if (iamremote == 0)
- (void) write(2, rbuf, (unsigned) (cp - rbuf));
- errs++;
- if (resp == 1)
- return (-1);
- exit(1);
- }
- /*NOTREACHED*/
-}
-
-
-
-krb5_sigtype
- lostconn(signumber)
- int signumber;
-{
- if (iamremote == 0)
- fprintf(stderr, "rcp: lost connection\n");
- exit(1);
-}
-
-
-#if !defined(HAVE_UTIMES)
-#include <utime.h>
-#include <sys/time.h>
-
-/*
- * We emulate utimes() instead of utime() as necessary because
- * utimes() is more powerful than utime(), and rcp actually tries to
- * set the microsecond values; we don't want to take away
- * functionality unnecessarily.
- */
-int utimes(file, tvp)
-const char *file;
-struct timeval *tvp;
-{
- struct utimbuf times;
-
- times.actime = tvp[0].tv_sec;
- times.modtime = tvp[1].tv_sec;
- return(utime(file, &times));
-}
-#endif
-
-
-void sink(argc, argv)
- int argc;
- char **argv;
-{
- mode_t mode;
- mode_t mask = umask(0);
- off_t i, j;
- char *targ, *whopp, *cp;
- int of, wrerr, exists, first;
- off_t size;
- unsigned int amt, count;
- struct buffer *bp;
- static struct buffer buffer;
- struct stat stb;
- int targisdir = 0;
- char *myargv[1];
- char cmdbuf[RCP_BUFSIZ], nambuf[RCP_BUFSIZ];
- int setimes = 0;
- struct timeval tv[2];
-#define atime tv[0]
-#define mtime tv[1]
-#define SCREWUP(str) { whopp = str; goto screwup; }
-
- if (!pflag)
- (void) umask(mask);
- if (argc != 1) {
- error("rcp: ambiguous target\n");
- exit(1);
- }
- targ = *argv;
- if (targetshouldbedirectory)
- verifydir(targ);
- ga();
- if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
- targisdir = 1;
- for (first = 1; ; first = 0) {
- cp = cmdbuf;
- if (rcmd_stream_read(rem, cp, 1, 0) <= 0)
- return;
- if (*cp++ == '\n')
- SCREWUP("unexpected '\\n'");
- do {
- if (rcmd_stream_read(rem, cp, 1, 0) != 1)
- SCREWUP("lost connection");
- } while (*cp++ != '\n');
- *cp = 0;
- if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
- if (iamremote == 0)
- (void) write(2, cmdbuf+1, strlen(cmdbuf+1));
- if (cmdbuf[0] == '\02')
- exit(1);
- errs++;
- continue;
- }
- *--cp = 0;
- cp = cmdbuf;
- if (*cp == 'E') {
- ga();
- return;
- }
-
-#define getnum(t) (t) = 0; while (isdigit((int) *cp)) (t) = (t) * 10 + (*cp++ - '0');
- if (*cp == 'T') {
- setimes++;
- cp++;
- getnum(mtime.tv_sec);
- if (*cp++ != ' ')
- SCREWUP("mtime.sec not delimited");
- getnum(mtime.tv_usec);
- if (*cp++ != ' ')
- SCREWUP("mtime.usec not delimited");
- getnum(atime.tv_sec);
- if (*cp++ != ' ')
- SCREWUP("atime.sec not delimited");
- getnum(atime.tv_usec);
- if (*cp++ != '\0')
- SCREWUP("atime.usec not delimited");
- ga();
- continue;
- }
- if (*cp != 'C' && *cp != 'D') {
- /*
- * Check for the case "rcp remote:foo\* local:bar".
- * In this case, the line "No match." can be returned
- * by the shell before the rcp command on the remote is
- * executed so the ^Aerror_message convention isn't
- * followed.
- */
- if (first) {
- error("%s\n", cp);
- exit(1);
- }
- SCREWUP("expected control record");
- }
- cp++;
- mode = 0;
- for (; cp < cmdbuf+5; cp++) {
- if (*cp < '0' || *cp > '7')
- SCREWUP("bad mode");
- mode = (mode << 3) | (*cp - '0');
- }
- if (*cp++ != ' ')
- SCREWUP("mode not delimited");
- size = 0;
- while (isdigit((int) *cp))
- size = size * 10 + (*cp++ - '0');
- if (*cp++ != ' ')
- SCREWUP("size not delimited");
- if (targisdir) {
- if(strlen(targ) + strlen(cp) + 2 >= sizeof(nambuf))
- SCREWUP("target name too long");
- (void) snprintf(nambuf, sizeof(nambuf), "%s%s%s", targ,
- *targ ? "/" : "", cp);
- } else {
- if (strlen(targ) + 1 >= sizeof (nambuf))
- SCREWUP("target name too long");
- (void) strncpy(nambuf, targ, sizeof(nambuf) - 1);
- }
- nambuf[sizeof(nambuf) - 1] = '\0';
- exists = stat(nambuf, &stb) == 0;
- if (cmdbuf[0] == 'D') {
- if (exists) {
- if ((stb.st_mode&S_IFMT) != S_IFDIR) {
- errno = ENOTDIR;
- goto bad;
- }
- if (pflag)
- (void) chmod(nambuf, mode);
- } else if (mkdir(nambuf, mode) < 0)
- goto bad;
- myargv[0] = nambuf;
- sink(1, myargv);
- if (setimes) {
- setimes = 0;
- if (utimes(nambuf, tv) < 0)
- error("rcp: can't set times on %s: %s\n",
- nambuf, error_message(errno));
- }
- continue;
- }
- if ((of = open(nambuf, O_WRONLY|O_CREAT, mode)) < 0) {
- bad:
- error("rcp: %s: %s\n", nambuf, error_message(errno));
- continue;
- }
- if (exists && pflag) {
-#ifdef NOFCHMOD
- (void) chmod(nambuf, mode);
-#else
- (void) fchmod(of, mode);
-#endif
- }
- ga();
- if ((bp = allocbuf(&buffer, of, RCP_BUFSIZ)) == NULLBUF) {
- (void) close(of);
- continue;
- }
- cp = bp->buf;
- count = 0;
- wrerr = 0;
- for (i = 0; i < size; i += RCP_BUFSIZ) {
- amt = RCP_BUFSIZ;
- if (i + amt > size)
- amt = size - i;
- count += amt;
- do {
- j = rcmd_stream_read(rem, cp, amt, 0);
- if (j <= 0) {
- if (j == 0)
- error("rcp: dropped connection");
- else
- error("rcp: %s\n", error_message(errno));
- exit(1);
- }
- amt -= j;
- cp += j;
- } while (amt > 0);
- if (count == bp->cnt) {
- if (wrerr == 0 &&
- write(of, bp->buf, count) != count)
- wrerr++;
- count = 0;
- cp = bp->buf;
- }
- }
- if (count != 0 && wrerr == 0 &&
- write(of, bp->buf, count) != count)
- wrerr++;
- if (ftruncate(of, size))
- error("rcp: can't truncate %s: %s\n", nambuf, error_message(errno));
- if (close(of) != 0)
- error("rcp: error closing %s: %s\n", nambuf, error_message(errno));
- (void) response();
- if (setimes) {
- setimes = 0;
- if (utimes(nambuf, tv) < 0)
- error("rcp: can't set times on %s: %s\n",
- nambuf, error_message(errno));
- }
- if (wrerr)
- error("rcp: %s: %s\n", nambuf, error_message(errno));
- else
- ga();
- }
- screwup:
- error("rcp: protocol screwup: %s\n", whopp);
- exit(1);
-}
-
-
-
-struct buffer *allocbuf(bp, fd, blksize)
- struct buffer *bp;
- int fd, blksize;
-{
- struct stat stb;
- int size;
-
- if (fstat(fd, &stb) < 0) {
- error("rcp: fstat: %s\n", error_message(errno));
- return (NULLBUF);
- }
-
- size = blksize;
- if (bp->cnt < size) {
- if (bp->buf != 0)
- free(bp->buf);
- bp->buf = (char *)malloc((unsigned) size);
- if (bp->buf == 0) {
- error("rcp: malloc: out of memory\n");
- return (NULLBUF);
- }
- }
- bp->cnt = size;
- return (bp);
-}
-
-void
-#ifdef HAVE_STDARG_H
-error(char *fmt, ...)
-#else
-/*VARARGS1*/
-error(fmt, va_alist)
- char *fmt;
- va_dcl
-#endif
-{
- va_list ap;
- char buf[RCP_BUFSIZ], *cp = buf;
-
-#ifdef HAVE_STDARG_H
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
-
- errs++;
- *cp++ = 1;
- (void) vsnprintf(cp, sizeof(buf) - (cp - buf), fmt, ap);
- va_end(ap);
-
- if (iamremote)
- (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
- else
- (void) write(2, buf+1, strlen(buf+1));
-}
-
-
-
-void usage()
-{
-#ifdef KERBEROS
- fprintf(stderr,
- "Usage: \trcp [-PN | -PO] [-p] [-x] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-x] [-k realm] f1 ... fn d2\n");
-#else
- fputs("usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n", stderr);
-#endif
- exit(1);
-}
-
-
-
-int hosteq(h1, h2)
- char *h1, *h2;
-{
- struct hostent *h_ptr;
- char hname1[256];
-
- if (forcenet)
- return(0);
-
- /* get the official names for the two hosts */
-
- if ((h_ptr = gethostbyname(h1)) == NULL)
- return(0);
- strncpy(hname1, h_ptr->h_name, sizeof (hname1));
- hname1[sizeof (hname1) - 1] = '\0';
- if ((h_ptr = gethostbyname(h2)) == NULL)
- return(0);
-
- /*return if they are equal (strcmp returns 0 for equal - I return 1) */
-
- return(!strcmp(hname1, h_ptr->h_name));
-}
-
-
-
-#ifdef KERBEROS
-void try_normal(argv)
- char **argv;
-{
- register int i;
-#ifndef KRB5_ATHENA_COMPAT
- if (!encryptflag)
-#endif
- {
- fprintf(stderr,"trying normal rcp (%s)\n", UCB_RCP);
- fflush(stderr);
- /* close all but stdin, stdout, stderr */
- for (i = getdtablesize(); i > 2; i--)
- (void) close(i);
- execv(UCB_RCP, argv);
- perror("exec");
- }
- exit(1);
-}
-
-
-
-char **save_argv(argc, argv)
- int argc;
- char **argv;
-{
- register int i;
-
- char **local_argv = (char **)calloc((unsigned) argc+1,
- (unsigned) sizeof(char *));
- /* allocate an extra pointer, so that it is initialized to NULL
- and execv() will work */
- for (i = 0; i < argc; i++)
- local_argv[i] = strsave(argv[i]);
- return(local_argv);
-}
-
-
-
-#ifdef unicos61
-#define SIZEOF_INADDR SIZEOF_in_addr
-#else
-#define SIZEOF_INADDR sizeof(struct in_addr)
-#endif
-
-
-/* This function is mostly vestigial, since under normal operation
- * the -x flag doesn't get set for the server process for encrypted
- * rcp. It only gets called by beta clients attempting user-to-user
- * authentication. */
-void
- answer_auth(config_file, ccache_file)
- char *config_file;
- char *ccache_file;
-{
- krb5_data pname_data, msg;
- krb5_creds creds, *new_creds;
- krb5_ccache cc;
- krb5_error_code status;
- krb5_auth_context auth_context = NULL;
-
- if (config_file) {
- const char * filenames[2];
- filenames[1] = NULL;
- filenames[0] = config_file;
- if ((status = krb5_set_config_files(bsd_context, filenames)))
- exit(1);
- }
-
- memset (&creds, 0, sizeof(creds));
-
- if ((status = krb5_read_message(bsd_context, (krb5_pointer)&rem,
- &pname_data)))
- exit(1);
-
- if ((status = krb5_read_message(bsd_context, (krb5_pointer) &rem,
- &creds.second_ticket)))
- exit(1);
-
- if (ccache_file == NULL) {
- if ((status = krb5_cc_default(bsd_context, &cc)))
- exit(1);
- } else {
- if ((status = krb5_cc_resolve(bsd_context, ccache_file, &cc)))
- exit(1);
- }
-
- if ((status = krb5_cc_get_principal(bsd_context, cc, &creds.client)))
- exit(1);
-
- if ((status = krb5_parse_name(bsd_context, pname_data.data,
- &creds.server)) )
- exit(1);
-
- krb5_free_data_contents(bsd_context, &pname_data);
-
- if ((status = krb5_get_credentials(bsd_context, KRB5_GC_USER_USER, cc,
- &creds, &new_creds)))
- exit(1);
-
- if ((status = krb5_mk_req_extended(bsd_context, &auth_context,
- AP_OPTS_USE_SESSION_KEY,
- NULL, new_creds, &msg)))
- exit(1);
-
- if ((status = krb5_write_message(bsd_context, (krb5_pointer) &rem,
- &msg))) {
- krb5_free_data_contents(bsd_context, &msg);
- exit(1);
- }
-
- rcmd_stream_init_krb5(&new_creds->keyblock, encryptflag, 0, 0,
- KCMD_OLD_PROTOCOL);
-
- /* cleanup */
- krb5_free_cred_contents(bsd_context, &creds);
- krb5_free_creds(bsd_context, new_creds);
- krb5_free_data_contents(bsd_context, &msg);
-
- return;
-}
-
-
-
-char storage[2*RCP_BUFSIZ]; /* storage for the decryption */
-int nstored = 0;
-char *store_ptr = storage;
-
-#endif /* KERBEROS */