diff options
author | Greg Hudson <ghudson@mit.edu> | 2008-12-15 20:29:01 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2008-12-15 20:29:01 +0000 |
commit | 9cefbad7f53cffbe75044262b98bd34ebe3ae2fd (patch) | |
tree | 48388ecc268a7e39cb8ebc1a9d3783ccd21631a7 /src/appl/bsd/v4rcp.c | |
parent | 38d175630716003c7c4fe9eb5284a66aedf1e119 (diff) | |
download | krb5-9cefbad7f53cffbe75044262b98bd34ebe3ae2fd.tar.gz krb5-9cefbad7f53cffbe75044262b98bd34ebe3ae2fd.tar.xz krb5-9cefbad7f53cffbe75044262b98bd34ebe3ae2fd.zip |
Remove krb4 support in the applications. login's ability to run aklog
has been preserved and made unconditional on krb4 support, since aklog
can now do krb5 auth. The config variable is now named krb_run_aklog
(as it was sometimes documented), not krb4_run_aklog as it previously
was.
ticket: 6303
status: open
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21450 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/appl/bsd/v4rcp.c')
-rw-r--r-- | src/appl/bsd/v4rcp.c | 1110 |
1 files changed, 0 insertions, 1110 deletions
diff --git a/src/appl/bsd/v4rcp.c b/src/appl/bsd/v4rcp.c deleted file mode 100644 index 85357e997..000000000 --- a/src/appl/bsd/v4rcp.c +++ /dev/null @@ -1,1110 +0,0 @@ -/* Stripped down Kerberos V4 rcp, for server-side use only */ -/* based on Cygnus CNS V4-96q1 src/appl/bsd/rcp.c. */ - -/* - * rcp.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 */ - -#ifndef lint -static char sccsid[] = "@(#)rcp.c 5.10 (Berkeley) 9/20/88"; -#endif /* not lint */ - -/* - * rcp - */ -#ifdef KERBEROS -#include "k5-int.h" -#include <com_err.h> -#include <k5-util.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#ifndef KERBEROS -/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */ -#include <sys/socket.h> -#endif -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#ifdef NEED_SYS_FCNTL_H -#include <sys/fcntl.h> -#endif -#include <netinet/in.h> - -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <signal.h> -#include <pwd.h> -#include <ctype.h> -#ifndef KERBEROS -/* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */ -#include <netdb.h> -#endif -#include <errno.h> -#include <stdarg.h> - -#include "port-sockets.h" - -#ifdef KERBEROS -#include <krb.h> -#include <krbports.h> - - -void sink(int, char **), source(int, char **), - rsource(char *, struct stat *), usage(void); -/*VARARGS*/ -void error (char *fmt, ...) -#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) - __attribute__ ((__format__ (__printf__, 1, 2))) -#endif - ; -int response(void); -#if !defined(HAVE_UTIMES) -int utimes(); -#endif - - -#if 0 -#include <kstream.h> -#else -/* we don't have full kstream in v5, so fake it... */ - -typedef struct { - int encrypting; - int read_fd, write_fd; - des_key_schedule *sched; - des_cblock *ivec; - /* used on the read side */ - char *inbuf; - char *outbuf; - int writelen; - char* retbuf; - int retbuflen; - int retlen; - int returned; -} *kstream; - -static kstream kstream_create_rcp_from_fd(read_fd, write_fd, sched, ivec) - int read_fd, write_fd; - des_key_schedule *sched; - des_cblock *ivec; -{ - kstream tmp = (kstream)malloc(sizeof(*tmp)); - if (tmp == NULL) - return NULL; - tmp->encrypting = 1; - tmp->read_fd = read_fd; - tmp->write_fd = write_fd; - /* they're static in this file, so just hang on to the pointers */ - tmp->sched = sched; - tmp->ivec = ivec; - tmp->inbuf = 0; - tmp->outbuf = 0; - tmp->writelen = 0; - tmp->retbuf = 0; - tmp->retbuflen = 0; - tmp->returned = 0; - tmp->retlen = 0; - return tmp; -} - -static kstream kstream_create_from_fd(read_fd, write_fd, sched, session) - int read_fd, write_fd; - Key_schedule *sched; - des_cblock *session; -{ - /* just set it up... */ - kstream tmp = (kstream)malloc(sizeof(*tmp)); - if (tmp == NULL) - return NULL; - tmp->encrypting = 0; - tmp->read_fd = read_fd; - tmp->write_fd = write_fd; - return tmp; -} - - -/* always set to 0 here anyway */ -#define kstream_set_buffer_mode(x,y) - -static int kstream_read(krem, buf, len) - kstream krem; - char *buf; - unsigned int len; -{ - if(krem->encrypting) { - /* when we get a length, we have to read the whole block. However, - we have to hand it to the user in the chunks they want, which - may be smaller if BUFSIZ doesn't match. [the caller can deal if - the incoming blocks are smaller...] */ - if (krem->returned) { - int remaining = krem->retlen - krem->returned; - int returning; - - if (remaining <= len) { - returning = remaining; - } else { - returning = len; - } - memcpy(buf, krem->retbuf+krem->returned, returning); - krem->returned += returning; - if (krem->returned == krem->retlen) krem->returned = 0; - - return returning; - } - - /* we need 4 bytes to get a length, and once we have that we know how - much to get to fill the buffer. Then we can hand back bits, or loop. */ - { - int cc; - unsigned char clen[4]; - unsigned int x = 0; - unsigned int sz, off; - - cc = read(krem->read_fd, clen, 4); - if (cc != 4) return cc; - x <<= 8; x += clen[0] & 0xff; - x <<= 8; x += clen[1] & 0xff; - x <<= 8; x += clen[2] & 0xff; - x <<= 8; x += clen[3] & 0xff; - sz = (x + 7) & (~7U); - - if (krem->retbuflen < sz) { - if (krem->retbuflen == 0) - krem->retbuf = (char*)malloc(sz>(BUFSIZ)?sz:(BUFSIZ)); - else - krem->retbuf = (char*)realloc(krem->retbuf, sz); - if(!krem->retbuf) { errno = ENOMEM; return -1; } - krem->retbuflen = sz>(BUFSIZ)?sz:(BUFSIZ); - } - - /* get all of it */ - off = 0; - do { - cc = read(krem->read_fd, krem->retbuf+off, sz-off); - if (cc <= 0) return cc; - off += cc; - } while (off < sz); - - /* decrypt it */ - des_pcbc_encrypt ((des_cblock *)krem->retbuf, - (des_cblock *)krem->retbuf, - (int) sz, *krem->sched, krem->ivec, - DECRYPT); - - /* now retbuf has sz bytes, return len or x of them to the user */ - if (x <= len) { - memcpy(buf, krem->retbuf, x); - return x; - } else { - memcpy(buf, krem->retbuf, len); - /* defer the rest */ - krem->returned = len; - krem->retlen = x; - return len; - } - } - } else { - return read(krem->read_fd, buf, len); - } -} - -static int kstream_write(krem, buf, len) - kstream krem; - char *buf; - unsigned int len; -{ - if (krem->encrypting) { - unsigned long x; - int st; - unsigned int outlen = (len + 7) & (~7U); - - if (krem->writelen < outlen || krem->outbuf == 0) { - krem->inbuf = (char*)realloc(krem->inbuf, outlen ? outlen : 1); - krem->outbuf = (char*)realloc(krem->outbuf, outlen+8); - if(!krem->inbuf || !krem->outbuf) { errno = ENOMEM; return -1; } - krem->writelen = outlen; - } - - outlen = (len + 7) & (~7U); - - memcpy(krem->inbuf, buf, len); - krb5_random_confounder(outlen-len, krem->inbuf+len); - buf = krem->inbuf; - - x = len; - krem->outbuf[3+4] = x & 0xff; x >>= 8; - krem->outbuf[2+4] = x & 0xff; x >>= 8; - krem->outbuf[1+4] = x & 0xff; x >>= 8; - krem->outbuf[0+4] = x & 0xff; x >>= 8; - if (x) - abort (); - /* memset(outbuf+4+4, 0x42, BUFSIZ); */ - st = des_pcbc_encrypt ((des_cblock *)buf, (des_cblock *)(krem->outbuf+4+4), - (int) outlen, - *krem->sched, krem->ivec, ENCRYPT); - - if (st) abort(); - return write(krem->write_fd, krem->outbuf+4, 4+outlen); - } else { - return write(krem->write_fd, buf, len); - } -} - -/* 0 = stdin, read; 1 = stdout, write */ -#define rem 0,1 - -#endif - - -#ifdef _AUX_SOURCE -#define vfork fork -#endif -#ifdef NOVFORK -#define vfork fork -#endif - -#ifndef roundup -#define roundup(x,y) ((((x)+(y)-1)/(y))*(y)) -#endif - -int sock; -CREDENTIALS cred; -MSG_DAT msg_data; -struct sockaddr_in foreign, local; -Key_schedule schedule; - -KTEXT_ST ticket; -AUTH_DAT kdata; -static des_cblock crypt_session_key; -char krb_realm[REALM_SZ]; -char **save_argv(int, char **), *krb_realmofhost(); -#ifndef HAVE_STRSAVE -static char *strsave(char *); -#endif -#ifdef NOENCRYPTION -#define des_read read -#define des_write write -#else /* !NOENCRYPTION */ -void answer_auth(void); -int encryptflag = 0; -#endif /* NOENCRYPTION */ -#include "rpaths.h" -#else /* !KERBEROS */ -#define des_read read -#define des_write write -#endif /* KERBEROS */ - -kstream krem; -int errs; -krb5_sigtype lostconn(int); -int iamremote, targetshouldbedirectory; -int iamrecursive; -int pflag; -int force_net; -struct passwd *pwd; -int userid; -int port; - -char *getenv(); - -struct buffer { - int cnt; - char *buf; -} *allocbuf(struct buffer *, int, int); - -#define NULLBUF (struct buffer *) 0 - -#define ga() (void) kstream_write (krem, "", 1) - -int main(argc, argv) - int argc; - char **argv; -{ - char portarg[20], rcpportarg[20]; -#ifdef ATHENA - static char curhost[256]; -#endif /* ATHENA */ -#ifdef KERBEROS - char realmarg[REALM_SZ + 5]; -#endif /* KERBEROS */ - - portarg[0] = '\0'; - rcpportarg[0] = '\0'; - realmarg[0] = '\0'; - - pwd = getpwuid(userid = getuid()); - if (pwd == 0) { - fprintf(stderr, "who are you?\n"); - exit(1); - } - -#ifdef KERBEROS - krb_realm[0] = '\0'; /* Initially no kerberos realm set */ -#endif /* KERBEROS */ - 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 'P': /* Set port to use. */ - port = atoi(*argv); - snprintf(portarg, sizeof(portarg), " -p%d", port); - snprintf(rcpportarg, sizeof(rcpportarg), " -P%d", - port); - port = htons(port); - goto next_arg; - - case 'N': - /* Force use of network even on local machine. */ - force_net++; - break; - -#ifdef KERBEROS -#ifndef NOENCRYPTION - case 'x': - encryptflag++; - break; -#endif - case 'k': /* Change kerberos realm */ - argc--, argv++; - if (argc == 0) - usage(); - strncpy(krb_realm,*argv,REALM_SZ); - krb_realm[REALM_SZ-1] = 0; - snprintf(realmarg, sizeof(realmarg), " -k %s", - krb_realm); - goto next_arg; -#endif /* KERBEROS */ - /* The rest of these are not for users. */ - case 'd': - targetshouldbedirectory = 1; - break; - - case 'f': /* "from" */ - iamremote = 1; -#if defined(KERBEROS) && !defined(NOENCRYPTION) - if (encryptflag) { - answer_auth(); - krem = kstream_create_rcp_from_fd (rem, - &schedule, - &crypt_session_key); - } else - krem = kstream_create_from_fd (rem, 0, 0); - if (krem == NULL) { - error("rcp: out of memory\n"); - exit(1); - } - kstream_set_buffer_mode (krem, 0); -#endif /* KERBEROS && !NOENCRYPTION */ - (void) response(); - if (setuid(userid)) { - error("rcp: can't setuid(user)\n"); - exit(1); - } - source(--argc, ++argv); - exit(errs); - - case 't': /* "to" */ - iamremote = 1; -#if defined(KERBEROS) && !defined(NOENCRYPTION) - if (encryptflag) { - answer_auth(); - krem = kstream_create_rcp_from_fd (rem, - &schedule, - &crypt_session_key); - } else - krem = kstream_create_from_fd (rem, 0, 0); - if (krem == NULL) { - error("rcp: out of memory\n"); - exit(1); - } - kstream_set_buffer_mode (krem, 0); -#endif /* KERBEROS && !NOENCRYPTION */ - if (setuid(userid)) { - error("rcp: can't setuid(user)\n"); - exit(1); - } - sink(--argc, ++argv); - exit(errs); - - default: - usage(); - } -#ifdef KERBEROS - next_arg: ; -#endif /* KERBEROS */ - } - usage(); - return 1; -} - -static 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); -} - -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[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); - kstream_write (krem, buf, strlen (buf)); - if (response() < 0) { - (void) close(f); - continue; - } - } - (void) snprintf(buf, sizeof(buf), "C%04o %ld %s\n", - (unsigned int) stb.st_mode&07777, - (long) stb.st_size, last); - kstream_write (krem, buf, strlen (buf)); - if (response() < 0) { - (void) close(f); - continue; - } - if ((bp = allocbuf(&buffer, f, 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; - kstream_write (krem, bp->buf, amt); - } - (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; - char buf[BUFSIZ]; - char *bufv[1]; -#ifdef USE_DIRENT_H - struct dirent *dp; -#else - struct direct *dp; -#endif - - 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); - kstream_write (krem, buf, strlen (buf)); - if (response() < 0) { - closedir(d); - return; - } - } - (void) sprintf(buf, sizeof(buf), "D%04o %d %s\n", - (unsigned int) statp->st_mode&07777, 0, last); - kstream_write (krem, buf, strlen (buf)); - if (response() < 0) { - closedir(d); - return; - } - while ((dp = readdir(d))) { - if (dp->d_ino == 0) - continue; - if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) - continue; - if (strlen(name) + 1 + strlen(dp->d_name) >= 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); - kstream_write (krem, "E\n", 2); - (void) response(); -} - -int response() -{ - char resp, c, rbuf[BUFSIZ], *cp = rbuf; - - if (kstream_read (krem, &resp, 1) != 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 (kstream_read (krem, &c, 1) != 1) - lostconn(0); - *cp++ = c; - } while (cp < &rbuf[BUFSIZ] && c != '\n'); - if (iamremote == 0) - (void) write(2, rbuf, (unsigned) (cp - rbuf)); - errs++; - if (resp == 1) - return (-1); - exit(1); - } - /*NOTREACHED*/ - return -1; -} - -krb5_sigtype lostconn(signum) - int signum; -{ - - 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, ×)); -} -#endif - -void sink(argc, argv) - int argc; - char **argv; -{ - off_t i, j; - char *targ, *whopp, *cp; - int of, wrerr, exists, first, amt; - mode_t mode; - unsigned int count; - off_t size; - struct buffer *bp; - static struct buffer buffer; - struct stat stb; - int targisdir = 0; - mode_t mask = umask(0); - char *myargv[1]; - char cmdbuf[BUFSIZ], nambuf[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 (kstream_read (krem, cp, 1) <= 0) - return; - if (*cp++ == '\n') - SCREWUP("unexpected '\\n'"); - do { - if (kstream_read(krem, cp, 1) != 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) + 1 < sizeof(nambuf)) { - (void) snprintf(nambuf, sizeof(nambuf), - "%s%s%s", targ, - *targ ? "/" : "", cp); - } else { - SCREWUP("target directory name too long"); - } - } else { - if (strlen(targ) + 1 < sizeof(nambuf)) - (void) strncpy(nambuf, targ, sizeof(nambuf)-1); - else - SCREWUP("target pathname too long"); - } - 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|O_TRUNC, mode)) < 0) { - bad: - error("rcp: %s: %s\n", nambuf, error_message(errno)); - continue; - } -#ifdef NO_FCHMOD - if (exists && pflag) - (void) chmod(nambuf, mode); -#else - if (exists && pflag) - (void) fchmod(of, mode); -#endif - ga(); - if ((bp = allocbuf(&buffer, of, BUFSIZ)) == NULLBUF) { - (void) close(of); - continue; - } - cp = bp->buf; - count = 0; - wrerr = 0; - for (i = 0; i < size; i += BUFSIZ) { - amt = BUFSIZ; - if (i + amt > size) - amt = size - i; - count += amt; - do { - j = kstream_read(krem, cp, amt); - 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++; -#ifndef __SCO__ - if (ftruncate(of, size)) - error("rcp: can't truncate %s: %s\n", - nambuf, error_message(errno)); -#endif - (void) close(of); - (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; -{ - int size; -#ifndef NOSTBLKSIZE - struct stat stb; - - if (fstat(fd, &stb) < 0) { - error("rcp: fstat: %s\n", error_message(errno)); - return (NULLBUF); - } - size = roundup(stb.st_blksize, blksize); - if (size == 0) -#endif - 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 -error(char *fmt, ...) -{ - va_list ap; - char buf[BUFSIZ], *cp = buf; - - va_start(ap, fmt); - - errs++; - *cp++ = 1; - (void) vsnprintf(cp, sizeof(buf) - (cp-buf), fmt, ap); - va_end(ap); - - if (krem) - (void) kstream_write(krem, buf, strlen(buf)); - if (iamremote == 0) - (void) write(2, buf+1, strlen(buf+1)); -} - -void usage() -{ - fprintf(stderr, -"v4rcp: this program only acts as a server, and is not for user function.\n"); - exit(1); -} - -#ifdef KERBEROS - -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); -} - -#ifndef HAVE_STRSAVE -static char * -strsave(sp) -char *sp; -{ - register char *ret; - - ret = strdup(sp); - if (ret == NULL) { - fprintf(stderr, "rcp: no memory for saving args\n"); - exit(1); - } - return ret; -} -#endif - -#ifndef NOENCRYPTION -#undef rem -#define rem 0 - -void -answer_auth() -{ - int status; - long authopts = KOPT_DO_MUTUAL; - char instance[INST_SZ]; - char version[9]; - char *srvtab; - char *envaddr; - -#if 0 - int sin_len; - - sin_len = sizeof (struct sockaddr_in); - if (getpeername(rem, &foreign, &sin_len) < 0) { - perror("getpeername"); - exit(1); - } - - sin_len = sizeof (struct sockaddr_in); - if (getsockname(rem, &local, &sin_len) < 0) { - perror("getsockname"); - exit(1); - } -#else - if ((envaddr = getenv("KRB5LOCALADDR"))) { -#ifdef HAVE_INET_ATON - inet_aton(envaddr, &local.sin_addr); -#else - local.sin_addr.s_addr = inet_addr(envaddr); -#endif - local.sin_family = AF_INET; - envaddr = getenv("KRB5LOCALPORT"); - if (envaddr) - local.sin_port = htons(atoi(envaddr)); - else - local.sin_port = 0; - } else { - fprintf(stderr, "v4rcp: couldn't get local address (KRB5LOCALADDR)\n"); - exit(1); - } - if ((envaddr = getenv("KRB5REMOTEADDR"))) { -#ifdef HAVE_INET_ATON - inet_aton(envaddr, &foreign.sin_addr); -#else - foreign.sin_addr.s_addr = inet_addr(envaddr); -#endif - foreign.sin_family = AF_INET; - envaddr = getenv("KRB5REMOTEPORT"); - if (envaddr) - foreign.sin_port = htons(atoi(envaddr)); - else - foreign.sin_port = 0; - } else { - fprintf(stderr, "v4rcp: couldn't get remote address (KRB5REMOTEADDR)\n"); - exit(1); - } - -#endif - strlcpy(instance, "*", sizeof(instance)); - - /* If rshd was invoked with the -s argument, it will set the - environment variable KRB_SRVTAB. We use that to get the - srvtab file to use. If we do use the environment variable, - we reset to our real user ID (which will already have been - set up by rsh). Since rcp is setuid root, we would - otherwise have a security hole. If we are using the normal - srvtab (KEYFILE in krb.h, normally set to /etc/krb-srvtab), - we must keep our effective uid of root, because that file - can only be read by root. */ - srvtab = (char *) getenv("KRB_SRVTAB"); - if (srvtab == NULL) - srvtab = ""; - if (*srvtab != '\0') - (void) setuid (userid); - - if ((status = krb_recvauth(authopts, rem, &ticket, "rcmd", instance, - &foreign, - &local, - &kdata, - srvtab, - schedule, - version)) != KSUCCESS) { - fprintf(stderr, "krb_recvauth mutual fail: %s\n", - krb_get_err_text(status)); - exit(1); - } - memcpy(&crypt_session_key, &kdata.session, sizeof (crypt_session_key)); - return; -} -#endif /* !NOENCRYPTION */ - -#endif /* KERBEROS */ |