diff options
Diffstat (limited to 'crypto/kerberosIV/appl')
81 files changed, 23759 insertions, 0 deletions
diff --git a/crypto/kerberosIV/appl/Makefile.in b/crypto/kerberosIV/appl/Makefile.in new file mode 100644 index 0000000..c951258 --- /dev/null +++ b/crypto/kerberosIV/appl/Makefile.in @@ -0,0 +1,43 @@ +# $Id: Makefile.in,v 1.27 1997/05/20 18:58:37 bg Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh + +@SET_MAKE@ + +SUBDIRS = sample kauth bsd movemail afsutil \ + kpopper xnlock kx otp @APPL_KIP_DIR@ ftp telnet + +all: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) all); done + +Wall: + make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +install: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) install); done + +uninstall: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) uninstall); done + +clean: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) clean); done + +mostlyclean: clean + +distclean: + for i in $(SUBDIRS);\ + do (cd $$i && $(MAKE) $(MFLAGS) distclean); done + rm -f Makefile *~ + +realclean: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) realclean); done + +.PHONY: all install uninstall clean distclean realclean mostlyclean diff --git a/crypto/kerberosIV/appl/bsd/Makefile.in b/crypto/kerberosIV/appl/bsd/Makefile.in new file mode 100644 index 0000000..57a8108 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/Makefile.in @@ -0,0 +1,135 @@ +# $Id: Makefile.in,v 1.56 1997/05/20 20:35:04 assar Exp $ + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +topdir = ../.. + +CC = @CC@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ -DBINDIR='"$(bindir)"' +CFLAGS = @CFLAGS@ +LD_FLAGS = @LD_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LIBS = @LIBS@ +LIB_DBM = @LIB_DBM@ +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +bindir = @bindir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +# Beware, these are all setuid root programs +PROG_SUIDBIN = rsh$(EXECSUFFIX) \ + rcp$(EXECSUFFIX) \ + rlogin$(EXECSUFFIX) \ + su$(EXECSUFFIX) +PROG_BIN = login$(EXECSUFFIX) +PROG_LIBEXEC = rshd$(EXECSUFFIX) \ + rlogind$(EXECSUFFIX) +PROGS = $(PROG_SUIDBIN) $(PROG_BIN) $(PROG_LIBEXEC) + +SOURCES = rsh.c kcmd.c krcmd.c rlogin.c rcp.c rcp_util.c rshd.c \ + login.c klogin.c login_access.c su.c rlogind.c iruserok.c \ + login_fbtab.c forkpty.c sysv_default.c sysv_environ.c sysv_shadow.c \ + utmp_login.c utmpx_login.c stty_default.c encrypt.c rcmd_util.c tty.c + +rsh_OBJS = rsh.o kcmd.o krcmd.o encrypt.o rcmd_util.o +rcp_OBJS = rcp.o rcp_util.o kcmd.o krcmd.o encrypt.o rcmd_util.o +rlogin_OBJS = rlogin.o kcmd.o krcmd.o encrypt.o rcmd_util.o +login_OBJS = login.o klogin.o login_fbtab.o login_access.o \ + sysv_default.o sysv_environ.o sysv_shadow.o \ + utmp_login.o utmpx_login.o stty_default.o tty.o +su_OBJS = su.o +rshd_OBJS = rshd.o iruserok.o encrypt.o rcmd_util.o +rlogind_OBJS = rlogind.o iruserok.o forkpty.o encrypt.o rcmd_util.o tty.o + + +all: $(PROGS) + +Wall: + make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $< + +install: all + $(MKINSTALLDIRS) $(libexecdir) + for x in $(PROG_LIBEXEC); do \ + $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + done + $(MKINSTALLDIRS) $(bindir) + for x in $(PROG_BIN); do \ + $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x| sed '$(transform)'`; \ + done + -for x in $(PROG_SUIDBIN); do \ + $(INSTALL_PROGRAM) -o root -m 04555 $$x $(bindir)/`echo $$x| sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROG_LIBEXEC); do \ + rm -f $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + done + for x in $(PROG_BIN); do \ + rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \ + done + for x in $(PROG_SUIDBIN); do \ + rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \ + done + +TAGS: $(SOURCES) + etags $(SOURCES) + +check: + +clean: + rm -f *.a *.o $(PROGS) + +mostlyclean: clean + +distclean: clean + rm -f Makefile *.tab.c *~ + +realclean: distclean + rm -f TAGS + +dist: $(DISTFILES) + for file in $(DISTFILES); do \ + ln $$file ../`cat ../.fname`/lib \ + || cp -p $$file ../`cat ../.fname`/lib; \ + done + +KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes +KLIB_AFS=@KRB_KAFS_LIB@ $(KLIB) +OTPLIB=-L../../lib/otp -lotp +LIBROKEN=-L../../lib/roken -lroken + +rcp$(EXECSUFFIX): $(rcp_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rcp_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +rsh$(EXECSUFFIX): $(rsh_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rsh_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +rshd$(EXECSUFFIX): $(rshd_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rshd_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +rlogin$(EXECSUFFIX): $(rlogin_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogin_OBJS) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +rlogind$(EXECSUFFIX): $(rlogind_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(rlogind_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +login$(EXECSUFFIX): $(login_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(login_OBJS) $(OTPLIB) $(KLIB_AFS) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN) + +su$(EXECSUFFIX): $(su_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(su_OBJS) $(KLIB_AFS) $(LIBROKEN) $(LIBS) $(LIBROKEN) diff --git a/crypto/kerberosIV/appl/bsd/README.login b/crypto/kerberosIV/appl/bsd/README.login new file mode 100644 index 0000000..c072969 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/README.login @@ -0,0 +1,20 @@ +This login has additional functionalities. They are all based on (part of) +Wietse Venema's logdaemon package. + + +The following defines can be used: +1) LOGIN_ACCESS to allow access control on a per tty/user combination +2) LOGALL to log all logins + +-Guido + +This login has some of Berkeley's paranoid/broken (depending on your point +of view) Kerberos code conditionalized out, so that by default it works like +klogin does at MIT-LCS. You can define KLOGIN_PARANOID to re-enable this code. +This define also controls whether a warning message is printed when logging +into a system with no krb.conf file, which usually means that Kerberos is +not configured. + +-GAWollman + +(removed S/Key, /assar) diff --git a/crypto/kerberosIV/appl/bsd/bsd_locl.h b/crypto/kerberosIV/appl/bsd/bsd_locl.h new file mode 100644 index 0000000..d0b37aa --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/bsd_locl.h @@ -0,0 +1,380 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: bsd_locl.h,v 1.98 1997/05/25 01:14:17 assar Exp $ */ + +#define LOGALL +#define KERBEROS +#define KLOGIN_PARANOID +#define LOGIN_ACCESS +#define PASSWD_FALLBACK + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Any better way to test NO_MOTD? */ +#if (SunOS == 5) || defined(__hpux) +#define NO_MOTD +#endif + +#ifdef HAVE_SHADOW_H +#define SYSV_SHADOW +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <setjmp.h> + +#include <stdarg.h> + +#include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifndef S_ISTXT +#ifdef S_ISVTX +#define S_ISTXT S_ISVTX +#else +#define S_ISTXT 0 +#endif +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif +#include <signal.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif /* HAVE_SYS_RESOURCE_H */ +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifndef NCARGS +#define NCARGS 0x100000 /* (absolute) max # characters in exec arglist */ +#endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + +#ifdef HAVE_GRP_H +#include <grp.h> +#endif +#ifdef HAVE_UTIME_H +#include <utime.h> +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4 +#include <sys/ioctl.h> +#endif +#ifdef HAVE_SYS_IOCCOM_H +#include <sys/ioccom.h> +#endif + +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif + +#ifdef HAVE_SYS_STREAM_H +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif /* HAVE_SYS_UIO_H */ +#include <sys/stream.h> +#endif /* HAVE_SYS_STREAM_H */ + +#ifdef HAVE_SYS_PTYVAR_H +#ifdef HAVE_SYS_PROC_H +#include <sys/proc.h> +#endif +#ifdef HAVE_SYS_TTY_H +#include <sys/tty.h> +#endif +#ifdef HAVE_SYS_PTYIO_H +#include <sys/ptyio.h> +#endif +#include <sys/ptyvar.h> +#endif /* HAVE_SYS_PTYVAR_H */ + +/* Cray stuff */ +#ifdef HAVE_UDB_H +#include <udb.h> +#endif +#ifdef HAVE_SYS_CATEGORY_H +#include <sys/category.h> +#endif + +/* Strange ioctls that are not always defined */ + +#ifndef TIOCPKT_FLUSHWRITE +#define TIOCPKT_FLUSHWRITE 0x02 +#endif + +#ifndef TIOCPKT_NOSTOP +#define TIOCPKT_NOSTOP 0x10 +#endif + +#ifndef TIOCPKT_DOSTOP +#define TIOCPKT_DOSTOP 0x20 +#endif + +#ifndef TIOCPKT +#define TIOCPKT _IOW('t', 112, int) /* pty: set/clear packet mode */ +#endif + +#ifdef HAVE_LASTLOG_H +#include <lastlog.h> +#endif + +#ifdef HAVE_LOGIN_H +#include <login.h> +#endif + +#ifdef HAVE_TTYENT_H +#include <ttyent.h> +#endif + +#ifdef HAVE_STROPTS_H +#include <stropts.h> +#endif + +#ifdef HAVE_UTMP_H +#include <utmp.h> +#endif +#ifndef UT_NAMESIZE +#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name) +#endif + +#ifdef HAVE_UTMPX_H +#include <utmpx.h> +#endif + +#ifdef HAVE_USERPW_H +#include <userpw.h> +#endif /* HAVE_USERPW_H */ + +#ifdef HAVE_USERSEC_H +#include <usersec.h> +#endif /* HAVE_USERSEC_H */ + +#ifndef PRIO_PROCESS +#define PRIO_PROCESS 0 +#endif + +#include <err.h> + +#include <roken.h> + +#ifdef SOCKS +#include <socks.h> +#endif + +#include <des.h> +#include <krb.h> +#include <kafs.h> + +int kcmd(int *sock, char **ahost, u_int16_t rport, char *locuser, + char *remuser, char *cmd, int *fd2p, KTEXT ticket, + char *service, char *realm, CREDENTIALS *cred, + Key_schedule schedule, MSG_DAT *msg_data, + struct sockaddr_in *laddr, struct sockaddr_in *faddr, + int32_t authopts); + +int krcmd(char **ahost, u_int16_t rport, char *remuser, char *cmd, + int *fd2p, char *realm); + +int krcmd_mutual(char **ahost, u_int16_t rport, char *remuser, + char *cmd,int *fd2p, char *realm, + CREDENTIALS *cred, Key_schedule sched); + +int klogin(struct passwd *pw, char *instance, char *localhost, char *password); + +typedef struct { + int cnt; + char *buf; +} BUF; + +char *colon(char *cp); +int okname(char *cp0); +int susystem(char *s, int userid); + +int forkpty(int *amaster, char *name, + struct termios *termp, struct winsize *winp); + +#ifndef MODEMASK +#define MODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) +#endif + +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif +#ifdef HAVE_MAILLOCK_H +#include <maillock.h> +#endif +#include "pathnames.h" + +void stty_default (void); + +int utmpx_login(char *line, char *user, char *host); + +extern char **environ; + +void sysv_newenv(int argc, char **argv, struct passwd *pwd, + char *term, int pflag); + +int login_access(char *user, char *from); +#ifndef HAVE_IRUSEROK +int iruserok(u_int32_t raddr, int superuser, const char *ruser, + const char *luser); +#endif +void fatal(int f, const char *msg, int syserr); + +extern int LEFT_JUSTIFIED; +int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, + des_cblock *iv); +int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, + des_cblock *iv); + +void sysv_defaults(void); +void utmp_login(char *tty, char *username, char *hostname); +void sleepexit (int); + +#ifndef HAVE_SETPRIORITY +#define setpriority(which, who, niceval) 0 +#endif + +#ifndef HAVE_GETPRIORITY +#define getpriority(which, who) 0 +#endif + +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#endif + +#ifndef _POSIX_VDISABLE +#define _POSIX_VDISABLE 0 +#endif /* _POSIX_VDISABLE */ +#if SunOS == 4 +#include <sys/ttold.h> +#endif + +#if defined(_AIX) +#include <sys/termio.h> +#endif + +#ifndef CEOF +#define CEOF 04 +#endif + +/* concession to Sun */ +#ifndef SIGUSR1 +#define SIGUSR1 30 +#endif + +#ifndef TIOCPKT_WINDOW +#define TIOCPKT_WINDOW 0x80 +#endif + +int get_shell_port(int kerberos, int encryption); +int get_login_port(int kerberos, int encryption); +int speed_t2int (speed_t); +speed_t int2speed_t (int); +void ip_options_and_die (int sock, struct sockaddr_in *); +void warning(const char *fmt, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + +char *clean_ttyname (char *tty); +char *make_id (char *tty); +void prepare_utmp (struct utmp *utmp, char *tty, char *username, + char *hostname); diff --git a/crypto/kerberosIV/appl/bsd/encrypt.c b/crypto/kerberosIV/appl/bsd/encrypt.c new file mode 100644 index 0000000..b74f329 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/encrypt.c @@ -0,0 +1,311 @@ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au) + * All rights reserved. + * + * This file is part of an SSL implementation written + * by Eric Young (eay@mincom.oz.au). + * The implementation was written so as to conform with Netscapes SSL + * specification. This library and applications are + * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE + * as long as the following conditions are aheared to. + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. If this code is used in a product, + * Eric Young should be given attribution as the author of the parts used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Eric Young (eay@mincom.oz.au) + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include "bsd_locl.h" + +RCSID("$Id: encrypt.c,v 1.3 1996/04/30 13:50:54 bg Exp $"); + +#undef BSIZE + +/* used in des_read and des_write */ +#define MAXWRITE (1024*16) +#define BSIZE (MAXWRITE+4) + +/* replacements for htonl and ntohl since I have no idea what to do + * when faced with machines with 8 byte longs. */ +#define HDRSIZE 4 + +#define n2l(c,l) (l =((u_int32_t)(*((c)++)))<<24, \ + l|=((u_int32_t)(*((c)++)))<<16, \ + l|=((u_int32_t)(*((c)++)))<< 8, \ + l|=((u_int32_t)(*((c)++)))) + +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* This has some uglies in it but it works - even over sockets. */ +extern int errno; +int des_rw_mode=DES_PCBC_MODE; +int LEFT_JUSTIFIED = 0; + +int +des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock *iv) +{ + /* data to be unencrypted */ + int net_num=0; + unsigned char net[BSIZE]; + /* extra unencrypted data + * for when a block of 100 comes in but is des_read one byte at + * a time. */ + static char unnet[BSIZE]; + static int unnet_start=0; + static int unnet_left=0; + int i; + long num=0,rnum; + unsigned char *p; + + /* left over data from last decrypt */ + if (unnet_left != 0) + { + if (unnet_left < len) + { + /* we still still need more data but will return + * with the number of bytes we have - should always + * check the return value */ + memcpy(buf,&(unnet[unnet_start]),unnet_left); + /* eay 26/08/92 I had the next 2 lines + * reversed :-( */ + i=unnet_left; + unnet_start=unnet_left=0; + } + else + { + memcpy(buf,&(unnet[unnet_start]),len); + unnet_start+=len; + unnet_left-=len; + i=len; + } + return(i); + } + + /* We need to get more data. */ + if (len > MAXWRITE) len=MAXWRITE; + + /* first - get the length */ + net_num=0; + while (net_num < HDRSIZE) + { + i=read(fd,&(net[net_num]),(unsigned int)HDRSIZE-net_num); + if ((i == -1) && (errno == EINTR)) continue; + if (i <= 0) return(0); + net_num+=i; + } + + /* we now have at net_num bytes in net */ + p=net; + num=0; + n2l(p,num); + /* num should be rounded up to the next group of eight + * we make sure that we have read a multiple of 8 bytes from the net. + */ + if ((num > MAXWRITE) || (num < 0)) /* error */ + return(-1); + rnum=(num < 8)?8:((num+7)/8*8); + + net_num=0; + while (net_num < rnum) + { + i=read(fd,&(net[net_num]),(unsigned int)rnum-net_num); + if ((i == -1) && (errno == EINTR)) continue; + if (i <= 0) return(0); + net_num+=i; + } + + /* Check if there will be data left over. */ + if (len < num) + { + if (des_rw_mode & DES_PCBC_MODE) + des_pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet, + num,sched,iv,DES_DECRYPT); + else + des_cbc_encrypt((des_cblock *)net,(des_cblock *)unnet, + num,sched,iv,DES_DECRYPT); + memcpy(buf,unnet,len); + unnet_start=len; + unnet_left=num-len; + + /* The following line is done because we return num + * as the number of bytes read. */ + num=len; + } + else + { + /* >output is a multiple of 8 byes, if len < rnum + * >we must be careful. The user must be aware that this + * >routine will write more bytes than he asked for. + * >The length of the buffer must be correct. + * FIXED - Should be ok now 18-9-90 - eay */ + if (len < rnum) + { + char tmpbuf[BSIZE]; + + if (des_rw_mode & DES_PCBC_MODE) + des_pcbc_encrypt((des_cblock *)net, + (des_cblock *)tmpbuf, + num,sched,iv,DES_DECRYPT); + else + des_cbc_encrypt((des_cblock *)net, + (des_cblock *)tmpbuf, + num,sched,iv,DES_DECRYPT); + + /* eay 26/08/92 fix a bug that returned more + * bytes than you asked for (returned len bytes :-( */ + if (LEFT_JUSTIFIED || (len >= 8)) + memcpy(buf,tmpbuf,num); + else + memcpy(buf,tmpbuf+(8-num),num); /* Right justified */ + } + else if (num >= 8) + { + if (des_rw_mode & DES_PCBC_MODE) + des_pcbc_encrypt((des_cblock *)net, + (des_cblock *)buf,num,sched,iv, + DES_DECRYPT); + else + des_cbc_encrypt((des_cblock *)net, + (des_cblock *)buf,num,sched,iv, + DES_DECRYPT); + } + else + { + if (des_rw_mode & DES_PCBC_MODE) + des_pcbc_encrypt((des_cblock *)net, + (des_cblock *)buf,8,sched,iv, + DES_DECRYPT); + else + des_cbc_encrypt((des_cblock *)net, + (des_cblock *)buf,8,sched,iv, + DES_DECRYPT); + if (!LEFT_JUSTIFIED) + memcpy(buf, buf+(8-num), num); /* Right justified */ + } + } + return(num); +} + +int +des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock *iv) +{ + long rnum; + int i,j,k,outnum; + char outbuf[BSIZE+HDRSIZE]; + char shortbuf[8]; + char *p; + static int start=1; + + /* If we are sending less than 8 bytes, the same char will look + * the same if we don't pad it out with random bytes */ + if (start) + { + start=0; + srand(time(NULL)); + } + + /* lets recurse if we want to send the data in small chunks */ + if (len > MAXWRITE) + { + j=0; + for (i=0; i<len; i+=k) + { + k=des_enc_write(fd,&(buf[i]), + ((len-i) > MAXWRITE)?MAXWRITE:(len-i),sched,iv); + if (k < 0) + return(k); + else + j+=k; + } + return(j); + } + + /* write length first */ + p=outbuf; + l2n(len,p); + + /* pad short strings */ + if (len < 8) + { + if (LEFT_JUSTIFIED) + { + p=shortbuf; + memcpy(shortbuf,buf,(unsigned int)len); + for (i=len; i<8; i++) + shortbuf[i]=rand(); + rnum=8; + } + else + { + p=shortbuf; + for (i=0; i<8-len; i++) + shortbuf[i]=rand(); + memcpy(shortbuf + 8 - len, buf, len); + rnum=8; + } + } + else + { + p=buf; + rnum=((len+7)/8*8); /* round up to nearest eight */ + } + + if (des_rw_mode & DES_PCBC_MODE) + des_pcbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]), + (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); + else + des_cbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]), + (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); + + /* output */ + outnum=rnum+HDRSIZE; + + for (j=0; j<outnum; j+=i) + { + /* eay 26/08/92 I was not doing writing from where we + * got upto. */ + i=write(fd,&(outbuf[j]),(unsigned int)(outnum-j)); + if (i == -1) + { + if (errno == EINTR) + i=0; + else /* This is really a bad error - very bad + * It will stuff-up both ends. */ + return(-1); + } + } + + return(len); +} diff --git a/crypto/kerberosIV/appl/bsd/forkpty.c b/crypto/kerberosIV/appl/bsd/forkpty.c new file mode 100644 index 0000000..5c0aaaf --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/forkpty.c @@ -0,0 +1,461 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "bsd_locl.h" + +#ifndef HAVE_FORKPTY + +RCSID("$Id: forkpty.c,v 1.52 1997/05/25 07:37:01 assar Exp $"); + +/* Only CRAY is known to have problems with forkpty(). */ +#if defined(CRAY) +static int forkpty_ok = 0; +#else +static int forkpty_ok = 1; +#endif + +#ifndef HAVE_PTSNAME +static char *ptsname(int fd) +{ +#ifdef HAVE_TTYNAME + return ttyname(fd); +#else + return NULL; +#endif +} +#endif + +#ifndef HAVE_GRANTPT +#define grantpt(fdm) (0) +#endif + +#ifndef HAVE_UNLOCKPT +#define unlockpt(fdm) (0) +#endif + +#ifndef HAVE_VHANGUP +#define vhangup() (0) +#endif + +#ifndef HAVE_REVOKE +static +void +revoke(char *line) +{ + int slave; + RETSIGTYPE (*ofun)(); + + if ( (slave = open(line, O_RDWR)) < 0) + return; + + ofun = signal(SIGHUP, SIG_IGN); + vhangup(); + signal(SIGHUP, ofun); + /* + * Some systems (atleast SunOS4) want to have the slave end open + * at all times to prevent a race in the child. Login will close + * it so it should really not be a problem. However for the + * paranoid we use the close on exec flag so it will only be open + * in the parent. Additionally since this will be the controlling + * tty of rlogind the final vhangup() in rlogind should hangup all + * processes. A working revoke would of course have been prefered + * though (sigh). + */ + fcntl(slave, F_SETFD, 1); + /* close(slave); */ +} +#endif + + +static int pty_major, pty_minor; + +static void +pty_scan_start(void) +{ + pty_major = -1; + pty_minor = 0; +} + +static char *bsd_1 = "0123456789abcdefghijklmnopqrstuv"; +/* there are many more */ +static char *bsd_2 = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +static int +pty_scan_next(char *buf, size_t sz) +{ +#ifdef CRAY + if(++pty_major >= sysconf(_SC_CRAY_NPTY)) + return -1; + snprintf(buf, sz, "/dev/pty/%03d", pty_major); +#else + if(++pty_major == strlen(bsd_1)){ + pty_major = 0; + if(++pty_minor == strlen(bsd_2)) + return -1; + } +#ifdef __hpux + snprintf(buf, sz, "/dev/ptym/pty%c%c", bsd_2[pty_major], bsd_1[pty_minor]); +#else + snprintf(buf, sz, "/dev/pty%c%c", bsd_2[pty_major], bsd_1[pty_minor]); +#endif /* __hpux */ +#endif /* CRAY */ + return 0; +} + +static void +pty_scan_tty(char *buf, size_t sz) +{ +#ifdef CRAY + snprintf(buf, sz, "/dev/ttyp%03d", pty_major); +#elif defined(__hpux) + snprintf(buf, sz, "/dev/pty/tty%c%c", bsd_2[pty_major], bsd_1[pty_minor]); +#else + snprintf(buf, sz, "/dev/tty%c%c", bsd_2[pty_major], bsd_1[pty_minor]); +#endif +} + +static int +ptym_open_streams_flavor(char *pts_name, int *streams_pty) +{ + /* Try clone device master ptys */ + const char *const clone[] = { "/dev/ptc", "/dev/ptmx", + "/dev/ptm", "/dev/ptym/clone", 0 }; + int fdm; + const char *const *q; + + for (q = clone; *q; q++) { + fdm = open(*q, O_RDWR); + if (fdm >= 0) + break; + } + if (fdm >= 0) { + char *ptr1; + if ((ptr1 = ptsname(fdm)) != NULL) /* Get slave's name */ + strcpy(pts_name, ptr1); /* Return name of slave */ + else { + close(fdm); + return(-4); + } + if (grantpt(fdm) < 0) { /* Grant access to slave */ + close(fdm); + return(-2); + } + if (unlockpt(fdm) < 0) { /* Clear slave's lock flag */ + close(fdm); + return(-3); + } + return(fdm); /* return fd of master */ + } + return -1; +} + +static int +ptym_open_bsd_flavor(char *pts_name, int *streams_pty) +{ + int fdm; + char ptm[MaxPathLen]; + + pty_scan_start(); + + while (pty_scan_next(ptm, sizeof(ptm)) != -1) { + fdm = open(ptm, O_RDWR); + if (fdm < 0) + continue; +#if SunOS == 4 + /* Avoid a bug in SunOS4 ttydriver */ + if (fdm > 0) { + int pgrp; + if ((ioctl(fdm, TIOCGPGRP, &pgrp) == -1) + && (errno == EIO)) + /* All fine */; + else { + close(fdm); + continue; + } + } +#endif + pty_scan_tty(pts_name, sizeof(ptm)); +#if CRAY + /* this is some magic from the telnet code */ + { + struct stat sb; + if(stat(pts_name, &sb) < 0) { + close(fdm); + continue; + } + if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { + chown(pts_name, 0, 0); + chmod(pts_name, 0600); + close(fdm); + fdm = open(ptm, 2); + if (fdm < 0) + continue; + } + } + /* + * Now it should be safe...check for accessability. + */ + if (access(pts_name, 6) != 0){ + /* no tty side to pty so skip it */ + close(fdm); + continue; + } +#endif + return fdm; /* All done! */ + } + + /* We failed to find BSD style pty */ + errno = ENOENT; + return -1; +} + +/* + * + * Open a master pty either using the STREAM flavor or the BSD flavor. + * Depending on if there are any free ptys in the different classes we + * need to try both. Normally try STREAMS first and then BSD. + * + * Kludge alert: Under HP-UX 10 and perhaps other systems STREAM ptys + * doesn't get initialized properly so we try them in different order + * until the problem has been resolved. + * + */ +static int +ptym_open(char *pts_name, size_t pts_name_sz, int *streams_pty) +{ + int fdm; + +#ifdef HAVE__GETPTY + { + char *p = _getpty(&fdm, O_RDWR, 0600, 1); + if (p) { + *streams_pty = 1; + strcpy (pts_name, p); + return fdm; + } + } +#endif + +#ifdef STREAMSPTY + fdm = ptym_open_streams_flavor(pts_name, streams_pty); + if (fdm >= 0) + { + *streams_pty = 1; + return fdm; + } +#endif + + fdm = ptym_open_bsd_flavor(pts_name, streams_pty); + if (fdm >= 0) + { + *streams_pty = 0; + return fdm; + } + +#ifndef STREAMSPTY + fdm = ptym_open_streams_flavor(pts_name, streams_pty); + if (fdm >= 0) + { + *streams_pty = 1; + return fdm; + } +#endif + + return -1; +} + +static int +maybe_push_modules(int fd, char **modules) +{ +#ifdef I_PUSH + char **p; + int err; + + for(p=modules; *p; p++){ + err=ioctl(fd, I_FIND, *p); + if(err == 1) + break; + if(err < 0 && errno != EINVAL) + return -17; + /* module not pushed or does not exist */ + } + /* p points to null or to an already pushed module, now push all + modules before this one */ + + for(p--; p >= modules; p--){ + err = ioctl(fd, I_PUSH, *p); + if(err < 0 && errno != EINVAL) + return -17; + } +#endif + return 0; +} + +static int +ptys_open(int fdm, char *pts_name, int streams_pty) +{ + int fds; + + if (streams_pty) { + /* Streams style slave ptys */ + if ( (fds = open(pts_name, O_RDWR)) < 0) { + close(fdm); + return(-5); + } + + { + char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; + char *ptymodules[] = { "pckt", NULL }; + + if(maybe_push_modules(fds, ttymodules)<0){ + close(fdm); + close(fds); + return -6; + } + if(maybe_push_modules(fdm, ptymodules)<0){ + close(fdm); + close(fds); + return -7; + } + } + } else { + /* BSD style slave ptys */ + struct group *grptr; + int gid; + if ( (grptr = getgrnam("tty")) != NULL) + gid = grptr->gr_gid; + else + gid = -1; /* group tty is not in the group file */ + + /* Grant access to slave */ + chown(pts_name, getuid(), gid); + chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP); + + if ( (fds = open(pts_name, O_RDWR)) < 0) { + close(fdm); + return(-1); + } + } + return(fds); +} + +int +forkpty(int *ptrfdm, + char *slave_name, + struct termios *slave_termios, + struct winsize *slave_winsize) +{ + int fdm, fds, streams_pty; + pid_t pid; + char pts_name[20]; + + if (!forkpty_ok) + fatal(0, "Protocol not yet supported, use telnet", 0); + + if ( (fdm = ptym_open(pts_name, sizeof(pts_name), &streams_pty)) < 0) + return -1; + + if (slave_name != NULL) + strcpy(slave_name, pts_name); /* Return name of slave */ + + pid = fork(); + if (pid < 0) + return(-1); + else if (pid == 0) { /* Child */ + if (setsid() < 0) + fatal(0, "setsid() failure", errno); + + revoke(slave_name); + +#if defined(NeXT) || defined(ultrix) + /* The NeXT is severely broken, this makes things slightly + * better but we still doesn't get a working pty. If there + * where a TIOCSCTTY we could perhaps fix things but... The + * same problem also exists in xterm! */ + if (setpgrp(0, 0) < 0) + fatal(0, "NeXT kludge failed setpgrp", errno); +#endif + + /* SVR4 acquires controlling terminal on open() */ + if ( (fds = ptys_open(fdm, pts_name, streams_pty)) < 0) + return -1; + close(fdm); /* All done with master in child */ + +#if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(__hpux) + /* 44BSD way to acquire controlling terminal */ + /* !CIBAUD to avoid doing this under SunOS */ + if (ioctl(fds, TIOCSCTTY, (char *) 0) < 0) + return -1; +#endif +#if defined(NeXT) + { + int t = open("/dev/tty", O_RDWR); + if (t < 0) + fatal(0, "Failed to open /dev/tty", errno); + close(fds); + fds = t; + } +#endif + /* Set slave's termios and window size */ + if (slave_termios != NULL) { + if (tcsetattr(fds, TCSANOW, slave_termios) < 0) + return -1; + } +#ifdef TIOCSWINSZ + if (slave_winsize != NULL) { + if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0) + return -1; + } +#endif + /* slave becomes stdin/stdout/stderr of child */ + if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) + return -1; + if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) + return -1; + if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) + return -1; + if (fds > STDERR_FILENO) + close(fds); + return(0); /* child returns 0 just like fork() */ + } + else { /* Parent */ + *ptrfdm = fdm; /* Return fd of master */ + return(pid); /* Parent returns pid of child */ + } +} +#endif /* HAVE_FORKPTY */ diff --git a/crypto/kerberosIV/appl/bsd/iruserok.c b/crypto/kerberosIV/appl/bsd/iruserok.c new file mode 100644 index 0000000..8349d85 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/iruserok.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID("$Id: iruserok.c,v 1.15 1997/03/23 04:54:00 assar Exp $"); + +#ifndef HAVE_IRUSEROK + +int __check_rhosts_file = 1; +char *__rcmd_errstr = 0; + +/* + * Returns "true" if match, 0 if no match. + */ +static +int +__icheckhost(u_int32_t raddr, const char *lhost) +{ + struct hostent *hp; + u_long laddr; + char **pp; + + /* Try for raw ip address first. */ + if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1) + return (raddr == laddr); + + /* Better be a hostname. */ + if ((hp = gethostbyname(lhost)) == NULL) + return (0); + + /* Spin through ip addresses. */ + for (pp = hp->h_addr_list; *pp; ++pp) + if (memcmp(&raddr, *pp, sizeof(u_long)) == 0) + return (1); + + /* No match. */ + return (0); +} + +#ifndef HAVE_INNETGR +static int +innetgr(const char *netgroup, const char *machine, + const char *user, const char *domain) +{ + return 0; +} +#endif + +/* + * Returns 0 if ok, -1 if not ok. + */ +static +int +__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, + const char *ruser) +{ + char *user, *p; + int ch; + char buf[MaxHostNameLen + 128]; /* host + login */ + char hname[MaxHostNameLen]; + struct hostent *hp; + /* Presumed guilty until proven innocent. */ + int userok = 0, hostok = 0; +#ifdef HAVE_YP_GET_DEFAULT_DOMAIN + char *ypdomain; + + if (yp_get_default_domain(&ypdomain)) + ypdomain = NULL; +#else +#define ypdomain NULL +#endif + /* We need to get the damn hostname back for netgroup matching. */ + if ((hp = gethostbyaddr((char *)&raddr, + sizeof(u_long), + AF_INET)) == NULL) + return (-1); + strncpy(hname, hp->h_name, sizeof(hname)); + hname[sizeof(hname) - 1] = '\0'; + + while (fgets(buf, sizeof(buf), hostf)) { + p = buf; + /* Skip lines that are too long. */ + if (strchr(p, '\n') == NULL) { + while ((ch = getc(hostf)) != '\n' && ch != EOF); + continue; + } + if (*p == '\n' || *p == '#') { + /* comment... */ + continue; + } + while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { + *p = isupper(*p) ? tolower(*p) : *p; + p++; + } + if (*p == ' ' || *p == '\t') { + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + user = p; + while (*p != '\n' && *p != ' ' && + *p != '\t' && *p != '\0') + p++; + } else + user = p; + *p = '\0'; + /* + * Do +/- and +@/-@ checking. This looks really nasty, + * but it matches SunOS's behavior so far as I can tell. + */ + switch(buf[0]) { + case '+': + if (!buf[1]) { /* '+' matches all hosts */ + hostok = 1; + break; + } + if (buf[1] == '@') /* match a host by netgroup */ + hostok = innetgr((char *)&buf[2], + (char *)&hname, NULL, ypdomain); + else /* match a host by addr */ + hostok = __icheckhost(raddr,(char *)&buf[1]); + break; + case '-': /* reject '-' hosts and all their users */ + if (buf[1] == '@') { + if (innetgr((char *)&buf[2], + (char *)&hname, NULL, ypdomain)) + return(-1); + } else { + if (__icheckhost(raddr,(char *)&buf[1])) + return(-1); + } + break; + default: /* if no '+' or '-', do a simple match */ + hostok = __icheckhost(raddr, buf); + break; + } + switch(*user) { + case '+': + if (!*(user+1)) { /* '+' matches all users */ + userok = 1; + break; + } + if (*(user+1) == '@') /* match a user by netgroup */ + userok = innetgr(user+2, NULL, (char *)ruser, + ypdomain); + else /* match a user by direct specification */ + userok = !(strcmp(ruser, user+1)); + break; + case '-': /* if we matched a hostname, */ + if (hostok) { /* check for user field rejections */ + if (!*(user+1)) + return(-1); + if (*(user+1) == '@') { + if (innetgr(user+2, NULL, + (char *)ruser, ypdomain)) + return(-1); + } else { + if (!strcmp(ruser, user+1)) + return(-1); + } + } + break; + default: /* no rejections: try to match the user */ + if (hostok) + userok = !(strcmp(ruser,*user ? user : luser)); + break; + } + if (hostok && userok) + return(0); + } + return (-1); +} + +/* + * New .rhosts strategy: We are passed an ip address. We spin through + * hosts.equiv and .rhosts looking for a match. When the .rhosts only + * has ip addresses, we don't have to trust a nameserver. When it + * contains hostnames, we spin through the list of addresses the nameserver + * gives us and look for a match. + * + * Returns 0 if ok, -1 if not ok. + */ +int +iruserok(u_int32_t raddr, int superuser, const char *ruser, const char *luser) +{ + char *cp; + struct stat sbuf; + struct passwd *pwd; + FILE *hostf; + uid_t uid; + int first; + char pbuf[MaxPathLen]; + + first = 1; + hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); +again: + if (hostf) { + if (__ivaliduser(hostf, raddr, luser, ruser) == 0) { + fclose(hostf); + return (0); + } + fclose(hostf); + } + if (first == 1 && (__check_rhosts_file || superuser)) { + first = 0; + if ((pwd = k_getpwnam((char*)luser)) == NULL) + return (-1); + strcpy(pbuf, pwd->pw_dir); + strcat(pbuf, "/.rhosts"); + + /* + * Change effective uid while opening .rhosts. If root and + * reading an NFS mounted file system, can't read files that + * are protected read/write owner only. + */ + uid = geteuid(); + seteuid(pwd->pw_uid); + hostf = fopen(pbuf, "r"); + seteuid(uid); + + if (hostf == NULL) + return (-1); + /* + * If not a regular file, or is owned by someone other than + * user or root or if writeable by anyone but the owner, quit. + */ + cp = NULL; + if (lstat(pbuf, &sbuf) < 0) + cp = ".rhosts lstat failed"; + else if (!S_ISREG(sbuf.st_mode)) + cp = ".rhosts not regular file"; + else if (fstat(fileno(hostf), &sbuf) < 0) + cp = ".rhosts fstat failed"; + else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) + cp = "bad .rhosts owner"; + else if (sbuf.st_mode & (S_IWGRP|S_IWOTH)) + cp = ".rhosts writeable by other than owner"; + /* If there were any problems, quit. */ + if (cp) { + __rcmd_errstr = cp; + fclose(hostf); + return (-1); + } + goto again; + } + return (-1); +} + +#endif /* !HAVE_IRUSEROK */ diff --git a/crypto/kerberosIV/appl/bsd/kcmd.c b/crypto/kerberosIV/appl/bsd/kcmd.c new file mode 100644 index 0000000..9fa7ab2 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/kcmd.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID("$Id: kcmd.c,v 1.19 1997/05/02 14:27:42 assar Exp $"); + +#define START_PORT 5120 /* arbitrary */ + +static int +getport(int *alport) +{ + struct sockaddr_in sin; + int s; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + return (-1); + for (;;) { + sin.sin_port = htons((u_short)*alport); + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + return (s); + if (errno != EADDRINUSE) { + close(s); + return (-1); + } + (*alport)--; +#ifdef ATHENA_COMPAT + if (*alport == IPPORT_RESERVED/2) { +#else + if (*alport == IPPORT_RESERVED) { +#endif + close(s); + errno = EAGAIN; /* close */ + return (-1); + } + } +} + +int +kcmd(int *sock, + char **ahost, + u_int16_t rport, + char *locuser, + char *remuser, + char *cmd, + int *fd2p, + KTEXT ticket, + char *service, + char *realm, + CREDENTIALS *cred, + Key_schedule schedule, + MSG_DAT *msg_data, + struct sockaddr_in *laddr, + struct sockaddr_in *faddr, + int32_t authopts) +{ + int s, timo = 1; + pid_t pid; + struct sockaddr_in sin, from; + char c; +#ifdef ATHENA_COMPAT + int lport = IPPORT_RESERVED - 1; +#else + int lport = START_PORT; +#endif + struct hostent *hp; + int rc; + char *host_save; + int status; + + pid = getpid(); + hp = gethostbyname(*ahost); + if (hp == NULL) { + /* fprintf(stderr, "%s: unknown host\n", *ahost); */ + return (-1); + } + + host_save = strdup(hp->h_name); + if (host_save == NULL) + return -1; + *ahost = host_save; + + /* If realm is null, look up from table */ + if (realm == NULL || realm[0] == '\0') + realm = krb_realmofhost(host_save); + + for (;;) { + s = getport(&lport); + if (s < 0) { + if (errno == EAGAIN) + warnx("kcmd(socket): All ports in use\n"); + else + warn("kcmd: socket"); + return (-1); + } + sin.sin_family = hp->h_addrtype; + memcpy (&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); + sin.sin_port = rport; + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + break; + close(s); + if (errno == EADDRINUSE) { + lport--; + continue; + } + /* + * don't wait very long for Kerberos rcmd. + */ + if (errno == ECONNREFUSED && timo <= 4) { + /* sleep(timo); don't wait at all here */ + timo *= 2; + continue; + } + if (hp->h_addr_list[1] != NULL) { + warn ("kcmd: connect (%s)", + inet_ntoa(sin.sin_addr)); + hp->h_addr_list++; + memcpy(&sin.sin_addr, + hp->h_addr_list[0], + sizeof(sin.sin_addr)); + fprintf(stderr, "Trying %s...\n", + inet_ntoa(sin.sin_addr)); + continue; + } + if (errno != ECONNREFUSED) + warn ("connect(%s)", hp->h_name); + return (-1); + } + lport--; + if (fd2p == 0) { + write(s, "", 1); + lport = 0; + } else { + char num[8]; + int s2 = getport(&lport), s3; + int len = sizeof(from); + + if (s2 < 0) { + status = -1; + goto bad; + } + listen(s2, 1); + snprintf(num, sizeof(num), "%d", lport); + if (write(s, num, strlen(num) + 1) != strlen(num) + 1) { + warn("kcmd(write): setting up stderr"); + close(s2); + status = -1; + goto bad; + } + { + fd_set fds; + FD_ZERO(&fds); + FD_SET(s, &fds); + FD_SET(s2, &fds); + status = select(FD_SETSIZE, &fds, NULL, NULL, NULL); + if(FD_ISSET(s, &fds)){ + warnx("kcmd: connection unexpectedly closed."); + close(s2); + status = -1; + goto bad; + } + } + s3 = accept(s2, (struct sockaddr *)&from, &len); + close(s2); + if (s3 < 0) { + warn ("kcmd: accept"); + lport = 0; + status = -1; + goto bad; + } + + *fd2p = s3; + from.sin_port = ntohs((u_short)from.sin_port); + if (from.sin_family != AF_INET || + from.sin_port >= IPPORT_RESERVED) { + warnx("kcmd(socket): " + "protocol failure in circuit setup."); + status = -1; + goto bad2; + } + } + /* + * Kerberos-authenticated service. Don't have to send locuser, + * since its already in the ticket, and we'll extract it on + * the other side. + */ + /* write(s, locuser, strlen(locuser)+1); */ + + /* set up the needed stuff for mutual auth, but only if necessary */ + if (authopts & KOPT_DO_MUTUAL) { + int sin_len; + *faddr = sin; + + sin_len = sizeof(struct sockaddr_in); + if (getsockname(s, (struct sockaddr *)laddr, &sin_len) < 0) { + warn("kcmd(getsockname)"); + status = -1; + goto bad2; + } + } + if ((status = krb_sendauth(authopts, s, ticket, service, *ahost, + realm, (unsigned long) getpid(), msg_data, + cred, schedule, + laddr, + faddr, + "KCMDV0.1")) != KSUCCESS) + goto bad2; + + write(s, remuser, strlen(remuser)+1); + write(s, cmd, strlen(cmd)+1); + + if ((rc = read(s, &c, 1)) != 1) { + if (rc == -1) + warn("read(%s)", *ahost); + else + warnx("kcmd: bad connection with remote host"); + status = -1; + goto bad2; + } + if (c != '\0') { + while (read(s, &c, 1) == 1) { + write(2, &c, 1); + if (c == '\n') + break; + } + status = -1; + goto bad2; + } + *sock = s; + return (KSUCCESS); +bad2: + if (lport) + close(*fd2p); +bad: + close(s); + return (status); +} diff --git a/crypto/kerberosIV/appl/bsd/klogin.c b/crypto/kerberosIV/appl/bsd/klogin.c new file mode 100644 index 0000000..321da64 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/klogin.c @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID("$Id: klogin.c,v 1.20 1997/05/02 14:27:42 assar Exp $"); + +#ifdef KERBEROS + +#define VERIFY_SERVICE "rcmd" + +extern int notickets; +extern char *krbtkfile_env; + +static char tkt_location[MaxPathLen]; + +/* + * Attempt to log the user in using Kerberos authentication + * + * return 0 on success (will be logged in) + * 1 if Kerberos failed (try local password in login) + */ +int +klogin(struct passwd *pw, char *instance, char *localhost, char *password) +{ + int kerror; + AUTH_DAT authdata; + KTEXT_ST ticket; + struct hostent *hp; + u_int32_t faddr; + char realm[REALM_SZ], savehost[MaxHostNameLen]; + extern int noticketsdontcomplain; + +#ifdef KLOGIN_PARANOID + noticketsdontcomplain = 0; /* enable warning message */ +#endif + /* + * Root logins don't use Kerberos. + * If we have a realm, try getting a ticket-granting ticket + * and using it to authenticate. Otherwise, return + * failure so that we can try the normal passwd file + * for a password. If that's ok, log the user in + * without issuing any tickets. + */ + if (strcmp(pw->pw_name, "root") == 0 || + krb_get_lrealm(realm, 0) != KSUCCESS) + return (1); + + noticketsdontcomplain = 0; /* enable warning message */ + + /* + * get TGT for local realm + * tickets are stored in a file named TKT_ROOT plus uid + * except for user.root tickets. + */ + + if (strcmp(instance, "root") != 0) + snprintf(tkt_location, sizeof(tkt_location), + "%s%u_%u", + TKT_ROOT, (unsigned)pw->pw_uid, (unsigned)getpid()); + else { + snprintf(tkt_location, sizeof(tkt_location), + "%s_root_%d", TKT_ROOT, + (unsigned)pw->pw_uid); + } + krbtkfile_env = tkt_location; + krb_set_tkt_string(tkt_location); + + kerror = krb_get_pw_in_tkt(pw->pw_name, instance, + realm, KRB_TICKET_GRANTING_TICKET, realm, + DEFAULT_TKT_LIFE, password); + + /* + * If we got a TGT, get a local "rcmd" ticket and check it so as to + * ensure that we are not talking to a bogus Kerberos server. + * + * There are 2 cases where we still allow a login: + * 1: the VERIFY_SERVICE doesn't exist in the KDC + * 2: local host has no srvtab, as (hopefully) indicated by a + * return value of RD_AP_UNDEC from krb_rd_req(). + */ + if (kerror != INTK_OK) { + if (kerror != INTK_BADPW && kerror != KDC_PR_UNKNOWN) { + syslog(LOG_ERR, "Kerberos intkt error: %s", + krb_get_err_text(kerror)); + dest_tkt(); + } + return (1); + } + + if (chown(TKT_FILE, pw->pw_uid, pw->pw_gid) < 0) + syslog(LOG_ERR, "chown tkfile (%s): %m", TKT_FILE); + + strncpy(savehost, krb_get_phost(localhost), sizeof(savehost)); + savehost[sizeof(savehost)-1] = '\0'; + +#ifdef KLOGIN_PARANOID + /* + * if the "VERIFY_SERVICE" doesn't exist in the KDC for this host, + * don't allow kerberos login, also log the error condition. + */ + + kerror = krb_mk_req(&ticket, VERIFY_SERVICE, savehost, realm, 33); + if (kerror == KDC_PR_UNKNOWN) { + syslog(LOG_NOTICE, + "warning: TGT not verified (%s); %s.%s not registered, or srvtab is wrong?", + krb_get_err_text(kerror), VERIFY_SERVICE, savehost); + notickets = 0; + return (1); + } + + if (kerror != KSUCCESS) { + warnx("unable to use TGT: (%s)", krb_get_err_text(kerror)); + syslog(LOG_NOTICE, "unable to use TGT: (%s)", + krb_get_err_text(kerror)); + dest_tkt(); + return (1); + } + + if (!(hp = gethostbyname(localhost))) { + syslog(LOG_ERR, "couldn't get local host address"); + dest_tkt(); + return (1); + } + + memcpy(&faddr, hp->h_addr, sizeof(faddr)); + + kerror = krb_rd_req(&ticket, VERIFY_SERVICE, savehost, faddr, + &authdata, ""); + + if (kerror == KSUCCESS) { + notickets = 0; + return (0); + } + + /* undecipherable: probably didn't have a srvtab on the local host */ + if (kerror == RD_AP_UNDEC) { + syslog(LOG_NOTICE, "krb_rd_req: (%s)\n", krb_get_err_text(kerror)); + dest_tkt(); + return (1); + } + /* failed for some other reason */ + warnx("unable to verify %s ticket: (%s)", VERIFY_SERVICE, + krb_get_err_text(kerror)); + syslog(LOG_NOTICE, "couldn't verify %s ticket: %s", VERIFY_SERVICE, + krb_get_err_text(kerror)); + dest_tkt(); + return (1); +#else + notickets = 0; + return (0); +#endif +} +#endif diff --git a/crypto/kerberosIV/appl/bsd/krcmd.c b/crypto/kerberosIV/appl/bsd/krcmd.c new file mode 100644 index 0000000..8c3c6f3 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/krcmd.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID("$Id: krcmd.c,v 1.10 1997/03/30 18:20:18 joda Exp $"); + +#define SERVICE_NAME "rcmd" + +/* + * krcmd: simplified version of Athena's "kcmd" + * returns a socket attached to the destination, -1 or krb error on error + * if fd2p is non-NULL, another socket is filled in for it + */ + +int +krcmd(char **ahost, u_short rport, char *remuser, char *cmd, int *fd2p, char *realm) +{ + int sock = -1, err = 0; + KTEXT_ST ticket; + long authopts = 0L; + + err = kcmd( + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + &ticket, + SERVICE_NAME, + realm, + (CREDENTIALS *) NULL, /* credentials not used */ + 0, /* key schedule not used */ + (MSG_DAT *) NULL, /* MSG_DAT not used */ + (struct sockaddr_in *) NULL, /* local addr not used */ + (struct sockaddr_in *) NULL, /* foreign addr not used */ + authopts + ); + + if (err > KSUCCESS && err < MAX_KRB_ERRORS) { + warning("krcmd: %s", krb_get_err_text(err)); + return(-1); + } + if (err < 0) + return(-1); + return(sock); +} + +int +krcmd_mutual(char **ahost, u_short rport, char *remuser, char *cmd, int *fd2p, char *realm, CREDENTIALS *cred, Key_schedule sched) +{ + int sock, err; + KTEXT_ST ticket; + MSG_DAT msg_dat; + struct sockaddr_in laddr, faddr; + long authopts = KOPT_DO_MUTUAL; + + err = kcmd( + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + &ticket, + SERVICE_NAME, + realm, + cred, /* filled in */ + sched, /* filled in */ + &msg_dat, /* filled in */ + &laddr, /* filled in */ + &faddr, /* filled in */ + authopts + ); + + if (err > KSUCCESS && err < MAX_KRB_ERRORS) { + warnx("krcmd_mutual: %s", krb_get_err_text(err)); + return(-1); + } + + if (err < 0) + return (-1); + return(sock); +} diff --git a/crypto/kerberosIV/appl/bsd/login.c b/crypto/kerberosIV/appl/bsd/login.c new file mode 100644 index 0000000..c436f8d --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/login.c @@ -0,0 +1,990 @@ +/*- + * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * login [ name ] + * login -h hostname (for telnetd, etc.) + * login -f name (for pre-authenticated login: datakit, xterm, etc.) + */ + +#include "bsd_locl.h" + +RCSID("$Id: login.c,v 1.104 1997/05/20 20:35:06 assar Exp $"); + +#include <otp.h> + +#include "sysv_default.h" +#ifdef SYSV_SHADOW +#include "sysv_shadow.h" +#endif + +static void badlogin (char *); +static void checknologin (void); +static void dolastlog (int); +static void getloginname (int); +static int rootterm (char *); +static char *stypeof (char *); +static RETSIGTYPE timedout (int); +static int doremotelogin (char *); +void login_fbtab (char *, uid_t, gid_t); +#ifdef KERBEROS +int klogin (struct passwd *, char *, char *, char *); +#endif + +#define TTYGRPNAME "tty" /* name of group to own ttys */ + +/* + * This bounds the time given to login. Change it in + * `/etc/default/login'. + */ + +static u_int login_timeout; + +#ifdef KERBEROS +int notickets = 1; +int noticketsdontcomplain = 1; +char *instance; +char *krbtkfile_env; +int authok; +#endif + +#ifdef HAVE_SHADOW_H +static struct spwd *spwd = NULL; +#endif + +static char *ttyprompt; + +static struct passwd *pwd; +static int failures; +static char term[64], *hostname, *username, *tty; + +static char rusername[100], lusername[100]; + +static int +change_passwd(struct passwd *who) +{ + int status; + int pid; + int wpid; + + switch (pid = fork()) { + case -1: + warn("fork /bin/passwd"); + sleepexit(1); + case 0: + execlp("/bin/passwd", "passwd", who->pw_name, (char *) 0); + _exit(1); + default: + while ((wpid = wait(&status)) != -1 && wpid != pid) + /* void */ ; + return (status); + } +} + +#ifndef NO_MOTD /* message of the day stuff */ + +jmp_buf motdinterrupt; + +static RETSIGTYPE +sigint(int signo) +{ + longjmp(motdinterrupt, 1); +} + +static void +motd(void) +{ + int fd, nchars; + RETSIGTYPE (*oldint)(); + char tbuf[8192]; + + if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) + return; + oldint = signal(SIGINT, sigint); + if (setjmp(motdinterrupt) == 0) + while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) + write(fileno(stdout), tbuf, nchars); + signal(SIGINT, oldint); + close(fd); +} + +#endif /* !NO_MOTD */ + +#define AUTH_NONE 0 +#define AUTH_OTP 1 + +/* + * getpwnam and try to detect the worst form of NIS attack. + */ + +static struct passwd * +paranoid_getpwnam (char *user) +{ + struct passwd *p; + + p = k_getpwnam (user); + if (p == NULL) + return p; + if (p->pw_uid == 0 && strcmp (username, "root") != 0) { + syslog (LOG_ALERT, + "NIS attack, user %s has uid 0", username); + return NULL; + } + return p; +} + +int +main(int argc, char **argv) +{ + struct group *gr; + int ask, ch, cnt, fflag, hflag, pflag, quietlog, nomailcheck; + int rootlogin, rval; + int rflag; + int changepass = 0; + uid_t uid; + char *domain, *p, passwd[128], *ttyn; + char tbuf[MaxPathLen + 2], tname[sizeof(_PATH_TTY) + 10]; + char localhost[MaxHostNameLen]; + char full_hostname[MaxHostNameLen]; + int auth_level = AUTH_NONE; + OtpContext otp_ctx; + int mask = 022; /* Default umask (set below) */ + int maxtrys = 5; /* Default number of allowed failed logins */ + + set_progname(argv[0]); + + openlog("login", LOG_ODELAY, LOG_AUTH); + + /* Read defaults file and set the login timeout period. */ + sysv_defaults(); + login_timeout = atoi(default_timeout); + maxtrys = atoi(default_maxtrys); + if (sscanf(default_umask, "%o", &mask) != 1 || (mask & ~0777)) + syslog(LOG_WARNING, "bad umask default: %s", default_umask); + else + umask(mask); + + signal(SIGALRM, timedout); + alarm(login_timeout); + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, SIG_IGN); + setpriority(PRIO_PROCESS, 0, 0); + + /* + * -p is used by getty to tell login not to destroy the environment + * -f is used to skip a second login authentication + * -h is used by other servers to pass the name of the remote + * host to login so that it may be placed in utmp and wtmp + * -r is used by old-style rlogind to execute the autologin protocol + */ + + *full_hostname = '\0'; + domain = NULL; + if (k_gethostname(localhost, sizeof(localhost)) < 0) + syslog(LOG_ERR, "couldn't get local hostname: %m"); + else + domain = strchr(localhost, '.'); + + fflag = hflag = pflag = rflag = 0; + uid = getuid(); + while ((ch = getopt(argc, argv, "a:d:fh:pr:")) != EOF) + switch (ch) { + case 'a': + if (strcmp (optarg, "none") == 0) + auth_level = AUTH_NONE; + else if (strcmp (optarg, "otp") == 0) + auth_level = AUTH_OTP; + else + warnx ("bad value for -a: %s", optarg); + break; + case 'd': + break; + case 'f': + fflag = 1; + break; + case 'h': + if (rflag || hflag) { + printf("Only one of -r and -h allowed\n"); + exit(1); + } + if (uid) + errx(1, "-h option: %s", strerror(EPERM)); + hflag = 1; + strncpy(full_hostname, optarg, sizeof(full_hostname)-1); + if (domain && (p = strchr(optarg, '.')) && + strcasecmp(p, domain) == 0) + *p = 0; + hostname = optarg; + break; + case 'p': + if (getuid()) { + warnx("-p for super-user only."); + exit(1); + } + pflag = 1; + break; + case 'r': + if (rflag || hflag) { + warnx("Only one of -r and -h allowed\n"); + exit(1); + } + if (getuid()) { + warnx("-r for super-user only."); + exit(1); + } + rflag = 1; + strncpy(full_hostname, optarg, sizeof(full_hostname)-1); + if (domain && (p = strchr(optarg, '.')) && + strcasecmp(p, domain) == 0) + *p = 0; + hostname = optarg; + fflag = (doremotelogin(full_hostname) == 0); + break; + case '?': + default: + if (!uid) + syslog(LOG_ERR, "invalid flag %c", ch); + fprintf(stderr, + "usage: login [-fp] [-a otp]" + "[-h hostname | -r hostname] [username]\n"); + exit(1); + } + argc -= optind; + argv += optind; + + if (geteuid() != 0) { + warnx("only root may use login, use su"); + /* Or install login setuid root, which is not necessary */ + sleep(10); + exit(1); + } + /* + * Figure out if we should ask for the username or not. The name + * may be given on the command line or via the environment, and + * it may even be in the terminal input queue. + */ + if (rflag) { + username = lusername; + ask = 0; + } else + if (*argv && strchr(*argv, '=')) { + ask = 1; + } else + if (*argv && strcmp(*argv, "-") == 0) { + argc--; + argv++; + ask = 1; + } else + if (*argv) { + username = *argv; + ask = 0; + argc--; + argv++; + } else if ((ttyprompt = getenv("TTYPROMPT")) && *ttyprompt) { + getloginname(0); + ask = 0; + } else + ask = 1; + + /* Default tty settings. */ + stty_default(); + + for (cnt = getdtablesize(); cnt > 2; cnt--) + close(cnt); + + /* + * Determine the tty name. BSD takes the basename, SYSV4 takes + * whatever remains after stripping the "/dev/" prefix. The code + * below should produce sensible results in either environment. + */ + ttyn = ttyname(STDIN_FILENO); + if (ttyn == NULL || *ttyn == '\0') { + snprintf(tname, sizeof(tname), "%s??", _PATH_TTY); + ttyn = tname; + } + if ((tty = strchr(ttyn + 1, '/'))) + ++tty; + else + tty = ttyn; + + for (cnt = 0;; ask = 1) { + char prompt[128], ss[256]; + if (ask) { + fflag = 0; + getloginname(1); + } + rootlogin = 0; + rval = 1; +#ifdef KERBEROS + if ((instance = strchr(username, '.')) != NULL) { + if (strcmp(instance, ".root") == 0) + rootlogin = 1; + *instance++ = '\0'; + } else + instance = ""; +#endif + if (strlen(username) > UT_NAMESIZE) + username[UT_NAMESIZE] = '\0'; + + /* + * Note if trying multiple user names; log failures for + * previous user name, but don't bother logging one failure + * for nonexistent name (mistyped username). + */ + if (failures && strcmp(tbuf, username)) { + if (failures > (pwd ? 0 : 1)) + badlogin(tbuf); + failures = 0; + } + strcpy(tbuf, username); + + pwd = paranoid_getpwnam (username); + + /* + * if we have a valid account name, and it doesn't have a + * password, or the -f option was specified and the caller + * is root or the caller isn't changing their uid, don't + * authenticate. + */ + if (pwd) { + if (pwd->pw_uid == 0) + rootlogin = 1; + + if (fflag && (uid == 0 || uid == pwd->pw_uid)) { + /* already authenticated */ + break; + } else if (pwd->pw_passwd[0] == '\0') { + /* pretend password okay */ + rval = 0; + goto ttycheck; + } + } + + fflag = 0; + + setpriority(PRIO_PROCESS, 0, -4); + + if (otp_challenge (&otp_ctx, username, + ss, sizeof(ss)) == 0) + snprintf (prompt, sizeof(prompt), "%s's %s Password: ", + username, ss); + else { + if (auth_level == AUTH_NONE) + snprintf(prompt, sizeof(prompt), "%s's Password: ", + username); + else { + char *s; + + rval = 1; + s = otp_error(&otp_ctx); + if(s) + printf ("OTP: %s\n", s); + continue; + } + } + + if (des_read_pw_string (passwd, sizeof(passwd) - 1, prompt, 0)) + continue; + passwd[sizeof(passwd) - 1] = '\0'; + + /* Verify it somehow */ + + if (otp_verify_user (&otp_ctx, passwd) == 0) + rval = 0; + else if (pwd == NULL) + ; + else if (auth_level == AUTH_NONE) { + uid_t pwd_uid = pwd->pw_uid; + + rval = unix_verify_user (username, passwd); + + if (rval == 0) + { + if (rootlogin && pwd_uid != 0) + rootlogin = 0; + } + else + { + rval = klogin(pwd, instance, localhost, passwd); + if (rval != 0 && rootlogin && pwd_uid != 0) + rootlogin = 0; + if (rval == 0) + authok = 1; + } + } else { + char *s; + + rval = 1; + if ((s = otp_error(&otp_ctx))) + printf ("OTP: %s\n", s); + } + + memset (passwd, 0, sizeof(passwd)); + setpriority (PRIO_PROCESS, 0, 0); + + /* + * Santa Claus, give me a portable and reentrant getpwnam. + */ + pwd = paranoid_getpwnam (username); + + ttycheck: + /* + * If trying to log in as root without Kerberos, + * but with insecure terminal, refuse the login attempt. + */ +#ifdef KERBEROS + if (authok == 0) +#endif + if (pwd && !rval && rootlogin && !rootterm(tty) + && !rootterm(ttyn)) { + warnx("%s login refused on this terminal.", + pwd->pw_name); + if (hostname) + syslog(LOG_NOTICE, + "LOGIN %s REFUSED FROM %s ON TTY %s", + pwd->pw_name, hostname, tty); + else + syslog(LOG_NOTICE, + "LOGIN %s REFUSED ON TTY %s", + pwd->pw_name, tty); + continue; + } + + if (rval == 0) + break; + + printf("Login incorrect\n"); + failures++; + + /* max number of attemps and delays taken from defaults file */ + /* we allow maxtrys tries, but after 2 we start backing off */ + if (++cnt > 2) { + if (cnt >= maxtrys) { + badlogin(username); + sleepexit(1); + } + sleep((u_int)((cnt - 2) * atoi(default_sleep))); + } + } + + /* committed to login -- turn off timeout */ + alarm(0); + + endpwent(); + +#if defined(HAVE_GETUDBNAM) && defined(HAVE_SETLIM) + { + struct udb *udb; + long t; + const long maxcpu = 46116860184; /* some random constant */ + udb = getudbnam(pwd->pw_name); + if(udb == UDB_NULL){ + warnx("Failed to get UDB entry."); + exit(1); + } + t = udb->ue_pcpulim[UDBRC_INTER]; + if(t == 0 || t > maxcpu) + t = CPUUNLIM; + else + t *= 100 * CLOCKS_PER_SEC; + + if(limit(C_PROC, 0, L_CPU, t) < 0) + warn("limit C_PROC"); + + t = udb->ue_jcpulim[UDBRC_INTER]; + if(t == 0 || t > maxcpu) + t = CPUUNLIM; + else + t *= 100 * CLOCKS_PER_SEC; + + if(limit(C_JOBPROCS, 0, L_CPU, t) < 0) + warn("limit C_JOBPROCS"); + + nice(udb->ue_nice[UDBRC_INTER]); + } +#endif + /* if user not super-user, check for disabled logins */ + if (!rootlogin) + checknologin(); + + if (chdir(pwd->pw_dir) < 0) { + printf("No home directory %s!\n", pwd->pw_dir); + if (chdir("/")) + exit(0); + pwd->pw_dir = "/"; + printf("Logging in with home = \"/\".\n"); + } + + quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; + nomailcheck = access(_PATH_NOMAILCHECK, F_OK) == 0; + +#if defined(HAVE_PASSWD_CHANGE) && defined(HAVE_PASSWD_EXPIRE) + if (pwd->pw_change || pwd->pw_expire) + gettimeofday(&tp, (struct timezone *)NULL); + + if (pwd->pw_change) + if (tp.tv_sec >= pwd->pw_change) { + printf("Sorry -- your password has expired.\n"); + changepass=1; + } else if (pwd->pw_change - tp.tv_sec < + 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) + printf("Warning: your password expires on %s", + ctime(&pwd->pw_change)); + if (pwd->pw_expire) + if (tp.tv_sec >= pwd->pw_expire) { + printf("Sorry -- your account has expired.\n"); + sleepexit(1); + } else if (pwd->pw_expire - tp.tv_sec < + 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) + printf("Warning: your account expires on %s", + ctime(&pwd->pw_expire)); +#endif /* defined(HAVE_PASSWD_CHANGE) && defined(HAVE_PASSWD_EXPIRE) */ + + /* Nothing else left to fail -- really log in. */ + + /* + * Update the utmp files, both BSD and SYSV style. + */ + if (utmpx_login(tty, username, hostname ? hostname : "") != 0 + && !fflag) { + printf("No utmpx entry. You must exec \"login\" from the lowest level \"sh\".\n"); + sleepexit(0); + } + utmp_login(ttyn, username, hostname ? hostname : ""); + dolastlog(quietlog); + + /* + * Set device protections, depending on what terminal the + * user is logged in. This feature is used on Suns to give + * console users better privacy. + */ + login_fbtab(tty, pwd->pw_uid, pwd->pw_gid); + + chown(ttyn, pwd->pw_uid, + (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); + chmod(ttyn, S_IRUSR | S_IWUSR | S_IWGRP); + setgid(pwd->pw_gid); + + initgroups(username, pwd->pw_gid); + + if (*pwd->pw_shell == '\0') + pwd->pw_shell = _PATH_BSHELL; + + /* + * Set up a new environment. With SYSV, some variables are always + * preserved; some varables are never preserved, and some variables + * are always clobbered. With BSD, nothing is always preserved, and + * some variables are always clobbered. We add code to make sure + * that LD_* and IFS are never preserved. + */ + if (term[0] == '\0') + strncpy(term, stypeof(tty), sizeof(term)); + /* set up a somewhat censored environment. */ + sysv_newenv(argc, argv, pwd, term, pflag); +#ifdef KERBEROS + if (krbtkfile_env) + setenv("KRBTKFILE", krbtkfile_env, 1); +#endif + + if (tty[sizeof("tty")-1] == 'd') + syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); + + /* If fflag is on, assume caller/authenticator has logged root login. */ + if (rootlogin && fflag == 0) + if (hostname) + syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", + username, tty, hostname); + else + syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty); + +#ifdef KERBEROS + if (!quietlog && notickets == 1 && !noticketsdontcomplain) + printf("Warning: no Kerberos tickets issued.\n"); +#endif + +#ifdef LOGALL + /* + * Syslog each successful login, so we don't have to watch hundreds + * of wtmp or lastlogin files. + */ + if (hostname) { + syslog(LOG_INFO, "login from %s as %s", hostname, pwd->pw_name); + } else { + syslog(LOG_INFO, "login on %s as %s", tty, pwd->pw_name); + } +#endif + +#ifndef NO_MOTD + /* + * Optionally show the message of the day. System V login leaves + * motd and mail stuff up to the shell startup file. + */ + if (!quietlog) { + struct stat st; +#if 0 + printf("%s\n\t%s %s\n\n", + "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994", + "The Regents of the University of California. ", + "All rights reserved."); +#endif + motd(); + if(!nomailcheck){ + snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name); + if (stat(tbuf, &st) == 0 && st.st_size != 0) + printf("You have %smail.\n", + (st.st_mtime > st.st_atime) ? "new " : ""); + } + } +#endif /* NO_MOTD */ + +#ifdef LOGIN_ACCESS + if (login_access(pwd->pw_name, hostname ? full_hostname : tty) == 0) { + printf("Permission denied\n"); + if (hostname) + syslog(LOG_NOTICE, "%s LOGIN REFUSED FROM %s", + pwd->pw_name, hostname); + else + syslog(LOG_NOTICE, "%s LOGIN REFUSED ON %s", + pwd->pw_name, tty); + sleepexit(1); + } +#endif + + signal(SIGALRM, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTSTP, SIG_IGN); + + tbuf[0] = '-'; + strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ? + p + 1 : pwd->pw_shell); + +#ifdef HAVE_SETLOGIN + if (setlogin(pwd->pw_name) < 0) + syslog(LOG_ERR, "setlogin() failure: %m"); +#endif + +#ifdef HAVE_SETPCRED + if (setpcred (pwd->pw_name, NULL) == -1) + syslog(LOG_ERR, "setpcred() failure: %m"); +#endif /* HAVE_SETPCRED */ + +#if defined(SYSV_SHADOW) && defined(HAVE_GETSPNAM) + spwd = getspnam (username); + endspent (); +#endif + /* Discard permissions last so can't get killed and drop core. */ + { + int uid = rootlogin ? 0 : pwd->pw_uid; + if(setuid(uid) != 0){ + warn("setuid(%d)", uid); + if(!rootlogin) + exit(1); + } + } + + + /* + * After dropping privileges and after cleaning up the environment, + * optionally run, as the user, /bin/passwd. + */ + + if (pwd->pw_passwd[0] == 0 && + strcasecmp(default_passreq, "YES") == 0) { + printf("You don't have a password. Choose one.\n"); + if (change_passwd(pwd)) + sleepexit(0); + changepass = 0; + } + +#ifdef SYSV_SHADOW + if (spwd && sysv_expire(spwd)) { + if (change_passwd(pwd)) + sleepexit(0); + changepass = 0; + } +#endif /* SYSV_SHADOW */ + if (changepass) { + int res; + if ((res=system(_PATH_CHPASS))) + sleepexit(1); + } + + if (k_hasafs()) { + char cell[64]; + k_setpag(); + if(k_afs_cell_of_file(pwd->pw_dir, cell, sizeof(cell)) == 0) + k_afsklog(cell, 0); + k_afsklog(0, 0); + } + + execlp(pwd->pw_shell, tbuf, 0); + if (getuid() == 0) { + warnx("Can't exec %s, trying %s\n", + pwd->pw_shell, _PATH_BSHELL); + execlp(_PATH_BSHELL, tbuf, 0); + err(1, "%s", _PATH_BSHELL); + } + err(1, "%s", pwd->pw_shell); + return 1; +} + +#ifdef KERBEROS +#define NBUFSIZ (UT_NAMESIZE + 1 + 5) /* .root suffix */ +#else +#define NBUFSIZ (UT_NAMESIZE + 1) +#endif + +static void +getloginname(int prompt) +{ + int ch; + char *p; + static char nbuf[NBUFSIZ]; + + for (;;) { + if (prompt) + if (ttyprompt && *ttyprompt) + printf("%s", ttyprompt); + else + printf("login: "); + prompt = 1; + for (p = nbuf; (ch = getchar()) != '\n'; ) { + if (ch == EOF) { + badlogin(username); + exit(0); + } + if (p < nbuf + (NBUFSIZ - 1)) + *p++ = ch; + } + if (p > nbuf) + if (nbuf[0] == '-') + warnx("login names may not start with '-'."); + else { + *p = '\0'; + username = nbuf; + break; + } + } +} + +static int +rootterm(char *ttyn) +{ +#ifndef HAVE_TTYENT_H + return (default_console == 0 || strcmp(default_console, ttyname(0)) == 0); +#else + struct ttyent *t; + + return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); +#endif +} + +static RETSIGTYPE +timedout(int signo) +{ + fprintf(stderr, "Login timed out after %d seconds\n", + login_timeout); + exit(0); +} + +static void +checknologin(void) +{ + int fd, nchars; + char tbuf[8192]; + + if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { + while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) + write(fileno(stdout), tbuf, nchars); + sleepexit(0); + } +} + +static void +dolastlog(int quiet) +{ +#if defined(HAVE_LASTLOG_H) || defined(HAVE_LOGIN_H) || defined(SYSV_SHADOW) + struct lastlog ll; + int fd; + + if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { + lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); +#ifdef SYSV_SHADOW + if (read(fd, &ll, sizeof(ll)) == sizeof(ll) && + ll.ll_time != 0) { + if (pwd->pw_uid && spwd && spwd->sp_inact > 0 + && ll.ll_time / (24 * 60 * 60) + + spwd->sp_inact < time(0)) { + printf("Your account has been inactive too long.\n"); + sleepexit(1); + } + if (!quiet) { + printf("Last login: %.*s ", + 24-5, ctime(&ll.ll_time)); + if (*ll.ll_host != '\0') { + printf("from %.*s\n", + (int)sizeof(ll.ll_host), + ll.ll_host); + } else + printf("on %.*s\n", + (int)sizeof(ll.ll_line), + ll.ll_line); + } + } + lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); +#else /* SYSV_SHADOW */ + if (!quiet) { + if (read(fd, &ll, sizeof(ll)) == sizeof(ll) && + ll.ll_time != 0) { + printf("Last login: %.*s ", + 24-5, ctime(&ll.ll_time)); + if (*ll.ll_host != '\0') + printf("from %.*s\n", + (int)sizeof(ll.ll_host), + ll.ll_host); + else + printf("on %.*s\n", + (int)sizeof(ll.ll_line), + ll.ll_line); + } + lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); + } +#endif /* SYSV_SHADOW */ + memset(&ll, 0, sizeof(ll)); + time(&ll.ll_time); + strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); + if (hostname) + strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); + write(fd, &ll, sizeof(ll)); + close(fd); + } +#endif /* DOLASTLOG */ +} + +static void +badlogin(char *name) +{ + + if (failures == 0) + return; + if (hostname) { + syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s", + failures, failures > 1 ? "S" : "", hostname); + syslog(LOG_AUTHPRIV|LOG_NOTICE, + "%d LOGIN FAILURE%s FROM %s, %s", + failures, failures > 1 ? "S" : "", hostname, name); + } else { + syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s", + failures, failures > 1 ? "S" : "", tty); + syslog(LOG_AUTHPRIV|LOG_NOTICE, + "%d LOGIN FAILURE%s ON %s, %s", + failures, failures > 1 ? "S" : "", tty, name); + } +} + +#undef UNKNOWN +#define UNKNOWN "su" + +static char * +stypeof(char *ttyid) +{ + /* TERM is probably a better guess than anything else. */ + char *term = getenv("TERM"); + + if (term != 0 && term[0] != 0) + return term; + + { +#ifndef HAVE_TTYENT_H + return UNKNOWN; +#else + struct ttyent *t; + return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); +#endif + } +} + +static void +xgetstr(char *buf, int cnt, char *err) +{ + char ch; + + do { + if (read(0, &ch, sizeof(ch)) != sizeof(ch)) + exit(1); + if (--cnt < 0) { + fprintf(stderr, "%s too long\r\n", err); + sleepexit(1); + } + *buf++ = ch; + } while (ch); +} + +/* + * Some old rlogind's unknowingly pass remuser, locuser and + * terminal_type/speed so we need to take care of that part of the + * protocol here. Also, we can't make a getpeername(2) on the socket + * so we have to trust that rlogind resolved the name correctly. + */ + +static int +doremotelogin(char *host) +{ + int code; + char *cp; + + xgetstr(rusername, sizeof (rusername), "remuser"); + xgetstr(lusername, sizeof (lusername), "locuser"); + xgetstr(term, sizeof(term), "Terminal type"); + cp = strchr(term, '/'); + if (cp != 0) + *cp = 0; /* For now ignore speed/bg */ + pwd = k_getpwnam(lusername); + if (pwd == NULL) + return(-1); + code = ruserok(host, (pwd->pw_uid == 0), rusername, lusername); + if (code == 0) + syslog(LOG_NOTICE, + "Warning: An old rlogind accepted login probably from host %s", + host); + return(code); +} + +void +sleepexit(int eval) +{ + + sleep(5); + exit(eval); +} diff --git a/crypto/kerberosIV/appl/bsd/login_access.c b/crypto/kerberosIV/appl/bsd/login_access.c new file mode 100644 index 0000000..0e017b1 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/login_access.c @@ -0,0 +1,221 @@ + /* + * This module implements a simple but effective form of login access + * control based on login names and on host (or domain) names, internet + * addresses (or network numbers), or on terminal line names in case of + * non-networked logins. Diagnostics are reported through syslog(3). + * + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + */ + +#include "bsd_locl.h" + +RCSID("$Id: login_access.c,v 1.15 1997/06/01 03:12:28 assar Exp $"); + +#ifdef LOGIN_ACCESS + + /* Delimiters for fields and for lists of users, ttys or hosts. */ + +static char fs[] = ":"; /* field separator */ +static char sep[] = ", \t"; /* list-element separator */ + + /* Constants to be used in assignments only, not in comparisons... */ + +#define YES 1 +#define NO 0 + +static int list_match(char *list, char *item, int (*match_fn)(char *, char *)); +static int user_match(char *tok, char *string); +static int from_match(char *tok, char *string); +static int string_match(char *tok, char *string); + +/* login_access - match username/group and host/tty with access control file */ + +int login_access(char *user, char *from) +{ + FILE *fp; + char line[BUFSIZ]; + char *perm; /* becomes permission field */ + char *users; /* becomes list of login names */ + char *froms; /* becomes list of terminals or hosts */ + int match = NO; + int end; + int lineno = 0; /* for diagnostics */ + char *foo; + + /* + * Process the table one line at a time and stop at the first match. + * Blank lines and lines that begin with a '#' character are ignored. + * Non-comment lines are broken at the ':' character. All fields are + * mandatory. The first field should be a "+" or "-" character. A + * non-existing table means no access control. + */ + + if ((fp = fopen(_PATH_LOGACCESS, "r")) != 0) { + while (!match && fgets(line, sizeof(line), fp)) { + lineno++; + if (line[end = strlen(line) - 1] != '\n') { + syslog(LOG_ERR, "%s: line %d: missing newline or line too long", + _PATH_LOGACCESS, lineno); + continue; + } + if (line[0] == '#') + continue; /* comment line */ + while (end > 0 && isspace(line[end - 1])) + end--; + line[end] = 0; /* strip trailing whitespace */ + if (line[0] == 0) /* skip blank lines */ + continue; + foo = NULL; + if (!(perm = strtok_r(line, fs, &foo)) + || !(users = strtok_r(NULL, fs, &foo)) + || !(froms = strtok_r(NULL, fs, &foo)) + || strtok_r(NULL, fs, &foo)) { + syslog(LOG_ERR, "%s: line %d: bad field count", + _PATH_LOGACCESS, + lineno); + continue; + } + if (perm[0] != '+' && perm[0] != '-') { + syslog(LOG_ERR, "%s: line %d: bad first field", + _PATH_LOGACCESS, + lineno); + continue; + } + match = (list_match(froms, from, from_match) + && list_match(users, user, user_match)); + } + fclose(fp); + } else if (errno != ENOENT) { + syslog(LOG_ERR, "cannot open %s: %m", _PATH_LOGACCESS); + } + return (match == 0 || (line[0] == '+')); +} + +/* list_match - match an item against a list of tokens with exceptions */ + +static int +list_match(char *list, char *item, int (*match_fn)(char *, char *)) +{ + char *tok; + int match = NO; + char *foo = NULL; + + /* + * Process tokens one at a time. We have exhausted all possible matches + * when we reach an "EXCEPT" token or the end of the list. If we do find + * a match, look for an "EXCEPT" list and recurse to determine whether + * the match is affected by any exceptions. + */ + + for (tok = strtok_r(list, sep, &foo); + tok != NULL; + tok = strtok_r(NULL, sep, &foo)) { + if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ + break; + if ((match = (*match_fn) (tok, item)) != 0) /* YES */ + break; + } + /* Process exceptions to matches. */ + + if (match != NO) { + while ((tok = strtok_r(NULL, sep, &foo)) && strcasecmp(tok, "EXCEPT")) + /* VOID */ ; + if (tok == 0 || list_match(NULL, item, match_fn) == NO) + return (match); + } + return (NO); +} + +/* netgroup_match - match group against machine or user */ + +static int netgroup_match(char *group, char *machine, char *user) +{ +#ifdef HAVE_YP_GET_DEFAULT_DOMAIN + static char *mydomain = 0; + + if (mydomain == 0) + yp_get_default_domain(&mydomain); + return (innetgr(group, machine, user, mydomain)); +#else + syslog(LOG_ERR, "NIS netgroup support not configured"); + return 0; +#endif +} + +/* user_match - match a username against one token */ + +static int user_match(char *tok, char *string) +{ + struct group *group; + int i; + + /* + * If a token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the username, or if + * the token is a group that contains the username. + */ + + if (tok[0] == '@') { /* netgroup */ + return (netgroup_match(tok + 1, (char *) 0, string)); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if ((group = getgrnam(tok)) != 0) { /* try group membership */ + for (i = 0; group->gr_mem[i]; i++) + if (strcasecmp(string, group->gr_mem[i]) == 0) + return (YES); + } + return (NO); +} + +/* from_match - match a host or tty against a list of tokens */ + +static int from_match(char *tok, char *string) +{ + int tok_len; + int str_len; + + /* + * If a token has the magic value "ALL" the match always succeeds. Return + * YES if the token fully matches the string. If the token is a domain + * name, return YES if it matches the last fields of the string. If the + * token has the magic value "LOCAL", return YES if the string does not + * contain a "." character. If the token is a network number, return YES + * if it matches the head of the string. + */ + + if (tok[0] == '@') { /* netgroup */ + return (netgroup_match(tok + 1, string, (char *) 0)); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if (tok[0] == '.') { /* domain: match last fields */ + if ((str_len = strlen(string)) > (tok_len = strlen(tok)) + && strcasecmp(tok, string + str_len - tok_len) == 0) + return (YES); + } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ + if (strchr(string, '.') == 0) + return (YES); + } else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */ + && strncmp(tok, string, tok_len) == 0) { + return (YES); + } + return (NO); +} + +/* string_match - match a string against one token */ + +static int string_match(char *tok, char *string) +{ + + /* + * If the token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the string. + */ + + if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */ + return (YES); + } else if (strcasecmp(tok, string) == 0) { /* try exact match */ + return (YES); + } + return (NO); +} +#endif /* LOGIN_ACCES */ diff --git a/crypto/kerberosIV/appl/bsd/login_fbtab.c b/crypto/kerberosIV/appl/bsd/login_fbtab.c new file mode 100644 index 0000000..f7f53aa --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/login_fbtab.c @@ -0,0 +1,144 @@ +/************************************************************************ +* Copyright 1995 by Wietse Venema. All rights reserved. +* +* This material was originally written and compiled by Wietse Venema at +* Eindhoven University of Technology, The Netherlands, in 1990, 1991, +* 1992, 1993, 1994 and 1995. +* +* Redistribution and use in source and binary forms are permitted +* provided that this entire copyright notice is duplicated in all such +* copies. +* +* This software is provided "as is" and without any expressed or implied +* warranties, including, without limitation, the implied warranties of +* merchantibility and fitness for any particular purpose. +************************************************************************/ +/* + SYNOPSIS + void login_fbtab(tty, uid, gid) + char *tty; + uid_t uid; + gid_t gid; + + DESCRIPTION + This module implements device security as described in the + SunOS 4.1.x fbtab(5) and SunOS 5.x logindevperm(4) manual + pages. The program first looks for /etc/fbtab. If that file + cannot be opened it attempts to process /etc/logindevperm. + We expect entries with the folowing format: + + Comments start with a # and extend to the end of the line. + + Blank lines or lines with only a comment are ignored. + + All other lines consist of three fields delimited by + whitespace: a login device (/dev/console), an octal + permission number (0600), and a ":"-delimited list of + devices (/dev/kbd:/dev/mouse). All device names are + absolute paths. A path that ends in "/*" refers to all + directory entries except "." and "..". + + If the tty argument (relative path) matches a login device + name (absolute path), the permissions of the devices in the + ":"-delimited list are set as specified in the second + field, and their ownership is changed to that of the uid + and gid arguments. + + DIAGNOSTICS + Problems are reported via the syslog daemon with severity + LOG_ERR. + + BUGS + + AUTHOR + Wietse Venema (wietse@wzv.win.tue.nl) + Eindhoven University of Technology + The Netherlands + */ + +#include "bsd_locl.h" + +RCSID("$Id: login_fbtab.c,v 1.10 1997/06/01 03:12:54 assar Exp $"); + +void login_protect (char *, char *, int, uid_t, gid_t); +void login_fbtab (char *tty, uid_t uid, gid_t gid); + +#define WSPACE " \t\n" + +/* login_fbtab - apply protections specified in /etc/fbtab or logindevperm */ + +void +login_fbtab(char *tty, uid_t uid, gid_t gid) +{ + FILE *fp; + char buf[BUFSIZ]; + char *devname; + char *cp; + int prot; + char *table; + char *foo; + + if ((fp = fopen(table = _PATH_FBTAB, "r")) == 0 + && (fp = fopen(table = _PATH_LOGINDEVPERM, "r")) == 0) + return; + + while (fgets(buf, sizeof(buf), fp)) { + if ((cp = strchr(buf, '#')) != 0) + *cp = 0; /* strip comment */ + foo = NULL; + if ((cp = devname = strtok_r(buf, WSPACE, &foo)) == 0) + continue; /* empty or comment */ + if (strncmp(devname, "/dev/", 5) != 0 + || (cp = strtok_r(NULL, WSPACE, &foo)) == 0 + || *cp != '0' + || sscanf(cp, "%o", &prot) == 0 + || prot == 0 + || (prot & 0777) != prot + || (cp = strtok_r(NULL, WSPACE, &foo)) == 0) { + syslog(LOG_ERR, "%s: bad entry: %s", table, cp ? cp : "(null)"); + continue; + } + if (strcmp(devname + 5, tty) == 0) { + foo = NULL; + for (cp = strtok_r(cp, ":", &foo); + cp; + cp = strtok_r(NULL, ":", &foo)) { + login_protect(table, cp, prot, uid, gid); + } + } + } + fclose(fp); +} + +/* login_protect - protect one device entry */ + +void +login_protect(char *table, char *path, int mask, uid_t uid, gid_t gid) +{ + char buf[BUFSIZ]; + int pathlen = strlen(path); + struct dirent *ent; + DIR *dir; + + if (strcmp("/*", path + pathlen - 2) != 0) { + if (chmod(path, mask) && errno != ENOENT) + syslog(LOG_ERR, "%s: chmod(%s): %m", table, path); + if (chown(path, uid, gid) && errno != ENOENT) + syslog(LOG_ERR, "%s: chown(%s): %m", table, path); + } else { + strcpy(buf, path); + buf[pathlen - 1] = 0; + if ((dir = opendir(buf)) == 0) { + syslog(LOG_ERR, "%s: opendir(%s): %m", table, path); + } else { + while ((ent = readdir(dir)) != 0) { + if (strcmp(ent->d_name, ".") != 0 + && strcmp(ent->d_name, "..") != 0) { + strcpy(buf + pathlen - 1, ent->d_name); + login_protect(table, buf, mask, uid, gid); + } + } + closedir(dir); + } + } +} diff --git a/crypto/kerberosIV/appl/bsd/pathnames.h b/crypto/kerberosIV/appl/bsd/pathnames.h new file mode 100644 index 0000000..3c10bff --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/pathnames.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * from: @(#)pathnames.h 5.2 (Berkeley) 4/9/90 + * $Id: pathnames.h,v 1.23 1996/11/17 06:36:42 joda Exp $ + */ + +/******* First fix default path, we stick to _PATH_DEFPATH everywhere */ + +#if !defined(_PATH_DEFPATH) && defined(_PATH_USERPATH) +#define _PATH_DEFPATH _PATH_USERPATH +#endif + +#if defined(_PATH_DEFPATH) && !defined(_DEF_PATH) +#define _DEF_PATH _PATH_DEFPATH +#endif + +#if !defined(_PATH_DEFPATH) && defined(_DEF_PATH) +#define _PATH_DEFPATH _DEF_PATH +#endif + +#ifndef _PATH_DEFPATH +#define _PATH_DEFPATH "/usr/ucb:/usr/bin:/bin" +#define _DEF_PATH _PATH_DEFPATH +#endif /* !_PATH_DEFPATH */ + +#ifndef _PATH_DEFSUPATH +#define _PATH_DEFSUPATH "/usr/sbin:" _DEF_PATH +#endif /* _PATH_DEFSUPATH */ + +/******* Default PATH fixed! */ + +#undef _PATH_RLOGIN /* Redifine rlogin */ +#define _PATH_RLOGIN BINDIR "/rlogin" + +#undef _PATH_RSH /* Redifine rsh */ +#define _PATH_RSH BINDIR "/rsh" + +#undef _PATH_LOGIN +#define _PATH_LOGIN BINDIR "/login" + +/******* The rest is fallback defaults */ + +#ifndef _PATH_DEV +#define _PATH_DEV "/dev/" +#endif + +#ifndef _PATH_CP +#define _PATH_CP "/bin/cp" +#endif /* _PATH_CP */ + +#ifndef _PATH_SHELLS +#define _PATH_SHELLS "/etc/shells" +#endif /* _PATH_SHELLS */ + +#ifndef _PATH_BSHELL +#define _PATH_BSHELL "/bin/sh" +#endif /* _PATH_BSHELL */ + +#ifndef _PATH_CSHELL +#define _PATH_CSHELL "/bin/csh" +#endif /* _PATH_CSHELL */ + +#ifndef _PATH_NOLOGIN +#define _PATH_NOLOGIN "/etc/nologin" +#endif /* _PATH_NOLOGIN */ + +#ifndef _PATH_TTY +#define _PATH_TTY "/dev/tty" +#endif /* _PATH_TTY */ + +#ifndef _PATH_HUSHLOGIN +#define _PATH_HUSHLOGIN ".hushlogin" +#endif /* _PATH_HUSHLOGIN */ + +#ifndef _PATH_NOMAILCHECK +#define _PATH_NOMAILCHECK ".nomailcheck" +#endif /* _PATH_NOMAILCHECK */ + +#ifndef _PATH_MOTDFILE +#define _PATH_MOTDFILE "/etc/motd" +#endif /* _PATH_MOTDFILE */ + +#ifndef _PATH_LOGACCESS +#define _PATH_LOGACCESS "/etc/login.access" +#endif /* _PATH_LOGACCESS */ + +#ifndef _PATH_HEQUIV +#define _PATH_HEQUIV "/etc/hosts.equiv" +#endif + +#ifndef _PATH_FBTAB +#define _PATH_FBTAB "/etc/fbtab" +#endif /* _PATH_FBTAB */ + +#ifndef _PATH_LOGINDEVPERM +#define _PATH_LOGINDEVPERM "/etc/logindevperm" +#endif /* _PATH_LOGINDEVPERM */ + +#ifndef _PATH_CHPASS +#define _PATH_CHPASS "/usr/bin/passwd" +#endif /* _PATH_CHPASS */ + +#if defined(__hpux) +#define __FALLBACK_MAILDIR__ "/usr/mail" +#else +#define __FALLBACK_MAILDIR__ "/usr/spool/mail" +#endif + +#ifndef KRB4_MAILDIR +#ifndef _PATH_MAILDIR +#ifdef MAILDIR +#define _PATH_MAILDIR MAILDIR +#else +#define _PATH_MAILDIR __FALLBACK_MAILDIR__ +#endif +#endif /* _PATH_MAILDIR */ +#define KRB4_MAILDIR _PATH_MAILDIR +#endif + +#ifndef _PATH_LASTLOG +#define _PATH_LASTLOG "/var/adm/lastlog" +#endif + +#if defined(UTMP_FILE) && !defined(_PATH_UTMP) +#define _PATH_UTMP UTMP_FILE +#endif + +#ifndef _PATH_UTMP +#define _PATH_UTMP "/etc/utmp" +#endif + +#if defined(WTMP_FILE) && !defined(_PATH_WTMP) +#define _PATH_WTMP WTMP_FILE +#endif + +#ifndef _PATH_WTMP +#define _PATH_WTMP "/usr/adm/wtmp" +#endif + +#ifndef _PATH_ETC_DEFAULT_LOGIN +#define _PATH_ETC_DEFAULT_LOGIN "/etc/default/login" +#endif + +#ifndef _PATH_ETC_ENVIRONMENT +#define _PATH_ETC_ENVIRONMENT "/etc/environment" +#endif + +/* + * NeXT KLUDGE ALERT!!!!!!!!!!!!!!!!!! + * Some sort of bug in the NEXTSTEP cpp. + */ +#ifdef NeXT +#undef _PATH_DEFSUPATH +#define _PATH_DEFSUPATH "/usr/sbin:/usr/ucb:/usr/bin:/bin" +#undef _PATH_RLOGIN +#define _PATH_RLOGIN "/usr/athena/bin/rlogin" +#undef _PATH_RSH +#define _PATH_RSH "/usr/athena/bin/rsh" +#undef _PATH_LOGIN +#define _PATH_LOGIN "/usr/athena/bin/login" +#endif diff --git a/crypto/kerberosIV/appl/bsd/rcmd_util.c b/crypto/kerberosIV/appl/bsd/rcmd_util.c new file mode 100644 index 0000000..4669009 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/rcmd_util.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "bsd_locl.h" + +RCSID("$Id: rcmd_util.c,v 1.15 1997/05/02 14:27:44 assar Exp $"); + +int +get_login_port(int kerberos, int encryption) +{ + char *service="login"; + int port=htons(513); + + if(kerberos && encryption){ + service="eklogin"; + port=htons(2105); + } + + if(kerberos && !encryption){ + service="klogin"; + port=htons(543); + } + return k_getportbyname (service, "tcp", port); +} + +int +get_shell_port(int kerberos, int encryption) +{ + char *service="shell"; + int port=htons(514); + + if(kerberos && encryption){ + service="ekshell"; + port=htons(545); + } + + if(kerberos && !encryption){ + service="kshell"; + port=htons(544); + } + + return k_getportbyname (service, "tcp", port); +} + +/* + * On reasonable systems, `cf[gs]et[io]speed' use values of bit/s + * directly, and the following functions are just identity functions. + * This is however a slower way of doing those + * should-be-but-are-not-always idenity functions. + */ + +static struct { int speed; int bps; } conv[] = { +#ifdef B0 + {B0, 0}, +#endif +#ifdef B50 + {B50, 50}, +#endif +#ifdef B75 + {B75, 75}, +#endif +#ifdef B110 + {B110, 110}, +#endif +#ifdef B134 + {B134, 134}, +#endif +#ifdef B150 + {B150, 150}, +#endif +#ifdef B200 + {B200, 200}, +#endif +#ifdef B300 + {B300, 300}, +#endif +#ifdef B600 + {B600, 600}, +#endif +#ifdef B1200 + {B1200, 1200}, +#endif +#ifdef B1800 + {B1800, 1800}, +#endif +#ifdef B2400 + {B2400, 2400}, +#endif +#ifdef B4800 + {B4800, 4800}, +#endif +#ifdef B9600 + {B9600, 9600}, +#endif +#ifdef B19200 + {B19200, 19200}, +#endif +#ifdef B38400 + {B38400, 38400}, +#endif +#ifdef B57600 + {B57600, 57600}, +#endif +#ifdef B115200 + {B115200, 115200}, +#endif +#ifdef B153600 + {B153600, 153600}, +#endif +#ifdef B230400 + {B230400, 230400}, +#endif +#ifdef B307200 + {B307200, 307200}, +#endif +#ifdef B460800 + {B460800, 460800}, +#endif +}; + +#define N (sizeof(conv)/sizeof(*conv)) + +int +speed_t2int (speed_t s) +{ + int l, r, m; + + l = 0; + r = N - 1; + while(l <= r) { + m = (l + r) / 2; + if (conv[m].speed == s) + return conv[m].bps; + else if(conv[m].speed < s) + l = m + 1; + else + r = m - 1; + } + return -1; +} + +/* + * + */ + +speed_t +int2speed_t (int i) +{ + int l, r, m; + + l = 0; + r = N - 1; + while(l <= r) { + m = (l + r) / 2; + if (conv[m].bps == i) + return conv[m].speed; + else if(conv[m].bps < i) + l = m + 1; + else + r = m - 1; + } + return -1; +} + +/* + * If there are any IP options on `sock', die. + */ + +void +ip_options_and_die (int sock, struct sockaddr_in *fromp) +{ +#if defined(IP_OPTIONS) && defined(HAVE_GETSOCKOPT) + u_char optbuf[BUFSIZ/3], *cp; + char lbuf[BUFSIZ], *lp; + int optsize = sizeof(optbuf), ipproto; + struct protoent *ip; + + if ((ip = getprotobyname("ip")) != NULL) + ipproto = ip->p_proto; + else + ipproto = IPPROTO_IP; + if (getsockopt(sock, ipproto, IP_OPTIONS, + (void *)optbuf, &optsize) == 0 && + optsize != 0) { + lp = lbuf; + for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) + snprintf(lp, sizeof(lbuf) - (lp - lbuf), " %2.2x", *cp); + syslog(LOG_NOTICE, + "Connection received from %s using IP options (dead):%s", + inet_ntoa(fromp->sin_addr), lbuf); + exit(1); + } +#endif +} + +void +warning(const char *fmt, ...) +{ + char *rstar_no_warn = getenv("RSTAR_NO_WARN"); + va_list args; + + va_start(args, fmt); + if (rstar_no_warn == NULL) + rstar_no_warn = ""; + if (strncmp(rstar_no_warn, "yes", 3) != 0) { + /* XXX */ + fprintf(stderr, "%s: warning, using standard ", __progname); + warnx(fmt, args); + } + va_end(args); +} diff --git a/crypto/kerberosIV/appl/bsd/rcp.c b/crypto/kerberosIV/appl/bsd/rcp.c new file mode 100644 index 0000000..6dfb472 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/rcp.c @@ -0,0 +1,1019 @@ +/* + * Copyright (c) 1983, 1990, 1992, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID("$Id: rcp.c,v 1.43 1997/05/13 09:41:26 bg Exp $"); + +/* Globals */ +static char dst_realm_buf[REALM_SZ]; +static char *dest_realm = NULL; +static int use_kerberos = 1; + +static int doencrypt = 0; +#define OPTIONS "dfKk:prtx" + +static int errs, rem; +static struct passwd *pwd; +static u_short port; +static uid_t userid; +static int pflag, iamremote, iamrecursive, targetshouldbedirectory; + +#define CMDNEEDS 64 +static char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ + +void rsource(char *name, struct stat *statp); + +#define SERVICE_NAME "rcmd" + +CREDENTIALS cred; +MSG_DAT msg_data; +struct sockaddr_in foreign, local; +Key_schedule schedule; + +KTEXT_ST ticket; +AUTH_DAT kdata; + +static void +send_auth(char *h, char *r) +{ + int lslen, fslen, status; + long opts; + + lslen = sizeof(struct sockaddr_in); + if (getsockname(rem, (struct sockaddr *)&local, &lslen) < 0) + err(1, "getsockname"); + fslen = sizeof(struct sockaddr_in); + if (getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0) + err(1, "getpeername"); + if ((r == NULL) || (*r == '\0')) + r = krb_realmofhost(h); + opts = KOPT_DO_MUTUAL; + if ((status = krb_sendauth(opts, rem, &ticket, SERVICE_NAME, h, r, + (unsigned long)getpid(), &msg_data, &cred, + schedule, &local, + &foreign, "KCMDV0.1")) != KSUCCESS) + errx(1, "krb_sendauth failure: %s", krb_get_err_text(status)); +} + +static void +answer_auth(void) +{ + int lslen, fslen, status; + long opts; + char inst[INST_SZ], v[9]; + + lslen = sizeof(struct sockaddr_in); + if (getsockname(rem, (struct sockaddr *)&local, &lslen) < 0) + err(1, "getsockname"); + fslen = sizeof(struct sockaddr_in); + if(getpeername(rem, (struct sockaddr *)&foreign, &fslen) < 0) + err(1, "getperrname"); + k_getsockinst(rem, inst, sizeof(inst)); + opts = KOPT_DO_MUTUAL; + if ((status = krb_recvauth(opts, rem, &ticket, SERVICE_NAME, inst, + &foreign, &local, + &kdata, "", schedule, v)) != KSUCCESS) + errx(1, "krb_recvauth failure: %s", krb_get_err_text(status)); +} + +static int +des_read(int fd, char *buf, int len) +{ + if (doencrypt) + return(des_enc_read(fd, buf, len, schedule, + (iamremote? &kdata.session : &cred.session))); + else + return(read(fd, buf, len)); +} + +static int +des_write(int fd, char *buf, int len) +{ + if (doencrypt) + return(des_enc_write(fd, buf, len, schedule, + (iamremote? &kdata.session : &cred.session))); + else + return(write(fd, buf, len)); +} + +static void run_err(const char *fmt, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + + +static void +run_err(const char *fmt, ...) +{ + char errbuf[1024]; + + va_list args; + va_start(args, fmt); + ++errs; +#define RCPERR "\001rcp: " + strcpy (errbuf, RCPERR); + vsnprintf (errbuf + strlen(RCPERR), sizeof(errbuf) - strlen(RCPERR), + fmt, args); + strcat (errbuf, "\n"); + des_write (rem, errbuf, strlen(errbuf)); + if (!iamremote) + vwarnx(fmt, args); + va_end(args); +} + +static void +verifydir(char *cp) +{ + struct stat stb; + + if (!stat(cp, &stb)) { + if (S_ISDIR(stb.st_mode)) + return; + errno = ENOTDIR; + } + run_err("%s: %s", cp, strerror(errno)); + exit(1); +} + +#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) + +static BUF * +allocbuf(BUF *bp, int fd, int blksize) +{ + struct stat stb; + size_t size; + + if (fstat(fd, &stb) < 0) { + run_err("fstat: %s", strerror(errno)); + return (0); + } +#ifdef HAVE_ST_BLKSIZE + size = ROUNDUP(stb.st_blksize, blksize); +#else + size = blksize; +#endif + if (size == 0) + size = blksize; + if (bp->cnt >= size) + return (bp); + if (bp->buf == NULL) + bp->buf = malloc(size); + else + bp->buf = realloc(bp->buf, size); + if (bp->buf == NULL) { + bp->cnt = 0; + run_err("%s", strerror(errno)); + return (0); + } + bp->cnt = size; + return (bp); +} + +static void +usage(void) +{ + fprintf(stderr, "%s\n\t%s\n", + "usage: rcp [-Kpx] [-k realm] f1 f2", + "or: rcp [-Kprx] [-k realm] f1 ... fn directory"); + exit(1); +} + +static void +oldw(const char *s) +{ + char *rstar_no_warn = getenv("RSTAR_NO_WARN"); + if (rstar_no_warn == 0) + rstar_no_warn = ""; + if (strncmp(rstar_no_warn, "yes", 3) != 0) + warnx("%s, using standard rcp", s); +} + +static RETSIGTYPE +lostconn(int signo) +{ + if (!iamremote) + warnx("lost connection"); + exit(1); +} + +static int +response(void) +{ + char ch, *cp, resp, rbuf[BUFSIZ]; + + if (des_read(rem, &resp, sizeof(resp)) != sizeof(resp)) + lostconn(0); + + cp = rbuf; + switch(resp) { + case 0: /* ok */ + return (0); + default: + *cp++ = resp; + /* FALLTHROUGH */ + case 1: /* error, followed by error msg */ + case 2: /* fatal error, "" */ + do { + if (des_read(rem, &ch, sizeof(ch)) != sizeof(ch)) + lostconn(0); + *cp++ = ch; + } while (cp < &rbuf[BUFSIZ] && ch != '\n'); + + if (!iamremote) + write(STDERR_FILENO, rbuf, cp - rbuf); + ++errs; + if (resp == 1) + return (-1); + exit(1); + } + /* NOTREACHED */ +} + +static void +source(int argc, char **argv) +{ + struct stat stb; + static BUF buffer; + BUF *bp; + off_t i; + int amt, fd, haderr, indx, result; + char *last, *name, buf[BUFSIZ]; + + for (indx = 0; indx < argc; ++indx) { + name = argv[indx]; + if ((fd = open(name, O_RDONLY, 0)) < 0) + goto syserr; + if (fstat(fd, &stb)) { +syserr: run_err("%s: %s", name, strerror(errno)); + goto next; + } + switch (stb.st_mode & S_IFMT) { + case S_IFREG: + break; + case S_IFDIR: + if (iamrecursive) { + rsource(name, &stb); + goto next; + } + /* FALLTHROUGH */ + default: + run_err("%s: not a regular file", name); + goto next; + } + if ((last = strrchr(name, '/')) == NULL) + last = name; + else + ++last; + if (pflag) { + /* + * Make it compatible with possible future + * versions expecting microseconds. + */ + snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n", + (long)stb.st_mtime, (long)stb.st_atime); + des_write(rem, buf, strlen(buf)); + if (response() < 0) + goto next; + } + snprintf(buf, sizeof(buf), "C%04o %ld %s\n", + (int)stb.st_mode & MODEMASK, (long) stb.st_size, last); + des_write(rem, buf, strlen(buf)); + if (response() < 0) + goto next; + if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) { +next: close(fd); + continue; + } + + /* Keep writing after an error so that we stay sync'd up. */ + for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { + amt = bp->cnt; + if (i + amt > stb.st_size) + amt = stb.st_size - i; + if (!haderr) { + result = read(fd, bp->buf, amt); + if (result != amt) + haderr = result >= 0 ? EIO : errno; + } + if (haderr) + des_write(rem, bp->buf, amt); + else { + result = des_write(rem, bp->buf, amt); + if (result != amt) + haderr = result >= 0 ? EIO : errno; + } + } + if (close(fd) && !haderr) + haderr = errno; + if (!haderr) + des_write(rem, "", 1); + else + run_err("%s: %s", name, strerror(haderr)); + response(); + } +} + +void +rsource(char *name, struct stat *statp) +{ + DIR *dirp; + struct dirent *dp; + char *last, *vect[1], path[MaxPathLen]; + + if (!(dirp = opendir(name))) { + run_err("%s: %s", name, strerror(errno)); + return; + } + last = strrchr(name, '/'); + if (last == 0) + last = name; + else + last++; + if (pflag) { + snprintf(path, sizeof(path), "T%ld 0 %ld 0\n", + (long)statp->st_mtime, (long)statp->st_atime); + des_write(rem, path, strlen(path)); + if (response() < 0) { + closedir(dirp); + return; + } + } + snprintf(path, sizeof(path), + "D%04o %d %s\n", (int)statp->st_mode & MODEMASK, 0, last); + des_write(rem, path, strlen(path)); + if (response() < 0) { + closedir(dirp); + return; + } + while ((dp = readdir(dirp))) { + if (dp->d_ino == 0) + continue; + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + if (strlen(name) + 1 + strlen(dp->d_name) >= MaxPathLen - 1) { + run_err("%s/%s: name too long", name, dp->d_name); + continue; + } + if (snprintf(path, sizeof(path), + "%s/%s", name, dp->d_name) >= sizeof(path)) { + run_err("%s/%s: name too long", name, dp->d_name); + continue; + } + vect[0] = path; + source(1, vect); + } + closedir(dirp); + des_write(rem, "E\n", 2); + response(); +} + +static int +kerberos(char **host, char *bp, char *locuser, char *user) +{ + int sock = -1, err; +again: + if (use_kerberos) { + rem = KSUCCESS; + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(*host); + +#if 0 + rem = krcmd(host, port, user, bp, 0, dest_realm); +#else + err = kcmd( + &sock, + host, + port, + NULL, /* locuser not used */ + user, + bp, + 0, + &ticket, + SERVICE_NAME, + dest_realm, + (CREDENTIALS *) NULL, /* credentials not used */ + 0, /* key schedule not used */ + (MSG_DAT *) NULL, /* MSG_DAT not used */ + (struct sockaddr_in *) NULL, /* local addr not used */ + (struct sockaddr_in *) NULL, /* foreign addr not used */ + 0L); /* authopts */ + if (err > KSUCCESS && err < MAX_KRB_ERRORS) { + warnx("kcmd: %s", krb_get_err_text(err)); + rem = -1; + } else if (err < 0) + rem = -1; + else + rem = sock; +#endif + if (rem < 0) { + use_kerberos = 0; + port = get_shell_port(use_kerberos, 0); + if (errno == ECONNREFUSED) + oldw("remote host doesn't support Kerberos"); + else if (errno == ENOENT) + oldw("can't provide Kerberos authentication data"); + goto again; + } + } else { + if (doencrypt) + errx(1, + "the -x option requires Kerberos authentication"); + if (geteuid() != 0) { + errx(1, "not installed setuid root, " + "only root may use non kerberized rcp"); + } + rem = rcmd(host, port, locuser, user, bp, 0); + } + return (rem); +} + +static void +toremote(char *targ, int argc, char **argv) +{ + int i, len; +#ifdef IP_TOS + int tos; +#endif + char *bp, *host, *src, *suser, *thost, *tuser; + + *targ++ = 0; + if (*targ == 0) + targ = "."; + + if ((thost = strchr(argv[argc - 1], '@'))) { + /* user@host */ + *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], '@'); + len = strlen(_PATH_RSH) + strlen(argv[i]) + + strlen(src) + (tuser ? strlen(tuser) : 0) + + strlen(thost) + strlen(targ) + CMDNEEDS + 20; + if (!(bp = malloc(len))) + err(1, " "); + if (host) { + *host++ = 0; + suser = argv[i]; + if (*suser == '\0') + suser = pwd->pw_name; + else if (!okname(suser)) + continue; + snprintf(bp, len, + "%s %s -l %s -n %s %s '%s%s%s:%s'", + _PATH_RSH, host, suser, cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + } else + snprintf(bp, len, + "exec %s %s -n %s %s '%s%s%s:%s'", + _PATH_RSH, argv[i], cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + susystem(bp, userid); + free(bp); + } else { /* local to remote */ + if (rem == -1) { + len = strlen(targ) + CMDNEEDS + 20; + if (!(bp = malloc(len))) + err(1, " "); + snprintf(bp, len, "%s -t %s", cmd, targ); + host = thost; + if (use_kerberos) + rem = kerberos(&host, bp, +#ifdef __CYGWIN32__ + tuser, +#else + pwd->pw_name, +#endif + tuser ? tuser : pwd->pw_name); + else + rem = rcmd(&host, port, +#ifdef __CYGWIN32__ + tuser, +#else + pwd->pw_name, +#endif + tuser ? tuser : pwd->pw_name, + bp, 0); + if (rem < 0) + exit(1); +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + tos = IPTOS_THROUGHPUT; + if (setsockopt(rem, IPPROTO_IP, IP_TOS, + (void *)&tos, sizeof(int)) < 0) + warn("TOS (ignored)"); +#endif /* IP_TOS */ + if (doencrypt) + send_auth(host, dest_realm); + if (response() < 0) + exit(1); + free(bp); + setuid(userid); + } + source(1, argv+i); + } + } +} + +static void +sink(int argc, char **argv) +{ + static BUF buffer; + struct stat stb; + struct timeval tv[2]; + enum { YES, NO, DISPLAYED } wrerr; + BUF *bp; + off_t i, j; + int amt, count, exists, first, mask, mode, ofd, omode; + int setimes, size, targisdir, wrerrno=0; + char ch, *cp, *np, *targ, *why, *vect[1], buf[BUFSIZ]; + +#define atime tv[0] +#define mtime tv[1] +#define SCREWUP(str) { why = str; goto screwup; } + + setimes = targisdir = 0; + mask = umask(0); + if (!pflag) + umask(mask); + if (argc != 1) { + run_err("ambiguous target"); + exit(1); + } + targ = *argv; + if (targetshouldbedirectory) + verifydir(targ); + des_write(rem, "", 1); + if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) + targisdir = 1; + for (first = 1;; first = 0) { + cp = buf; + if (des_read(rem, cp, 1) <= 0) + return; + if (*cp++ == '\n') + SCREWUP("unexpected <newline>"); + do { + if (des_read(rem, &ch, sizeof(ch)) != sizeof(ch)) + SCREWUP("lost connection"); + *cp++ = ch; + } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); + *cp = 0; + + if (buf[0] == '\01' || buf[0] == '\02') { + if (iamremote == 0) + write(STDERR_FILENO, + buf + 1, strlen(buf + 1)); + if (buf[0] == '\02') + exit(1); + ++errs; + continue; + } + if (buf[0] == 'E') { + des_write(rem, "", 1); + return; + } + + if (ch == '\n') + *--cp = 0; + +#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); + cp = buf; + 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"); + des_write(rem, "", 1); + 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) { + run_err("%s", cp); + exit(1); + } + SCREWUP("expected control record"); + } + mode = 0; + for (++cp; cp < buf + 5; cp++) { + if (*cp < '0' || *cp > '7') + SCREWUP("bad mode"); + mode = (mode << 3) | (*cp - '0'); + } + if (*cp++ != ' ') + SCREWUP("mode not delimited"); + + for (size = 0; isdigit(*cp);) + size = size * 10 + (*cp++ - '0'); + if (*cp++ != ' ') + SCREWUP("size not delimited"); + if (targisdir) { + static char *namebuf; + static int cursize; + size_t need; + + need = strlen(targ) + strlen(cp) + 250; + if (need > cursize) { + if (!(namebuf = malloc(need))) + run_err("%s", strerror(errno)); + } + snprintf(namebuf, need, "%s%s%s", targ, + *targ ? "/" : "", cp); + np = namebuf; + } else + np = targ; + exists = stat(np, &stb) == 0; + if (buf[0] == 'D') { + int mod_flag = pflag; + if (exists) { + if (!S_ISDIR(stb.st_mode)) { + errno = ENOTDIR; + goto bad; + } + if (pflag) + chmod(np, mode); + } else { + /* Handle copying from a read-only directory */ + mod_flag = 1; + if (mkdir(np, mode | S_IRWXU) < 0) + goto bad; + } + vect[0] = np; + sink(1, vect); + if (setimes) { + struct utimbuf times; + times.actime = atime.tv_sec; + times.modtime = mtime.tv_sec; + setimes = 0; + if (utime(np, ×) < 0) + run_err("%s: set times: %s", + np, strerror(errno)); + } + if (mod_flag) + chmod(np, mode); + continue; + } + omode = mode; + mode |= S_IWRITE; + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { +bad: run_err("%s: %s", np, strerror(errno)); + continue; + } + des_write(rem, "", 1); + if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) { + close(ofd); + continue; + } + cp = bp->buf; + wrerr = NO; + for (count = i = 0; i < size; i += BUFSIZ) { + amt = BUFSIZ; + if (i + amt > size) + amt = size - i; + count += amt; + do { + j = des_read(rem, cp, amt); + if (j <= 0) { + run_err("%s", j ? strerror(errno) : + "dropped connection"); + exit(1); + } + amt -= j; + cp += j; + } while (amt > 0); + if (count == bp->cnt) { + /* Keep reading so we stay sync'd up. */ + if (wrerr == NO) { + j = write(ofd, bp->buf, count); + if (j != count) { + wrerr = YES; + wrerrno = j >= 0 ? EIO : errno; + } + } + count = 0; + cp = bp->buf; + } + } + if (count != 0 && wrerr == NO && + (j = write(ofd, bp->buf, count)) != count) { + wrerr = YES; + wrerrno = j >= 0 ? EIO : errno; + } + if (ftruncate(ofd, size)) { + run_err("%s: truncate: %s", np, strerror(errno)); + wrerr = DISPLAYED; + } + if (pflag) { + if (exists || omode != mode) +#ifdef HAVE_FCHMOD + if (fchmod(ofd, omode)) +#else + if (chmod(np, omode)) +#endif + run_err("%s: set mode: %s", + np, strerror(errno)); + } else { + if (!exists && omode != mode) +#ifdef HAVE_FCHMOD + if (fchmod(ofd, omode & ~mask)) +#else + if (chmod(np, omode & ~mask)) +#endif + run_err("%s: set mode: %s", + np, strerror(errno)); + } + close(ofd); + response(); + if (setimes && wrerr == NO) { + struct utimbuf times; + times.actime = atime.tv_sec; + times.modtime = mtime.tv_sec; + setimes = 0; + if (utime(np, ×) < 0) { + run_err("%s: set times: %s", + np, strerror(errno)); + wrerr = DISPLAYED; + } + } + switch(wrerr) { + case YES: + run_err("%s: %s", np, strerror(wrerrno)); + break; + case NO: + des_write(rem, "", 1); + break; + case DISPLAYED: + break; + } + } +screwup: + run_err("protocol error: %s", why); + exit(1); +} + +static void +tolocal(int argc, char **argv) +{ + int i, len; +#ifdef IP_TOS + int tos; +#endif + char *bp, *host, *src, *suser; + + for (i = 0; i < argc - 1; i++) { + if (!(src = colon(argv[i]))) { /* Local to local. */ + len = strlen(_PATH_CP) + strlen(argv[i]) + + strlen(argv[argc - 1]) + 20; + if (!(bp = malloc(len))) + err(1, " "); + snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, + iamrecursive ? " -r" : "", pflag ? " -p" : "", + argv[i], argv[argc - 1]); + if (susystem(bp, userid)) + ++errs; + free(bp); + continue; + } + *src++ = 0; + if (*src == 0) + src = "."; + if ((host = strchr(argv[i], '@')) == NULL) { +#ifdef __CYGWIN32__ + errx (1, "Sorry, you need to specify the username"); +#else + host = argv[i]; + suser = pwd->pw_name; +#endif + } else { + *host++ = 0; + suser = argv[i]; + if (*suser == '\0') +#ifdef __CYGWIN32__ + errx (1, "Sorry, you need to specify the username"); +#else + suser = pwd->pw_name; +#endif + else if (!okname(suser)) + continue; + } + len = strlen(src) + CMDNEEDS + 20; + if ((bp = malloc(len)) == NULL) + err(1, " "); + snprintf(bp, len, "%s -f %s", cmd, src); + rem = + use_kerberos ? + kerberos(&host, bp, +#ifndef __CYGWIN32__ + pwd->pw_name, +#else + suser, +#endif + suser) : + rcmd(&host, port, +#ifndef __CYGWIN32__ + pwd->pw_name, +#else + suser, +#endif + suser, bp, 0); + free(bp); + if (rem < 0) { + ++errs; + continue; + } + seteuid(userid); +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + tos = IPTOS_THROUGHPUT; + if (setsockopt(rem, IPPROTO_IP, IP_TOS, (void *)&tos, + sizeof(int)) < 0) + warn("TOS (ignored)"); +#endif /* IP_TOS */ + if (doencrypt) + send_auth(host, dest_realm); + sink(1, argv + argc - 1); + seteuid(0); + close(rem); + rem = -1; + } +} + + +int +main(int argc, char **argv) +{ + int ch, fflag, tflag; + char *targ; + + set_progname(argv[0]); + fflag = tflag = 0; + while ((ch = getopt(argc, argv, OPTIONS)) != EOF) + switch(ch) { /* User-visible flags. */ + case 'K': + use_kerberos = 0; + break; + case 'k': + dest_realm = dst_realm_buf; + strncpy(dst_realm_buf, optarg, REALM_SZ); + break; + case 'x': + doencrypt = 1; + LEFT_JUSTIFIED = 1; + break; + case 'p': + pflag = 1; + break; + case 'r': + iamrecursive = 1; + break; + /* Server options. */ + case 'd': + targetshouldbedirectory = 1; + break; + case 'f': /* "from" */ + iamremote = 1; + fflag = 1; + break; + case 't': /* "to" */ + iamremote = 1; + tflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + /* Rcp implements encrypted file transfer without using the + * kshell service, pass 0 for no encryption */ + port = get_shell_port(use_kerberos, 0); + +#ifndef __CYGWIN32__ + if ((pwd = k_getpwuid(userid = getuid())) == NULL) + errx(1, "unknown user %d", (int)userid); +#endif + + rem = STDIN_FILENO; /* XXX */ + + if (fflag) { /* Follow "protocol", send data. */ + if (doencrypt) + answer_auth(); + response(); + setuid(userid); + if (k_hasafs()) { + /* Sometimes we will need cell specific tokens + * to be able to read and write files, thus, + * the token stuff done in rshd might not + * suffice. + */ + char cell[64]; + if (k_afs_cell_of_file(pwd->pw_dir, + cell, sizeof(cell)) == 0) + k_afsklog(cell, 0); + k_afsklog(0, 0); + } + source(argc, argv); + exit(errs); + } + + if (tflag) { /* Receive data. */ + if (doencrypt) + answer_auth(); + setuid(userid); + if (k_hasafs()) { + char cell[64]; + if (k_afs_cell_of_file(pwd->pw_dir, + cell, sizeof(cell)) == 0) + k_afsklog(cell, 0); + k_afsklog(0, 0); + } + sink(argc, argv); + exit(errs); + } + + if (argc < 2) + usage(); + if (argc > 2) + targetshouldbedirectory = 1; + + rem = -1; + /* Command to be executed on remote system using "rsh". */ + snprintf(cmd, sizeof(cmd), + "rcp%s%s%s%s", iamrecursive ? " -r" : "", + (doencrypt && use_kerberos ? " -x" : ""), + pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); + + signal(SIGPIPE, lostconn); + + if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ + toremote(targ, argc, argv); + else { + tolocal(argc, argv); /* Dest is local host. */ + if (targetshouldbedirectory) + verifydir(argv[argc - 1]); + } + exit(errs); +} diff --git a/crypto/kerberosIV/appl/bsd/rcp_util.c b/crypto/kerberosIV/appl/bsd/rcp_util.c new file mode 100644 index 0000000..6f0c5f0 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/rcp_util.c @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID("$Id: rcp_util.c,v 1.7 1996/11/17 20:23:05 assar Exp $"); + +char * +colon(char *cp) +{ + if (*cp == ':') /* Leading colon is part of file name. */ + return (0); + + for (; *cp; ++cp) { + if (*cp == ':') + return (cp); + if (*cp == '/') + return (0); + } + return (0); +} + +int +okname(char *cp0) +{ + int c; + char *cp; + + cp = cp0; + do { + c = *cp; + if (c & 0200) + goto bad; + if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') + goto bad; + } while (*++cp); + return (1); + +bad: warnx("%s: invalid user name", cp0); + return (0); +} + +int +susystem(char *s, int userid) +{ + RETSIGTYPE (*istat)(), (*qstat)(); + int status; + pid_t pid; + + pid = fork(); + switch (pid) { + case -1: + return (127); + + case 0: + setuid(userid); + execl(_PATH_BSHELL, "sh", "-c", s, NULL); + _exit(127); + } + istat = signal(SIGINT, SIG_IGN); + qstat = signal(SIGQUIT, SIG_IGN); + if (waitpid(pid, &status, 0) < 0) + status = -1; + signal(SIGINT, istat); + signal(SIGQUIT, qstat); + return (status); +} diff --git a/crypto/kerberosIV/appl/bsd/rlogin.c b/crypto/kerberosIV/appl/bsd/rlogin.c new file mode 100644 index 0000000..27aa8f0 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/rlogin.c @@ -0,0 +1,707 @@ +/* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * rlogin - remote login + */ +#include "bsd_locl.h" + +RCSID("$Id: rlogin.c,v 1.61 1997/05/25 01:14:47 assar Exp $"); + +CREDENTIALS cred; +Key_schedule schedule; +int use_kerberos = 1, doencrypt; +char dst_realm_buf[REALM_SZ], *dest_realm = NULL; + +#ifndef CCEQ +#define c2uc(x) ((unsigned char) x) +#define CCEQ__(val, c) (c == val ? val != c2uc(_POSIX_VDISABLE) : 0) +#define CCEQ(val, c) CCEQ__(c2uc(val), c2uc(c)) +#endif + +int eight, rem; +struct termios deftty; + +int noescape; +char escapechar = '~'; + +struct winsize winsize; + +int parent, rcvcnt; +char rcvbuf[8 * 1024]; + +int child; + +static void +echo(char c) +{ + char *p; + char buf[8]; + + p = buf; + c &= 0177; + *p++ = escapechar; + if (c < ' ') { + *p++ = '^'; + *p++ = c + '@'; + } else if (c == 0177) { + *p++ = '^'; + *p++ = '?'; + } else + *p++ = c; + *p++ = '\r'; + *p++ = '\n'; + write(STDOUT_FILENO, buf, p - buf); +} + +static void +mode(int f) +{ + struct termios tty; + + switch (f) { + case 0: + tcsetattr(0, TCSANOW, &deftty); + break; + case 1: + tcgetattr(0, &deftty); + tty = deftty; + /* This is loosely derived from sys/compat/tty_compat.c. */ + tty.c_lflag &= ~(ECHO|ICANON|ISIG|IEXTEN); + tty.c_iflag &= ~ICRNL; + tty.c_oflag &= ~OPOST; + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 0; + if (eight) { + tty.c_iflag &= IXOFF; + tty.c_cflag &= ~(CSIZE|PARENB); + tty.c_cflag |= CS8; + } + tcsetattr(0, TCSANOW, &tty); + break; + default: + return; + } +} + +static void +done(int status) +{ + int w, wstatus; + + mode(0); + if (child > 0) { + /* make sure catch_child does not snap it up */ + signal(SIGCHLD, SIG_DFL); + if (kill(child, SIGKILL) >= 0) + while ((w = wait(&wstatus)) > 0 && w != child); + } + exit(status); +} + +static +RETSIGTYPE +catch_child(int foo) +{ + int status; + int pid; + + for (;;) { + pid = waitpid(-1, &status, WNOHANG|WUNTRACED); + if (pid == 0) + return; + /* if the child (reader) dies, just quit */ + if (pid < 0 || (pid == child && !WIFSTOPPED(status))) + done(WTERMSIG(status) | WEXITSTATUS(status)); + } + /* NOTREACHED */ +} + +/* + * There is a race in the SunOS5 rlogind. If the slave end has not yet + * been opened by the child when setting tty size the size is reset to + * zero when the child opens it. Therefore we send the window update + * twice. + */ + +static int tty_kludge = 1; + +/* Return the number of OOB bytes processed. */ +static int +oob_real(void) +{ + struct termios tty; + int atmark, n, out, rcvd; + char waste[BUFSIZ], mark; + + out = O_RDWR; + rcvd = 0; + if (recv(rem, &mark, 1, MSG_OOB) < 0) { + return -1; + } + if (mark & TIOCPKT_WINDOW) { + /* Let server know about window size changes */ + kill(parent, SIGUSR1); + } else if (tty_kludge) { + /* Let server know about window size changes */ + kill(parent, SIGUSR1); + tty_kludge = 0; + } + if (!eight && (mark & TIOCPKT_NOSTOP)) { + tcgetattr(0, &tty); + tty.c_iflag &= ~IXON; + tcsetattr(0, TCSANOW, &tty); + } + if (!eight && (mark & TIOCPKT_DOSTOP)) { + tcgetattr(0, &tty); + tty.c_iflag |= (deftty.c_iflag & IXON); + tcsetattr(0, TCSANOW, &tty); + } + if (mark & TIOCPKT_FLUSHWRITE) { +#ifdef TCOFLUSH + tcflush(1, TCOFLUSH); +#else + ioctl(1, TIOCFLUSH, (char *)&out); +#endif + for (;;) { + if (ioctl(rem, SIOCATMARK, &atmark) < 0) { + warn("ioctl"); + break; + } + if (atmark) + break; + n = read(rem, waste, sizeof (waste)); + if (n <= 0) + break; + } + /* + * Don't want any pending data to be output, so clear the recv + * buffer. If we were hanging on a write when interrupted, + * don't want it to restart. If we were reading, restart + * anyway. + */ + rcvcnt = 0; + } + + /* oob does not do FLUSHREAD (alas!) */ + return 1; +} + +/* reader: read from remote: line -> 1 */ +static int +reader(void) +{ + int n, remaining; + char *bufp; + int kludgep = 1; + + bufp = rcvbuf; + for (;;) { + fd_set readfds, exceptfds; + while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { + n = write(STDOUT_FILENO, bufp, remaining); + if (n < 0) { + if (errno != EINTR) + return (-1); + continue; + } + bufp += n; + } + bufp = rcvbuf; + rcvcnt = 0; + + FD_ZERO (&readfds); + FD_SET (rem, &readfds); + FD_ZERO (&exceptfds); + if (kludgep) + FD_SET (rem, &exceptfds); + if (select(rem+1, &readfds, 0, &exceptfds, 0) == -1) { + if (errno == EINTR) + continue; /* Got signal */ + else + errx(1, "select failed mysteriously"); + } + + if (!FD_ISSET(rem, &exceptfds) && !FD_ISSET(rem, &readfds)) { + warnx("select: nothing to read?"); + continue; + } + + if (FD_ISSET(rem, &exceptfds)) { + int foo = oob_real (); + if (foo >= 1) + continue; /* First check if there is more OOB data. */ + else if (foo < 0) + kludgep = 0; + } + + if (!FD_ISSET(rem, &readfds)) + continue; /* Nothing to read. */ + + kludgep = 1; +#ifndef NOENCRYPTION + if (doencrypt) + rcvcnt = des_enc_read(rem, rcvbuf, + sizeof(rcvbuf), + schedule, &cred.session); + else +#endif + rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); + if (rcvcnt == 0) + return (0); + if (rcvcnt < 0) { + if (errno == EINTR) + continue; + warn("read"); + return (-1); + } + } +} + +/* + * Send the window size to the server via the magic escape + */ +static void +sendwindow(void) +{ + char obuf[4 + 4 * sizeof (u_int16_t)]; + unsigned short *p; + + p = (u_int16_t *)(obuf + 4); + obuf[0] = 0377; + obuf[1] = 0377; + obuf[2] = 's'; + obuf[3] = 's'; + *p++ = htons(winsize.ws_row); + *p++ = htons(winsize.ws_col); +#ifdef HAVE_WS_XPIXEL + *p++ = htons(winsize.ws_xpixel); +#else + *p++ = htons(0); +#endif +#ifdef HAVE_WS_YPIXEL + *p++ = htons(winsize.ws_ypixel); +#else + *p++ = htons(0); +#endif + +#ifndef NOENCRYPTION + if(doencrypt) + des_enc_write(rem, obuf, sizeof(obuf), schedule, + &cred.session); + else +#endif + write(rem, obuf, sizeof(obuf)); +} + +static +RETSIGTYPE +sigwinch(int foo) +{ + struct winsize ws; + + if (get_window_size(0, &ws) == 0 && + memcmp(&ws, &winsize, sizeof(ws))) { + winsize = ws; + sendwindow(); + } +} + +static void +stop(int all) +{ + mode(0); + signal(SIGCHLD, SIG_IGN); + kill(all ? 0 : getpid(), SIGTSTP); + signal(SIGCHLD, catch_child); + mode(1); +#ifdef SIGWINCH + kill(SIGWINCH, getpid()); /* check for size changes, if caught */ +#endif +} + +/* + * writer: write to remote: 0 -> line. + * ~. terminate + * ~^Z suspend rlogin process. + * ~<delayed-suspend char> suspend rlogin process, but leave reader alone. + */ +static void +writer(void) +{ + int bol, local, n; + char c; + + bol = 1; /* beginning of line */ + local = 0; + for (;;) { + n = read(STDIN_FILENO, &c, 1); + if (n <= 0) { + if (n < 0 && errno == EINTR) + continue; + break; + } + /* + * If we're at the beginning of the line and recognize a + * command character, then we echo locally. Otherwise, + * characters are echo'd remotely. If the command character + * is doubled, this acts as a force and local echo is + * suppressed. + */ + if (bol) { + bol = 0; + if (!noescape && c == escapechar) { + local = 1; + continue; + } + } else if (local) { + local = 0; + if (c == '.' || CCEQ(deftty.c_cc[VEOF], c)) { + echo(c); + break; + } + if (CCEQ(deftty.c_cc[VSUSP], c)) { + bol = 1; + echo(c); + stop(1); + continue; + } +#ifdef VDSUSP + /* Is VDSUSP called something else on Linux? + * Perhaps VDELAY is a better thing? */ + if (CCEQ(deftty.c_cc[VDSUSP], c)) { + bol = 1; + echo(c); + stop(0); + continue; + } +#endif /* VDSUSP */ + if (c != escapechar) +#ifndef NOENCRYPTION + if (doencrypt) + des_enc_write(rem, &escapechar,1, schedule, &cred.session); + else +#endif + write(rem, &escapechar, 1); + } + + if (doencrypt) { +#ifdef NOENCRYPTION + if (write(rem, &c, 1) == 0) { +#else + if (des_enc_write(rem, &c, 1, schedule, &cred.session) == 0) { +#endif + warnx("line gone"); + break; + } + } else + if (write(rem, &c, 1) == 0) { + warnx("line gone"); + break; + } + bol = CCEQ(deftty.c_cc[VKILL], c) || + CCEQ(deftty.c_cc[VEOF], c) || + CCEQ(deftty.c_cc[VINTR], c) || + CCEQ(deftty.c_cc[VSUSP], c) || + c == '\r' || c == '\n'; + } +} + +static +RETSIGTYPE +lostpeer(int foo) +{ + signal(SIGPIPE, SIG_IGN); + warnx("\aconnection closed.\r"); + done(1); +} + +/* + * This is called in the parent when the reader process gets the + * out-of-band (urgent) request to turn on the window-changing + * protocol. It is signalled from the child(reader). + */ +static +RETSIGTYPE +sigusr1(int foo) +{ + /* + * Now we now daemon supports winsize hack, + */ + sendwindow(); +#ifdef SIGWINCH + signal(SIGWINCH, sigwinch); /* so we start to support it */ +#endif + SIGRETURN(0); +} + +static void +doit(void) +{ + signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + + signal(SIGCHLD, catch_child); + + /* + * Child sends parent this signal for window size hack. + */ + signal(SIGUSR1, sigusr1); + + signal(SIGPIPE, lostpeer); + + mode(1); + parent = getpid(); + child = fork(); + if (child == -1) { + warn("fork"); + done(1); + } + if (child == 0) { + signal(SIGCHLD, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + if (reader() == 0) + errx(1, "connection closed.\r"); + sleep(1); + errx(1, "\aconnection closed.\r"); + } + + writer(); + warnx("closed connection.\r"); + done(0); +} + +static void +usage(void) +{ + fprintf(stderr, + "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", + "8DEKLdx", " [-k realm] "); + exit(1); +} + +static u_int +getescape(char *p) +{ + long val; + int len; + + if ((len = strlen(p)) == 1) /* use any single char, including '\' */ + return ((u_int)*p); + /* otherwise, \nnn */ + if (*p == '\\' && len >= 2 && len <= 4) { + val = strtol(++p, NULL, 8); + for (;;) { + if (!*++p) + return ((u_int)val); + if (*p < '0' || *p > '8') + break; + } + } + warnx("illegal option value -- e"); + usage(); + return 0; +} + +int +main(int argc, char **argv) +{ + struct passwd *pw; + int sv_port, user_port = 0; + int argoff, ch, dflag, Dflag, one, uid; + char *host, *user, term[1024]; + + argoff = dflag = Dflag = 0; + one = 1; + host = user = NULL; + + set_progname(argv[0]); + + /* handle "rlogin host flags" */ + if (argc > 2 && argv[1][0] != '-') { + host = argv[1]; + argoff = 1; + } + +#define OPTIONS "8DEKLde:k:l:xp:" + while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) + switch(ch) { + case '8': + eight = 1; + break; + case 'D': + Dflag = 1; + break; + case 'E': + noescape = 1; + break; + case 'K': + use_kerberos = 0; + break; + case 'd': + dflag = 1; + break; + case 'e': + noescape = 0; + escapechar = getescape(optarg); + break; + case 'k': + dest_realm = dst_realm_buf; + strncpy(dest_realm, optarg, REALM_SZ); + break; + case 'l': + user = optarg; + break; + case 'x': + doencrypt = 1; + break; + case 'p': + user_port = htons(atoi(optarg)); + break; + case '?': + default: + usage(); + } + optind += argoff; + argc -= optind; + argv += optind; + + /* if haven't gotten a host yet, do so */ + if (!host && !(host = *argv++)) + usage(); + + if (*argv) + usage(); + + if (!(pw = k_getpwuid(uid = getuid()))) + errx(1, "unknown user id."); + if (!user) + user = pw->pw_name; + + + if (user_port) + sv_port = user_port; + else + sv_port = get_login_port(use_kerberos, doencrypt); + + { + char *p = getenv("TERM"); + struct termios tty; + int i; + + if (p == NULL) + p = "network"; + + if (tcgetattr(0, &tty) == 0 + && (i = speed_t2int (cfgetospeed(&tty))) > 0) + snprintf (term, sizeof(term), + "%s/%d", + p, i); + else + snprintf (term, sizeof(term), + "%s", + p); + } + + get_window_size(0, &winsize); + + try_connect: + if (use_kerberos) { + struct hostent *hp; + + /* Fully qualify hostname (needed for krb_realmofhost). */ + hp = gethostbyname(host); + if (hp != NULL && !(host = strdup(hp->h_name))) { + errno = ENOMEM; + err(1, NULL); + } + + rem = KSUCCESS; + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(host); + + if (doencrypt) + rem = krcmd_mutual(&host, sv_port, user, term, 0, + dest_realm, &cred, schedule); + else + rem = krcmd(&host, sv_port, user, term, 0, + dest_realm); + if (rem < 0) { + use_kerberos = 0; + if (user_port == 0) + sv_port = get_login_port(use_kerberos, + doencrypt); + if (errno == ECONNREFUSED) + warning("remote host doesn't support Kerberos"); + if (errno == ENOENT) + warning("can't provide Kerberos auth data"); + goto try_connect; + } + } else { + if (doencrypt) + errx(1, "the -x flag requires Kerberos authentication."); + if (geteuid() != 0) + errx(1, "not installed setuid root, " + "only root may use non kerberized rlogin"); + rem = rcmd(&host, sv_port, pw->pw_name, user, term, 0); + } + + if (rem < 0) + exit(1); + +#ifdef HAVE_SETSOCKOPT +#ifdef SO_DEBUG + if (dflag && + setsockopt(rem, SOL_SOCKET, SO_DEBUG, (void *)&one, + sizeof(one)) < 0) + warn("setsockopt"); +#endif +#ifdef TCP_NODELAY + if (Dflag && + setsockopt(rem, IPPROTO_TCP, TCP_NODELAY, (void *)&one, + sizeof(one)) < 0) + warn("setsockopt(TCP_NODELAY)"); +#endif +#ifdef IP_TOS + one = IPTOS_LOWDELAY; + if (setsockopt(rem, IPPROTO_IP, IP_TOS, (void *)&one, sizeof(int)) < 0) + warn("setsockopt(IP_TOS)"); +#endif /* IP_TOS */ +#endif /* HAVE_SETSOCKOPT */ + + setuid(uid); + doit(); + return 0; +} diff --git a/crypto/kerberosIV/appl/bsd/rlogind.c b/crypto/kerberosIV/appl/bsd/rlogind.c new file mode 100644 index 0000000..c5d80774 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/rlogind.c @@ -0,0 +1,934 @@ +/*- + * Copyright (c) 1983, 1988, 1989, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * remote login server: + * \0 + * remuser\0 + * locuser\0 + * terminal_type/speed\0 + * data + */ + +#include "bsd_locl.h" + +RCSID("$Id: rlogind.c,v 1.100 1997/05/25 01:15:20 assar Exp $"); + +extern int __check_rhosts_file; + +char *INSECURE_MESSAGE = +"\r\n*** Connection not encrypted! Communication may be eavesdropped. ***" +"\r\n*** Use telnet or rlogin -x instead! ***\r\n"; + +#ifndef NOENCRYPTION +char *SECURE_MESSAGE = +"This rlogin session is using DES encryption for all transmissions.\r\n"; +#else +#define SECURE_MESSAGE INSECURE_MESSAGE +#endif + +AUTH_DAT *kdata; +KTEXT ticket; +u_char auth_buf[sizeof(AUTH_DAT)]; +u_char tick_buf[sizeof(KTEXT_ST)]; +Key_schedule schedule; +int doencrypt, retval, use_kerberos, vacuous; + +#define ARGSTR "Daip:lnkvxL:" + +char *env[2]; +#define NMAX 30 +char lusername[NMAX+1], rusername[NMAX+1]; +static char term[64] = "TERM="; +#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ +int keepalive = 1; +int check_all = 0; +int no_delay = 0; + +struct passwd *pwd; + +static const char *new_login = _PATH_LOGIN; + +static void doit (int, struct sockaddr_in *); +static int control (int, char *, int); +static void protocol (int, int); +static RETSIGTYPE cleanup (int); +void fatal (int, const char *, int); +static int do_rlogin (struct sockaddr_in *); +static void setup_term (int); +static int do_krb_login (struct sockaddr_in *); +static void usage (void); + +static int +readstream(int p, char *ibuf, int bufsize) +{ +#ifndef HAVE_GETMSG + return read(p, ibuf, bufsize); +#else + static int flowison = -1; /* current state of flow: -1 is unknown */ + static struct strbuf strbufc, strbufd; + static unsigned char ctlbuf[BUFSIZ]; + static int use_read = 1; + + int flags = 0; + int ret; + struct termios tsp; + + struct iocblk ip; + char vstop, vstart; + int ixon; + int newflow; + + if (use_read) + { + ret = read(p, ibuf, bufsize); + if (ret < 0 && errno == EBADMSG) + use_read = 0; + else + return ret; + } + + strbufc.maxlen = BUFSIZ; + strbufc.buf = (char *)ctlbuf; + strbufd.maxlen = bufsize-1; + strbufd.len = 0; + strbufd.buf = ibuf+1; + ibuf[0] = 0; + + ret = getmsg(p, &strbufc, &strbufd, &flags); + if (ret < 0) /* error of some sort -- probably EAGAIN */ + return(-1); + + if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { + /* data message */ + if (strbufd.len > 0) { /* real data */ + return(strbufd.len + 1); /* count header char */ + } else { + /* nothing there */ + errno = EAGAIN; + return(-1); + } + } + + /* + * It's a control message. Return 1, to look at the flag we set + */ + + switch (ctlbuf[0]) { + case M_FLUSH: + if (ibuf[1] & FLUSHW) + ibuf[0] = TIOCPKT_FLUSHWRITE; + return(1); + + case M_IOCTL: + memcpy(&ip, (ibuf+1), sizeof(ip)); + + switch (ip.ioc_cmd) { +#ifdef TCSETS + case TCSETS: + case TCSETSW: + case TCSETSF: + memcpy(&tsp, + (ibuf+1 + sizeof(struct iocblk)), + sizeof(tsp)); + vstop = tsp.c_cc[VSTOP]; + vstart = tsp.c_cc[VSTART]; + ixon = tsp.c_iflag & IXON; + break; +#endif + default: + errno = EAGAIN; + return(-1); + } + + newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; + if (newflow != flowison) { /* it's a change */ + flowison = newflow; + ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; + return(1); + } + } + + /* nothing worth doing anything about */ + errno = EAGAIN; + return(-1); +#endif +} + +#ifdef HAVE_UTMPX_H +static int +logout(const char *line) +{ + struct utmpx utmpx, *utxp; + int ret = 1; + + setutxent (); + memset(&utmpx, 0, sizeof(utmpx)); + utmpx.ut_type = USER_PROCESS; + strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line)); + utxp = getutxline(&utmpx); + if (utxp) { + strcpy(utxp->ut_user, ""); + utxp->ut_type = DEAD_PROCESS; +#ifdef _STRUCT___EXIT_STATUS + utxp->ut_exit.__e_termination = 0; + utxp->ut_exit.__e_exit = 0; +#elif defined(__osf__) /* XXX */ + utxp->ut_exit.ut_termination = 0; + utxp->ut_exit.ut_exit = 0; +#else + utxp->ut_exit.e_termination = 0; + utxp->ut_exit.e_exit = 0; +#endif + gettimeofday(&utxp->ut_tv, NULL); + pututxline(utxp); +#ifdef WTMPX_FILE + updwtmpx(WTMPX_FILE, utxp); +#else + ret = 0; +#endif + } + endutxent(); + return ret; +} +#else +static int +logout(const char *line) +{ + FILE *fp; + struct utmp ut; + int rval; + + if (!(fp = fopen(_PATH_UTMP, "r+"))) + return(0); + rval = 1; + while (fread(&ut, sizeof(struct utmp), 1, fp) == 1) { + if (!ut.ut_name[0] || + strncmp(ut.ut_line, line, sizeof(ut.ut_line))) + continue; + memset(ut.ut_name, 0, sizeof(ut.ut_name)); +#ifdef HAVE_UT_HOST + memset(ut.ut_host, 0, sizeof(ut.ut_host)); +#endif + time(&ut.ut_time); + fseek(fp, (long)-sizeof(struct utmp), SEEK_CUR); + fwrite(&ut, sizeof(struct utmp), 1, fp); + fseek(fp, (long)0, SEEK_CUR); + rval = 0; + } + fclose(fp); + return(rval); +} +#endif + +#ifndef HAVE_LOGWTMP +static void +logwtmp(const char *line, const char *name, const char *host) +{ + struct utmp ut; + struct stat buf; + int fd; + + memset (&ut, 0, sizeof(ut)); + if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) + return; + if (!fstat(fd, &buf)) { + strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + strncpy(ut.ut_name, name, sizeof(ut.ut_name)); +#ifdef HAVE_UT_HOST + strncpy(ut.ut_host, host, sizeof(ut.ut_host)); +#endif +#ifdef HAVE_UT_PID + ut.ut_pid = getpid(); +#endif +#ifdef HAVE_UT_TYPE + if(name[0]) + ut.ut_type = USER_PROCESS; + else + ut.ut_type = DEAD_PROCESS; +#endif + time(&ut.ut_time); + if (write(fd, &ut, sizeof(struct utmp)) != + sizeof(struct utmp)) + ftruncate(fd, buf.st_size); + } + close(fd); +} +#endif + +int +main(int argc, char **argv) +{ + struct sockaddr_in from; + int ch, fromlen, on; + int interactive = 0; + int portnum = 0; + + set_progname(argv[0]); + + openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); + + opterr = 0; + while ((ch = getopt(argc, argv, ARGSTR)) != EOF) + switch (ch) { + case 'D': + no_delay = 1; + break; + case 'a': + break; + case 'i': + interactive = 1; + break; + case 'p': + portnum = htons(atoi(optarg)); + break; + case 'l': + __check_rhosts_file = 0; + break; + case 'n': + keepalive = 0; + break; + case 'k': + use_kerberos = 1; + break; + case 'v': + vacuous = 1; + break; + case 'x': + doencrypt = 1; + break; + case 'L': + new_login = optarg; + break; + case '?': + default: + usage(); + break; + } + argc -= optind; + argv += optind; + + if (use_kerberos && vacuous) { + usage(); + fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); + } + if (interactive) { + if(portnum == 0) + portnum = get_login_port (use_kerberos, doencrypt); + mini_inetd (portnum); + } + + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + syslog(LOG_ERR,"Can't get peer name of remote host: %m"); + fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); + } + on = 1; +#ifdef HAVE_SETSOCKOPT +#ifdef SO_KEEPALIVE + if (keepalive && + setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, + sizeof (on)) < 0) + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); +#endif +#ifdef TCP_NODELAY + if (no_delay && + setsockopt(0, IPPROTO_TCP, TCP_NODELAY, (void *)&on, + sizeof(on)) < 0) + syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); +#endif + +#ifdef IP_TOS + on = IPTOS_LOWDELAY; + if (setsockopt(0, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); +#endif +#endif /* HAVE_SETSOCKOPT */ + doit(0, &from); + return 0; +} + +int child; +int netf; +char line[MaxPathLen]; +int confirmed; + +struct winsize win = { 0, 0, 0, 0 }; + + +static void +doit(int f, struct sockaddr_in *fromp) +{ + int master, pid, on = 1; + int authenticated = 0; + char hostname[2 * MaxHostNameLen + 1]; + char c; + + alarm(60); + read(f, &c, 1); + + if (c != 0) + exit(1); + if (vacuous) + fatal(f, "Remote host requires Kerberos authentication", 0); + + alarm(0); + inaddr2str (fromp->sin_addr, hostname, sizeof(hostname)); + + if (use_kerberos) { + retval = do_krb_login(fromp); + if (retval == 0) + authenticated++; + else if (retval > 0) + fatal(f, krb_get_err_text(retval), 0); + write(f, &c, 1); + confirmed = 1; /* we sent the null! */ + } else { + fromp->sin_port = ntohs((u_short)fromp->sin_port); + if (fromp->sin_family != AF_INET || + fromp->sin_port >= IPPORT_RESERVED || + fromp->sin_port < IPPORT_RESERVED/2) { + syslog(LOG_NOTICE, "Connection from %s on illegal port", + inet_ntoa(fromp->sin_addr)); + fatal(f, "Permission denied", 0); + } + ip_options_and_die (0, fromp); + if (do_rlogin(fromp) == 0) + authenticated++; + } + if (confirmed == 0) { + write(f, "", 1); + confirmed = 1; /* we sent the null! */ + } +#ifndef NOENCRYPTION + if (doencrypt) + des_enc_write(f, SECURE_MESSAGE, + strlen(SECURE_MESSAGE), + schedule, &kdata->session); + else +#endif + write(f, INSECURE_MESSAGE, strlen(INSECURE_MESSAGE)); + netf = f; + + pid = forkpty(&master, line, NULL, NULL); + if (pid < 0) { + if (errno == ENOENT) + fatal(f, "Out of ptys", 0); + else + fatal(f, "Forkpty", 1); + } + if (pid == 0) { + if (f > 2) /* f should always be 0, but... */ + close(f); + setup_term(0); + if (lusername[0] == '-'){ + syslog(LOG_ERR, "tried to pass user \"%s\" to login", + lusername); + fatal(STDERR_FILENO, "invalid user", 0); + } + if (authenticated) { + if (use_kerberos && (pwd->pw_uid == 0)) + syslog(LOG_INFO|LOG_AUTH, + "ROOT Kerberos login from %s on %s\n", + krb_unparse_name_long(kdata->pname, + kdata->pinst, + kdata->prealm), + hostname); + + execl(new_login, "login", "-p", + "-h", hostname, "-f", "--", lusername, 0); + } else + execl(new_login, "login", "-p", + "-h", hostname, "--", lusername, 0); + fatal(STDERR_FILENO, new_login, 1); + /*NOTREACHED*/ + } + /* + * If encrypted, don't turn on NBIO or the des read/write + * routines will croak. + */ + + if (!doencrypt) + ioctl(f, FIONBIO, &on); + ioctl(master, FIONBIO, &on); + ioctl(master, TIOCPKT, &on); + signal(SIGTSTP, SIG_IGN); + signal(SIGCHLD, cleanup); + setsid(); + protocol(f, master); + signal(SIGCHLD, SIG_IGN); + cleanup(0); +} + +const char magic[2] = { 0377, 0377 }; + +/* + * Handle a "control" request (signaled by magic being present) + * in the data stream. For now, we are only willing to handle + * window size changes. + */ +static int +control(int master, char *cp, int n) +{ + struct winsize w; + char *p; + u_int32_t tmp; + + if (n < 4 + 4 * sizeof (u_int16_t) || cp[2] != 's' || cp[3] != 's') + return (0); +#ifdef TIOCSWINSZ + p = cp + 4; + p += krb_get_int(p, &tmp, 2, 0); + w.ws_row = tmp; + p += krb_get_int(p, &tmp, 2, 0); + w.ws_col = tmp; + + p += krb_get_int(p, &tmp, 2, 0); +#ifdef HAVE_WS_XPIXEL + w.ws_xpixel = tmp; +#endif + p += krb_get_int(p, &tmp, 2, 0); +#ifdef HAVE_WS_YPIXEL + w.ws_ypixel = tmp; +#endif + ioctl(master, TIOCSWINSZ, &w); +#endif + return p - cp; +} + +static +void +send_oob(int fd, char c) +{ + static char last_oob = 0xFF; + +#if (SunOS == 5) || defined(__hpux) + /* + * PSoriasis and HP-UX always send TIOCPKT_DOSTOP at startup so we + * can avoid sending OOB data and thus not break on Linux by merging + * TIOCPKT_DOSTOP into the first TIOCPKT_WINDOW. + */ + static int oob_kludge = 2; + if (oob_kludge == 2) + { + oob_kludge--; /* First time send nothing */ + return; + } + else if (oob_kludge == 1) + { + oob_kludge--; /* Second time merge TIOCPKT_WINDOW */ + c |= TIOCPKT_WINDOW; + } +#endif + +#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) + c = pkcontrol(c); + /* Multiple OOB data breaks on Linux, avoid it when possible. */ + if (c != last_oob) + send(fd, &c, 1, MSG_OOB); + last_oob = c; +} + +/* + * rlogin "protocol" machine. + */ +static void +protocol(int f, int master) +{ + char pibuf[1024+1], fibuf[1024], *pbp, *fbp; + int pcc = 0, fcc = 0; + int cc, nfd, n; + char cntl; + unsigned char oob_queue = 0; + + /* + * Must ignore SIGTTOU, otherwise we'll stop + * when we try and set slave pty's window shape + * (our controlling tty is the master pty). + */ + signal(SIGTTOU, SIG_IGN); + + send_oob(f, TIOCPKT_WINDOW); /* indicate new rlogin */ + + if (f > master) + nfd = f + 1; + else + nfd = master + 1; + if (nfd > FD_SETSIZE) { + syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); + fatal(f, "internal error (select mask too small)", 0); + } + for (;;) { + fd_set ibits, obits, ebits, *omask; + + FD_ZERO(&ebits); + FD_ZERO(&ibits); + FD_ZERO(&obits); + omask = (fd_set *)NULL; + if (fcc) { + FD_SET(master, &obits); + omask = &obits; + } else + FD_SET(f, &ibits); + if (pcc >= 0) + if (pcc) { + FD_SET(f, &obits); + omask = &obits; + } else + FD_SET(master, &ibits); + FD_SET(master, &ebits); + if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { + if (errno == EINTR) + continue; + fatal(f, "select", 1); + } + if (n == 0) { + /* shouldn't happen... */ + sleep(5); + continue; + } + if (FD_ISSET(master, &ebits)) { + cc = readstream(master, &cntl, 1); + if (cc == 1 && pkcontrol(cntl)) { +#if 0 /* Kludge around */ + send_oob(f, cntl); +#endif + oob_queue = cntl; + if (cntl & TIOCPKT_FLUSHWRITE) { + pcc = 0; + FD_CLR(master, &ibits); + } + } + } + if (FD_ISSET(f, &ibits)) { +#ifndef NOENCRYPTION + if (doencrypt) + fcc = des_enc_read(f, fibuf, + sizeof(fibuf), + schedule, &kdata->session); + else +#endif + fcc = read(f, fibuf, sizeof(fibuf)); + if (fcc < 0 && errno == EWOULDBLOCK) + fcc = 0; + else { + char *cp; + int left, n; + + if (fcc <= 0) + break; + fbp = fibuf; + + top: + for (cp = fibuf; cp < fibuf+fcc-1; cp++) + if (cp[0] == magic[0] && + cp[1] == magic[1]) { + left = fcc - (cp-fibuf); + n = control(master, cp, left); + if (n) { + left -= n; + if (left > 0) + memmove(cp, cp+n, left); + fcc -= n; + goto top; /* n^2 */ + } + } + FD_SET(master, &obits); /* try write */ + } + } + + if (FD_ISSET(master, &obits) && fcc > 0) { + cc = write(master, fbp, fcc); + if (cc > 0) { + fcc -= cc; + fbp += cc; + } + } + + if (FD_ISSET(master, &ibits)) { + pcc = readstream(master, pibuf, sizeof (pibuf)); + pbp = pibuf; + if (pcc < 0 && errno == EWOULDBLOCK) + pcc = 0; + else if (pcc <= 0) + break; + else if (pibuf[0] == 0) { + pbp++, pcc--; + if (!doencrypt) + FD_SET(f, &obits); /* try write */ + } else { + if (pkcontrol(pibuf[0])) { + oob_queue = pibuf[0]; +#if 0 /* Kludge around */ + send_oob(f, pibuf[0]); +#endif + } + pcc = 0; + } + } + if ((FD_ISSET(f, &obits)) && pcc > 0) { +#ifndef NOENCRYPTION + if (doencrypt) + cc = des_enc_write(f, pbp, pcc, schedule, &kdata->session); + else +#endif + cc = write(f, pbp, pcc); + if (cc < 0 && errno == EWOULDBLOCK) { + /* + * This happens when we try write after read + * from p, but some old kernels balk at large + * writes even when select returns true. + */ + if (!FD_ISSET(master, &ibits)) + sleep(5); + continue; + } + if (cc > 0) { + pcc -= cc; + pbp += cc; + /* Only send urg data when normal data + * has just been sent. + * Linux has deep problems with more + * than one byte of OOB data. + */ + if (oob_queue) { + send_oob (f, oob_queue); + oob_queue = 0; + } + } + } + } +} + +static RETSIGTYPE +cleanup(int signo) +{ + char *p = clean_ttyname (line); + + if (logout(p) == 0) + logwtmp(p, "", ""); + chmod(line, 0666); + chown(line, 0, 0); + *p = 'p'; + chmod(line, 0666); + chown(line, 0, 0); + shutdown(netf, 2); + signal(SIGHUP, SIG_IGN); +#ifdef HAVE_VHANGUP + vhangup(); +#endif /* HAVE_VHANGUP */ + exit(1); +} + +void +fatal(int f, const char *msg, int syserr) +{ + int len; + char buf[BUFSIZ], *bp = buf; + + /* + * Prepend binary one to message if we haven't sent + * the magic null as confirmation. + */ + if (!confirmed) + *bp++ = '\01'; /* error indicator */ + if (syserr) + snprintf(bp, sizeof(buf) - (bp - buf), + "rlogind: %s: %s.\r\n", + msg, strerror(errno)); + else + snprintf(bp, sizeof(buf) - (bp - buf), + "rlogind: %s.\r\n", msg); + len = strlen(bp); +#ifndef NOENCRYPTION + if (doencrypt) + des_enc_write(f, buf, bp + len - buf, schedule, &kdata->session); + else +#endif + write(f, buf, bp + len - buf); + exit(1); +} + +static void +xgetstr(char *buf, int cnt, char *errmsg) +{ + char c; + + do { + if (read(0, &c, 1) != 1) + exit(1); + if (--cnt < 0) + fatal(STDOUT_FILENO, errmsg, 0); + *buf++ = c; + } while (c != 0); +} + +static int +do_rlogin(struct sockaddr_in *dest) +{ + xgetstr(rusername, sizeof(rusername), "remuser too long"); + xgetstr(lusername, sizeof(lusername), "locuser too long"); + xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); + + pwd = k_getpwnam(lusername); + if (pwd == NULL) + return (-1); + if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0) + { + syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername); + return (-1); + } + return (iruserok(dest->sin_addr.s_addr, + (pwd->pw_uid == 0), + rusername, + lusername)); +} + +static void +setup_term(int fd) +{ + char *cp = strchr(term+ENVSIZE, '/'); + char *speed; + struct termios tt; + + tcgetattr(fd, &tt); + if (cp) { + int s; + + *cp++ = '\0'; + speed = cp; + cp = strchr(speed, '/'); + if (cp) + *cp++ = '\0'; + s = int2speed_t (atoi (speed)); + if (s > 0) { + cfsetospeed (&tt, s); + cfsetispeed (&tt, s); + } + } + + tt.c_iflag &= ~INPCK; + tt.c_iflag |= ICRNL|IXON; + tt.c_oflag |= OPOST|ONLCR; +#ifdef TAB3 + tt.c_oflag |= TAB3; +#endif /* TAB3 */ +#ifdef ONLRET + tt.c_oflag &= ~ONLRET; +#endif /* ONLRET */ + tt.c_lflag |= (ECHO|ECHOE|ECHOK|ISIG|ICANON); + tt.c_cflag &= ~PARENB; + tt.c_cflag |= CS8; + tt.c_cc[VMIN] = 1; + tt.c_cc[VTIME] = 0; + tt.c_cc[VEOF] = CEOF; + tcsetattr(fd, TCSAFLUSH, &tt); + + env[0] = term; + env[1] = 0; + environ = env; +} + +#define VERSION_SIZE 9 + +/* + * Do the remote kerberos login to the named host with the + * given inet address + * + * Return 0 on valid authorization + * Return -1 on valid authentication, no authorization + * Return >0 for error conditions + */ +static int +do_krb_login(struct sockaddr_in *dest) +{ + int rc; + char instance[INST_SZ], version[VERSION_SIZE]; + long authopts = 0L; /* !mutual */ + struct sockaddr_in faddr; + + kdata = (AUTH_DAT *) auth_buf; + ticket = (KTEXT) tick_buf; + + k_getsockinst(0, instance, sizeof(instance)); + + if (doencrypt) { + rc = sizeof(faddr); + if (getsockname(0, (struct sockaddr *)&faddr, &rc)) + return (-1); + authopts = KOPT_DO_MUTUAL; + rc = krb_recvauth( + authopts, 0, + ticket, "rcmd", + instance, dest, &faddr, + kdata, "", schedule, version); + des_set_key(&kdata->session, schedule); + + } else + rc = krb_recvauth( + authopts, 0, + ticket, "rcmd", + instance, dest, (struct sockaddr_in *) 0, + kdata, "", 0, version); + + if (rc != KSUCCESS) + return (rc); + + xgetstr(lusername, sizeof(lusername), "locuser"); + /* get the "cmd" in the rcmd protocol */ + xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); + + pwd = k_getpwnam(lusername); + if (pwd == NULL) + return (-1); + if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0) + { + syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername); + return (-1); + } + + /* returns nonzero for no access */ + if (kuserok(kdata, lusername) != 0) + return (-1); + + return (0); + +} + +static void +usage(void) +{ + syslog(LOG_ERR, + "usage: rlogind [-Dailn] [-p port] [-x] [-L login] [-k | -v]"); + exit(1); +} diff --git a/crypto/kerberosIV/appl/bsd/rsh.c b/crypto/kerberosIV/appl/bsd/rsh.c new file mode 100644 index 0000000..329ebf7 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/rsh.c @@ -0,0 +1,353 @@ +/*- + * Copyright (c) 1983, 1990 The Regents of the University of California. + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID("$Id: rsh.c,v 1.35 1997/03/30 18:20:22 joda Exp $"); + +CREDENTIALS cred; +Key_schedule schedule; +int use_kerberos = 1, doencrypt; +char dst_realm_buf[REALM_SZ], *dest_realm; + +/* + * rsh - remote shell + */ +int rfd2; + +static void +usage(void) +{ + fprintf(stderr, + "usage: rsh [-ndKx] [-k realm] [-l login] host [command]\n"); + exit(1); +} + +static char * +copyargs(char **argv) +{ + int cc; + char **ap, *p; + char *args; + + cc = 0; + for (ap = argv; *ap; ++ap) + cc += strlen(*ap) + 1; + if (!(args = malloc(cc))) + errx(1, "Out of memory."); + for (p = args, ap = argv; *ap; ++ap) { + strcpy(p, *ap); + for (p = strcpy(p, *ap); *p; ++p); + if (ap[1]) + *p++ = ' '; + } + return(args); +} + +static RETSIGTYPE +sendsig(int signo_) +{ + char signo = signo_; +#ifndef NOENCRYPTION + if (doencrypt) + des_enc_write(rfd2, &signo, 1, schedule, &cred.session); + else +#endif + write(rfd2, &signo, 1); +} + +static void +talk(int nflag, sigset_t omask, int pid, int rem) +{ + int cc, wc; + char *bp; + fd_set readfrom, ready, rembits; + char buf[BUFSIZ]; + + if (pid == 0) { + if (nflag) + goto done; + + close(rfd2); + + reread: errno = 0; + if ((cc = read(0, buf, sizeof buf)) <= 0) + goto done; + bp = buf; + + rewrite: FD_ZERO(&rembits); + FD_SET(rem, &rembits); + if (select(16, 0, &rembits, 0, 0) < 0) { + if (errno != EINTR) + err(1, "select"); + goto rewrite; + } + if (!FD_ISSET(rem, &rembits)) + goto rewrite; +#ifndef NOENCRYPTION + if (doencrypt) + wc = des_enc_write(rem, bp, cc, schedule, &cred.session); + else +#endif + wc = write(rem, bp, cc); + if (wc < 0) { + if (errno == EWOULDBLOCK) + goto rewrite; + goto done; + } + bp += wc; + cc -= wc; + if (cc == 0) + goto reread; + goto rewrite; + done: + shutdown(rem, 1); + exit(0); + } + + if (sigprocmask(SIG_SETMASK, &omask, 0) != 0) + warn("sigprocmask"); + FD_ZERO(&readfrom); + FD_SET(rem, &readfrom); + FD_SET(rfd2, &readfrom); + do { + ready = readfrom; + if (select(16, &ready, 0, 0, 0) < 0) { + if (errno != EINTR) + err(1, "select"); + continue; + } + if (FD_ISSET(rfd2, &ready)) { + errno = 0; +#ifndef NOENCRYPTION + if (doencrypt) + cc = des_enc_read(rfd2, buf, sizeof buf, + schedule, &cred.session); + else +#endif + cc = read(rfd2, buf, sizeof buf); + if (cc <= 0) { + if (errno != EWOULDBLOCK) + FD_CLR(rfd2, &readfrom); + } else + write(2, buf, cc); + } + if (FD_ISSET(rem, &ready)) { + errno = 0; +#ifndef NOENCRYPTION + if (doencrypt) + cc = des_enc_read(rem, buf, sizeof buf, + schedule, &cred.session); + else +#endif + cc = read(rem, buf, sizeof buf); + if (cc <= 0) { + if (errno != EWOULDBLOCK) + FD_CLR(rem, &readfrom); + } else + write(1, buf, cc); + } + } while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom)); +} + +int +main(int argc, char **argv) +{ + struct passwd *pw; + int sv_port; + sigset_t omask; + int argoff, ch, dflag, nflag, nfork, one, pid, rem, uid; + char *args, *host, *user, *local_user; + + argoff = dflag = nflag = nfork = 0; + one = 1; + host = user = NULL; + pid = 1; + + set_progname(argv[0]); + + /* handle "rsh host flags" */ + if (!host && argc > 2 && argv[1][0] != '-') { + host = argv[1]; + argoff = 1; + } + +#define OPTIONS "+8KLde:k:l:nwx" + while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) + switch(ch) { + case 'K': + use_kerberos = 0; + break; + case 'L': /* -8Lew are ignored to allow rlogin aliases */ + case 'e': + case 'w': + case '8': + break; + case 'd': + dflag = 1; + break; + case 'l': + user = optarg; + break; + case 'k': + dest_realm = dst_realm_buf; + strncpy(dest_realm, optarg, REALM_SZ); + break; + case 'n': + nflag = nfork = 1; + break; + case 'x': + doencrypt = 1; + break; + case '?': + default: + usage(); + } + optind += argoff; + + /* if haven't gotten a host yet, do so */ + if (!host && !(host = argv[optind++])) + usage(); + + /* if no further arguments, must have been called as rlogin. */ + if (!argv[optind]) { + *argv = "rlogin"; + setuid(getuid()); + execv(_PATH_RLOGIN, argv); + err(1, "can't exec %s", _PATH_RLOGIN); + } + + argc -= optind; + argv += optind; + +#ifndef __CYGWIN32__ + if (!(pw = k_getpwuid(uid = getuid()))) + errx(1, "unknown user id."); + local_user = pw->pw_name; + if (!user) + user = local_user; +#else + if (!user) + errx(1, "Sorry, you need to specify the username (with -l)"); + local_user = user; +#endif + + /* -n must still fork but does not turn of the -n functionality */ + if (doencrypt) + nfork = 0; + + args = copyargs(argv); + + sv_port=get_shell_port(use_kerberos, doencrypt); + +try_connect: + if (use_kerberos) { + rem = KSUCCESS; + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(host); + + if (doencrypt) + rem = krcmd_mutual(&host, sv_port, user, args, + &rfd2, dest_realm, &cred, schedule); + else + rem = krcmd(&host, sv_port, user, args, &rfd2, + dest_realm); + if (rem < 0) { + if (errno == ECONNREFUSED) + warning("remote host doesn't support Kerberos"); + if (errno == ENOENT) + warning("can't provide Kerberos auth data"); + use_kerberos = 0; + sv_port=get_shell_port(use_kerberos, doencrypt); + goto try_connect; + } + } else { + if (doencrypt) + errx(1, "the -x flag requires Kerberos authentication."); + if (geteuid() != 0) + errx(1, "not installed setuid root, " + "only root may use non kerberized rsh"); + rem = rcmd(&host, sv_port, local_user, user, args, &rfd2); + } + + if (rem < 0) + exit(1); + + if (rfd2 < 0) + errx(1, "can't establish stderr."); +#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) + if (dflag) { + if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, (void *)&one, + sizeof(one)) < 0) + warn("setsockopt"); + if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, (void *)&one, + sizeof(one)) < 0) + warn("setsockopt"); + } +#endif + + setuid(uid); + { + sigset_t sigmsk; + sigemptyset(&sigmsk); + sigaddset(&sigmsk, SIGINT); + sigaddset(&sigmsk, SIGQUIT); + sigaddset(&sigmsk, SIGTERM); + if (sigprocmask(SIG_BLOCK, &sigmsk, &omask) != 0) + warn("sigprocmask"); + } + 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 (!nfork) { + pid = fork(); + if (pid < 0) + err(1, "fork"); + } + + if (!doencrypt) { + ioctl(rfd2, FIONBIO, &one); + ioctl(rem, FIONBIO, &one); + } + + talk(nflag, omask, pid, rem); + + if (!nflag) + kill(pid, SIGKILL); + exit(0); +} diff --git a/crypto/kerberosIV/appl/bsd/rshd.c b/crypto/kerberosIV/appl/bsd/rshd.c new file mode 100644 index 0000000..75ca1df --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/rshd.c @@ -0,0 +1,635 @@ +/*- + * Copyright (c) 1988, 1989, 1992, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * remote shell server: + * [port]\0 + * remuser\0 + * locuser\0 + * command\0 + * data + */ + +#include "bsd_locl.h" + +RCSID("$Id: rshd.c,v 1.51 1997/05/13 09:42:39 bg Exp $"); + +extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */ +extern int __check_rhosts_file; + +static int keepalive = 1; +static int log_success; /* If TRUE, log all successful accesses */ +static int new_pag = 1; /* Put process in new PAG by default */ +static int no_inetd = 0; +static int sent_null; + +static void doit (struct sockaddr_in *); +static void error (const char *, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; +static void usage (void); + +#define VERSION_SIZE 9 +#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n" +#define OPTIONS "alnkvxLp:Pi" +AUTH_DAT authbuf; +KTEXT_ST tickbuf; +int doencrypt, use_kerberos, vacuous; +Key_schedule schedule; + +int +main(int argc, char *argv[]) +{ + struct linger linger; + int ch, on = 1, fromlen; + struct sockaddr_in from; + int portnum = 0; + + set_progname(argv[0]); + + openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON); + + opterr = 0; + while ((ch = getopt(argc, argv, OPTIONS)) != EOF) + switch (ch) { + case 'a': + break; + case 'l': + __check_rhosts_file = 0; + break; + case 'n': + keepalive = 0; + break; + case 'k': + use_kerberos = 1; + break; + + case 'v': + vacuous = 1; + break; + + case 'x': + doencrypt = 1; + break; + case 'L': + log_success = 1; + break; + case 'p': + portnum = htons(atoi(optarg)); + break; + case 'P': + new_pag = 0; + break; + case 'i': + no_inetd = 1; + break; + case '?': + default: + usage(); + break; + } + + argc -= optind; + argv += optind; + + if (use_kerberos && vacuous) { + syslog(LOG_ERR, "only one of -k and -v allowed"); + exit(2); + } + if (doencrypt && !use_kerberos) { + syslog(LOG_ERR, "-k is required for -x"); + exit(2); + } + + if (no_inetd) { + if(portnum == 0) + portnum = get_shell_port (use_kerberos, doencrypt); + mini_inetd (portnum); + } + + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + _exit(1); + } +#ifdef HAVE_SETSOCKOPT +#ifdef SO_KEEPALIVE + if (keepalive && + setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, + sizeof(on)) < 0) + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); +#endif +#ifdef SO_LINGER + linger.l_onoff = 1; + linger.l_linger = 60; /* XXX */ + if (setsockopt(0, SOL_SOCKET, SO_LINGER, (void *)&linger, + sizeof (linger)) < 0) + syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); +#endif +#endif /* HAVE_SETSOCKOPT */ + doit(&from); + /* NOTREACHED */ + return 0; +} + +char username[20] = "USER="; +char homedir[64] = "HOME="; +char shell[64] = "SHELL="; +char path[100] = "PATH="; +char *envinit[] = +{homedir, shell, path, username, 0}; + +static void +xgetstr(char *buf, int cnt, char *err) +{ + char c; + + do { + if (read(STDIN_FILENO, &c, 1) != 1) + exit(1); + *buf++ = c; + if (--cnt == 0) { + error("%s too long\n", err); + exit(1); + } + } while (c != 0); +} + +static void +doit(struct sockaddr_in *fromp) +{ + struct passwd *pwd; + u_short port; + fd_set ready, readfrom; + int cc, nfd, pv[2], pid, s; + int one = 1; + const char *errorhost = ""; + char *errorstr; + char *cp, sig, buf[BUFSIZ]; + char cmdbuf[NCARGS+1], locuser[16], remuser[16]; + char remotehost[2 * MaxHostNameLen + 1]; + + AUTH_DAT *kdata; + KTEXT ticket; + char instance[INST_SZ], version[VERSION_SIZE]; + struct sockaddr_in fromaddr; + int rc; + long authopts; + int pv1[2], pv2[2]; + fd_set wready, writeto; + + fromaddr = *fromp; + + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +#ifdef DEBUG + { int t = open(_PATH_TTY, 2); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + close(t); + } + } +#endif + fromp->sin_port = ntohs((u_short)fromp->sin_port); + if (fromp->sin_family != AF_INET) { + syslog(LOG_ERR, "malformed \"from\" address (af %d)\n", + fromp->sin_family); + exit(1); + } + + + if (!use_kerberos) { + ip_options_and_die (0, fromp); + if (fromp->sin_port >= IPPORT_RESERVED || + fromp->sin_port < IPPORT_RESERVED/2) { + syslog(LOG_NOTICE|LOG_AUTH, + "Connection from %s on illegal port %u", + inet_ntoa(fromp->sin_addr), + fromp->sin_port); + exit(1); + } + } + + alarm(60); + port = 0; + for (;;) { + char c; + if ((cc = read(STDIN_FILENO, &c, 1)) != 1) { + if (cc < 0) + syslog(LOG_NOTICE, "read: %m"); + shutdown(0, 1+1); + exit(1); + } + if (c== 0) + break; + port = port * 10 + c - '0'; + } + + alarm(0); + if (port != 0) { + int lport = IPPORT_RESERVED - 1; + s = rresvport(&lport); + if (s < 0) { + syslog(LOG_ERR, "can't get stderr port: %m"); + exit(1); + } + if (!use_kerberos) + if (port >= IPPORT_RESERVED) { + syslog(LOG_ERR, "2nd port not reserved\n"); + exit(1); + } + fromp->sin_port = htons(port); + if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { + syslog(LOG_INFO, "connect second port %d: %m", port); + exit(1); + } + } + + if (vacuous) { + error("rshd: remote host requires Kerberos authentication\n"); + exit(1); + } + + errorstr = NULL; + inaddr2str (fromp->sin_addr, remotehost, sizeof(remotehost)); + + if (use_kerberos) { + kdata = &authbuf; + ticket = &tickbuf; + authopts = 0L; + k_getsockinst(0, instance, sizeof(instance)); + version[VERSION_SIZE - 1] = '\0'; + if (doencrypt) { + struct sockaddr_in local_addr; + rc = sizeof(local_addr); + if (getsockname(0, (struct sockaddr *)&local_addr, + &rc) < 0) { + syslog(LOG_ERR, "getsockname: %m"); + error("rlogind: getsockname: %m"); + exit(1); + } + authopts = KOPT_DO_MUTUAL; + rc = krb_recvauth(authopts, 0, ticket, + "rcmd", instance, &fromaddr, + &local_addr, kdata, "", schedule, + version); +#ifndef NOENCRYPTION + des_set_key(&kdata->session, schedule); +#else + memset(schedule, 0, sizeof(schedule)); +#endif + } else + rc = krb_recvauth(authopts, 0, ticket, "rcmd", + instance, &fromaddr, + (struct sockaddr_in *) 0, + kdata, "", 0, version); + if (rc != KSUCCESS) { + error("Kerberos authentication failure: %s\n", + krb_get_err_text(rc)); + exit(1); + } + } else + xgetstr(remuser, sizeof(remuser), "remuser"); + + xgetstr(locuser, sizeof(locuser), "locuser"); + xgetstr(cmdbuf, sizeof(cmdbuf), "command"); + setpwent(); + pwd = k_getpwnam(locuser); + if (pwd == NULL) { + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: unknown login. cmd='%.80s'", + remuser, remotehost, locuser, cmdbuf); + if (errorstr == NULL) + errorstr = "Login incorrect.\n"; + goto fail; + } + if (pwd->pw_uid == 0 && strcmp("root", locuser) != 0) + { + syslog(LOG_ALERT, "NIS attack, user %s has uid 0", locuser); + if (errorstr == NULL) + errorstr = "Login incorrect.\n"; + goto fail; + } + if (chdir(pwd->pw_dir) < 0) { + chdir("/"); +#ifdef notdef + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: no home directory. cmd='%.80s'", + remuser, remotehost, locuser, cmdbuf); + error("No remote directory.\n"); + exit(1); +#endif + } + + if (use_kerberos) { + if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') { + if (kuserok(kdata, locuser) != 0) { + syslog(LOG_INFO|LOG_AUTH, + "Kerberos rsh denied to %s", + krb_unparse_name_long(kdata->pname, + kdata->pinst, + kdata->prealm)); + error("Permission denied.\n"); + exit(1); + } + } + } else + + if (errorstr || + pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && + iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0, + remuser, locuser) < 0) { + if (__rcmd_errstr) + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: permission denied (%s). cmd='%.80s'", + remuser, remotehost, locuser, + __rcmd_errstr, cmdbuf); + else + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: permission denied. cmd='%.80s'", + remuser, remotehost, locuser, cmdbuf); + fail: + if (errorstr == NULL) + errorstr = "Permission denied.\n"; + error(errorstr, errorhost); + exit(1); + } + + if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) { + error("Logins currently disabled.\n"); + exit(1); + } + + write(STDERR_FILENO, "\0", 1); + sent_null = 1; + + if (port) { + if (pipe(pv) < 0) { + error("Can't make pipe.\n"); + exit(1); + } + if (doencrypt) { + if (pipe(pv1) < 0) { + error("Can't make 2nd pipe.\n"); + exit(1); + } + if (pipe(pv2) < 0) { + error("Can't make 3rd pipe.\n"); + exit(1); + } + } + pid = fork(); + if (pid == -1) { + error("Can't fork; try again.\n"); + exit(1); + } + if (pid) { + if (doencrypt) { + static char msg[] = SECURE_MESSAGE; + close(pv1[1]); + close(pv2[0]); +#ifndef NOENCRYPTION + des_enc_write(s, msg, sizeof(msg) - 1, schedule, &kdata->session); +#else + write(s, msg, sizeof(msg) - 1); +#endif + } else { + close(0); + close(1); + } + close(2); + close(pv[1]); + + FD_ZERO(&readfrom); + FD_SET(s, &readfrom); + FD_SET(pv[0], &readfrom); + if (pv[0] > s) + nfd = pv[0]; + else + nfd = s; + if (doencrypt) { + FD_ZERO(&writeto); + FD_SET(pv2[1], &writeto); + FD_SET(pv1[0], &readfrom); + FD_SET(STDIN_FILENO, &readfrom); + + nfd = max(nfd, pv2[1]); + nfd = max(nfd, pv1[0]); + } else + ioctl(pv[0], FIONBIO, (char *)&one); + + /* should set s nbio! */ + nfd++; + do { + ready = readfrom; + if (doencrypt) { + wready = writeto; + if (select(nfd, &ready, + &wready, 0, + (struct timeval *) 0) < 0) + break; + } else + if (select(nfd, &ready, 0, + 0, (struct timeval *)0) < 0) + break; + if (FD_ISSET(s, &ready)) { + int ret; + if (doencrypt) +#ifndef NOENCRYPTION + ret = des_enc_read(s, &sig, 1, schedule, &kdata->session); +#else + ret = read(s, &sig, 1); +#endif + else + ret = read(s, &sig, 1); + if (ret <= 0) + FD_CLR(s, &readfrom); + else + kill(-pid, sig); + } + if (FD_ISSET(pv[0], &ready)) { + errno = 0; + cc = read(pv[0], buf, sizeof(buf)); + if (cc <= 0) { + shutdown(s, 1+1); + FD_CLR(pv[0], &readfrom); + } else { + if (doencrypt) +#ifndef NOENCRYPTION + des_enc_write(s, buf, cc, schedule, &kdata->session); +#else + write(s, buf, cc); +#endif + else + (void) + write(s, buf, cc); + } + } + if (doencrypt && FD_ISSET(pv1[0], &ready)) { + errno = 0; + cc = read(pv1[0], buf, sizeof(buf)); + if (cc <= 0) { + shutdown(pv1[0], 1+1); + FD_CLR(pv1[0], &readfrom); + } else +#ifndef NOENCRYPTION + des_enc_write(STDOUT_FILENO, buf, cc, schedule, &kdata->session); +#else + write(STDOUT_FILENO, buf, cc); +#endif + } + + if (doencrypt + && FD_ISSET(STDIN_FILENO, &ready) + && FD_ISSET(pv2[1], &wready)) { + errno = 0; +#ifndef NOENCRYPTION + cc = des_enc_read(STDIN_FILENO, buf, sizeof(buf), schedule, &kdata->session); +#else + cc = read(STDIN_FILENO, buf, sizeof(buf)); +#endif + if (cc <= 0) { + shutdown(STDIN_FILENO, 0); + FD_CLR(STDIN_FILENO, &readfrom); + close(pv2[1]); + FD_CLR(pv2[1], &writeto); + } else + write(pv2[1], buf, cc); + } + + } while (FD_ISSET(s, &readfrom) || + (doencrypt && FD_ISSET(pv1[0], &readfrom)) || + FD_ISSET(pv[0], &readfrom)); + exit(0); + } + setsid(); + close(s); + close(pv[0]); + if (doencrypt) { + close(pv1[0]); + close(pv2[1]); + dup2(pv1[1], 1); + dup2(pv2[0], 0); + close(pv1[1]); + close(pv2[0]); + } + dup2(pv[1], 2); + close(pv[1]); + } + if (*pwd->pw_shell == '\0') + pwd->pw_shell = _PATH_BSHELL; +#ifdef HAVE_SETLOGIN + if (setlogin(pwd->pw_name) < 0) + syslog(LOG_ERR, "setlogin() failed: %m"); +#endif + +#ifdef HAVE_SETPCRED + if (setpcred (pwd->pw_name, NULL) == -1) + syslog(LOG_ERR, "setpcred() failure: %m"); +#endif /* HAVE_SETPCRED */ + setgid((gid_t)pwd->pw_gid); + initgroups(pwd->pw_name, pwd->pw_gid); + setuid((uid_t)pwd->pw_uid); + strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); + + /* Need to extend path to find rcp */ + strncat(path, BINDIR, sizeof(path)-1); + strncat(path, ":", sizeof(path)-1); + strncat(path, _PATH_DEFPATH, sizeof(path)-1); + path[sizeof(path)-1] = '\0'; + + strncat(shell, pwd->pw_shell, sizeof(shell)-7); + strncat(username, pwd->pw_name, sizeof(username)-6); + cp = strrchr(pwd->pw_shell, '/'); + if (cp) + cp++; + else + cp = pwd->pw_shell; + endpwent(); + if (log_success || pwd->pw_uid == 0) { + if (use_kerberos) + syslog(LOG_INFO|LOG_AUTH, + "Kerberos shell from %s on %s as %s, cmd='%.80s'", + krb_unparse_name_long(kdata->pname, + kdata->pinst, + kdata->prealm), + remotehost, locuser, cmdbuf); + else + syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", + remuser, remotehost, locuser, cmdbuf); + } + if (k_hasafs()) { + if (new_pag) + k_setpag(); /* Put users process in an new pag */ + k_afsklog(0, 0); + } + execle(pwd->pw_shell, cp, "-c", cmdbuf, 0, envinit); + err(1, pwd->pw_shell); +} + +/* + * Report error to client. Note: can't be used until second socket has + * connected to client, or older clients will hang waiting for that + * connection first. + */ + +static void +error(const char *fmt, ...) +{ + va_list ap; + int len; + char *bp, buf[BUFSIZ]; + + va_start(ap, fmt); + bp = buf; + if (sent_null == 0) { + *bp++ = 1; + len = 1; + } else + len = 0; + len = vsnprintf (bp, sizeof(buf) - len, fmt, ap); + write (STDERR_FILENO, buf, len); + va_end(ap); +} + +static void +usage() +{ + + syslog(LOG_ERR, + "usage: rshd [-alnkvxLPi] [-p port]"); + exit(2); +} diff --git a/crypto/kerberosIV/appl/bsd/stty_default.c b/crypto/kerberosIV/appl/bsd/stty_default.c new file mode 100644 index 0000000..b7112c1 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/stty_default.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "bsd_locl.h" + +RCSID("$Id: stty_default.c,v 1.6 1997/04/01 08:17:17 joda Exp $"); + +#include <termios.h> + +/* HP-UX 9.0 termios doesn't define these */ +#ifndef FLUSHO +#define FLUSHO 0 +#endif + +#ifndef XTABS +#define XTABS 0 +#endif + +#ifndef OXTABS +#define OXTABS XTABS +#endif + +/* Ultrix... */ +#ifndef ECHOPRT +#define ECHOPRT 0 +#endif + +#ifndef ECHOCTL +#define ECHOCTL 0 +#endif + +#ifndef ECHOKE +#define ECHOKE 0 +#endif + +#ifndef IMAXBEL +#define IMAXBEL 0 +#endif + +#define Ctl(x) ((x) ^ 0100) + +void +stty_default(void) +{ + struct termios termios; + + /* + * Finalize the terminal settings. Some systems default to 8 bits, + * others to 7, so we should leave that alone. + */ + tcgetattr(0, &termios); + + termios.c_iflag |= (BRKINT|IGNPAR|ICRNL|IXON|IMAXBEL); + termios.c_iflag &= ~IXANY; + + termios.c_lflag |= (ISIG|IEXTEN|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE); + termios.c_lflag &= ~(ECHOPRT|TOSTOP|FLUSHO); + + termios.c_oflag |= (OPOST|ONLCR); + termios.c_oflag &= ~OXTABS; + + termios.c_cc[VINTR] = Ctl('C'); + termios.c_cc[VERASE] = Ctl('H'); + termios.c_cc[VKILL] = Ctl('U'); + termios.c_cc[VEOF] = Ctl('D'); + + termios.c_cc[VSUSP] = Ctl('Z'); + + tcsetattr(0, TCSANOW, &termios); +} diff --git a/crypto/kerberosIV/appl/bsd/su.c b/crypto/kerberosIV/appl/bsd/su.c new file mode 100644 index 0000000..8c610e1 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/su.c @@ -0,0 +1,452 @@ +/* + * Copyright (c) 1988 The Regents of the University of California. + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "bsd_locl.h" + +RCSID ("$Id: su.c,v 1.59 1997/05/26 17:45:54 bg Exp $"); + +#ifdef SYSV_SHADOW +#include "sysv_shadow.h" +#endif + +static int kerberos (char *username, char *user, int uid); +static int chshell (char *sh); +static char *ontty (void); +static int koktologin (char *name, char *realm, char *toname); +static int chshell (char *sh); + +/* Handle '-' option after all the getopt options */ +#define ARGSTR "Kflmi:" + +static int use_kerberos = 1; +static char *root_inst = "root"; + +int +main (int argc, char **argv) +{ + struct passwd *pwd; + char *p, **g; + struct group *gr; + uid_t ruid; + int asme, ch, asthem, fastlogin, prio; + enum { UNSET, YES, NO } iscsh = UNSET; + char *user, *shell, *avshell, *username, **np; + char shellbuf[MaxPathLen], avshellbuf[MaxPathLen]; + + set_progname (argv[0]); + + asme = asthem = fastlogin = 0; + while ((ch = getopt (argc, argv, ARGSTR)) != EOF) + switch ((char) ch) { + case 'K': + use_kerberos = 0; + break; + case 'f': + fastlogin = 1; + break; + case 'l': + asme = 0; + asthem = 1; + break; + case 'm': + asme = 1; + asthem = 0; + break; + case 'i': + root_inst = optarg; + break; + case '?': + default: + fprintf (stderr, + "usage: su [-Kflm] [-i root-instance] [-] [login]\n"); + exit (1); + } + /* Don't handle '-' option with getopt */ + if (optind < argc && strcmp (argv[optind], "-") == 0) { + asme = 0; + asthem = 1; + optind++; + } + argv += optind; + + if (use_kerberos) { + int fd = open (KEYFILE, O_RDONLY); + + if (fd >= 0) + close (fd); + else + use_kerberos = 0; + } + errno = 0; + prio = getpriority (PRIO_PROCESS, 0); + if (errno) + prio = 0; + setpriority (PRIO_PROCESS, 0, -2); + openlog ("su", LOG_CONS, 0); + + /* get current login name and shell */ + ruid = getuid (); + username = getlogin (); + if (username == NULL || (pwd = k_getpwnam (username)) == NULL || + pwd->pw_uid != ruid) + pwd = k_getpwuid (ruid); + if (pwd == NULL) + errx (1, "who are you?"); + username = strdup (pwd->pw_name); + if (asme) + if (pwd->pw_shell && *pwd->pw_shell) + shell = strcpy (shellbuf, pwd->pw_shell); + else { + shell = _PATH_BSHELL; + iscsh = NO; + } + + /* get target login information, default to root */ + user = *argv ? *argv : "root"; + np = *argv ? argv : argv - 1; + + pwd = k_getpwnam (user); + if (pwd == NULL) + errx (1, "unknown login %s", user); + if (pwd->pw_uid == 0 && strcmp ("root", user) != 0) { + syslog (LOG_ALERT, "NIS attack, user %s has uid 0", user); + errx (1, "unknown login %s", user); + } + if (!use_kerberos || kerberos (username, user, pwd->pw_uid)) { +#ifndef PASSWD_FALLBACK + errx (1, "won't use /etc/passwd authentication"); +#endif + /* getpwnam() is not reentrant and kerberos might use it! */ + pwd = k_getpwnam (user); + if (pwd == NULL) + errx (1, "unknown login %s", user); + /* only allow those in group zero to su to root. */ + if (pwd->pw_uid == 0 && (gr = getgrgid ((gid_t) 0))) + for (g = gr->gr_mem;; ++g) { + if (!*g) { +#if 1 + /* if group 0 is empty or only + contains root su is still ok. */ + if (gr->gr_mem[0] == 0) + break; /* group 0 is empty */ + if (gr->gr_mem[1] == 0 && + strcmp (gr->gr_mem[0], "root") == 0) + break; /* only root in group 0 */ +#endif + errx (1, "you are not in the correct group to su %s.", + user); + } + if (!strcmp (username, *g)) + break; + } + /* if target requires a password, verify it */ + if (ruid && *pwd->pw_passwd) { + char prompt[128]; + char passwd[256]; + + snprintf (prompt, sizeof(prompt), "%s's Password: ", pwd->pw_name); + if (des_read_pw_string (passwd, sizeof (passwd), + prompt, 0)) { + memset (passwd, 0, sizeof (passwd)); + exit (1); + } + if (strcmp (pwd->pw_passwd, + crypt (passwd, pwd->pw_passwd))) { + memset (passwd, 0, sizeof (passwd)); + syslog (LOG_AUTH | LOG_WARNING, + "BAD SU %s to %s%s", username, + user, ontty ()); + errx (1, "Sorry"); + } + memset (passwd, 0, sizeof (passwd)); + } + } + if (asme) { + /* if asme and non-standard target shell, must be root */ + if (!chshell (pwd->pw_shell) && ruid) + errx (1, "permission denied (shell '%s' not in /etc/shells).", + pwd->pw_shell); + } else if (pwd->pw_shell && *pwd->pw_shell) { + shell = pwd->pw_shell; + iscsh = UNSET; + } else { + shell = _PATH_BSHELL; + iscsh = NO; + } + + if ((p = strrchr (shell, '/')) != 0) + avshell = p + 1; + else + avshell = shell; + + /* if we're forking a csh, we want to slightly muck the args */ + if (iscsh == UNSET) + iscsh = strcmp (avshell, "csh") ? NO : YES; + + /* set permissions */ + + if (setgid (pwd->pw_gid) < 0) + err (1, "setgid"); + if (initgroups (user, pwd->pw_gid)) + errx (1, "initgroups failed."); + + if (setuid (pwd->pw_uid) < 0) + err (1, "setuid"); + + if (!asme) { + if (asthem) { + char *k = getenv ("KRBTKFILE"); + char *t = getenv ("TERM"); + + environ = malloc (10 * sizeof (char *)); + environ[0] = NULL; + setenv ("PATH", _PATH_DEFPATH, 1); + if (t) + setenv ("TERM", t, 1); + if (k) + setenv ("KRBTKFILE", k, 1); + if (chdir (pwd->pw_dir) < 0) + errx (1, "no directory"); + } + if (asthem || pwd->pw_uid) + setenv ("USER", pwd->pw_name, 1); + setenv ("HOME", pwd->pw_dir, 1); + setenv ("SHELL", shell, 1); + } + if (iscsh == YES) { + if (fastlogin) + *np-- = "-f"; + if (asme) + *np-- = "-m"; + } + if (asthem) { + avshellbuf[0] = '-'; + strcpy (avshellbuf + 1, avshell); + avshell = avshellbuf; + } else if (iscsh == YES) { + /* csh strips the first character... */ + avshellbuf[0] = '_'; + strcpy (avshellbuf + 1, avshell); + avshell = avshellbuf; + } + *np = avshell; + + if (ruid != 0) + syslog (LOG_NOTICE | LOG_AUTH, "%s to %s%s", + username, user, ontty ()); + + setpriority (PRIO_PROCESS, 0, prio); + + if (k_hasafs ()) { + int code; + + if (k_setpag () != 0) + warn ("setpag"); + code = k_afsklog (0, 0); + if (code != KSUCCESS && code != KDC_PR_UNKNOWN) + warnx ("afsklog: %s", krb_get_err_text (code)); + } + execv (shell, np); + warn ("execv(%s)", shell); + if (getuid () == 0) { + execv (_PATH_BSHELL, np); + warn ("execv(%s)", _PATH_BSHELL); + } + exit (1); +} + +static int +chshell (char *sh) +{ + char *cp; + + while ((cp = getusershell ()) != NULL) + if (!strcmp (cp, sh)) + return (1); + return (0); +} + +static char * +ontty (void) +{ + char *p; + static char buf[MaxPathLen + 4]; + + buf[0] = 0; + if ((p = ttyname (STDERR_FILENO)) != 0) + snprintf (buf, sizeof(buf), " on %s", p); + return (buf); +} + +static int +kerberos (char *username, char *user, int uid) +{ + KTEXT_ST ticket; + AUTH_DAT authdata; + struct hostent *hp; + int kerno; + u_long faddr; + char lrealm[REALM_SZ], krbtkfile[MaxPathLen]; + char hostname[MaxHostNameLen], savehost[MaxHostNameLen]; + + if (krb_get_lrealm (lrealm, 1) != KSUCCESS) + return (1); + if (koktologin (username, lrealm, user) && !uid) { +#ifndef PASSWD_FALLBACK + warnx ("not in %s's ACL.", user); +#endif + return (1); + } + snprintf (krbtkfile, sizeof(krbtkfile), + "%s_%s_to_%s_%u", TKT_ROOT, username, user, + (unsigned) getpid ()); + + setenv ("KRBTKFILE", krbtkfile, 1); + krb_set_tkt_string (krbtkfile); + /* + * Little trick here -- if we are su'ing to root, we need to get a ticket + * for "xxx.root", where xxx represents the name of the person su'ing. + * Otherwise (non-root case), we need to get a ticket for "yyy.", where + * yyy represents the name of the person being su'd to, and the instance + * is null + * + * We should have a way to set the ticket lifetime, with a system default + * for root. + */ + { + char prompt[128]; + char passw[256]; + + snprintf (prompt, sizeof(prompt), + "%s's Password: ", + krb_unparse_name_long ((uid == 0 ? username : user), + (uid == 0 ? root_inst : ""), + lrealm)); + if (des_read_pw_string (passw, sizeof (passw), prompt, 0)) { + memset (passw, 0, sizeof (passw)); + return (1); + } + if (strlen(passw) == 0) + return (1); /* Empty passwords is not allowed */ + kerno = krb_get_pw_in_tkt ((uid == 0 ? username : user), + (uid == 0 ? root_inst : ""), lrealm, + KRB_TICKET_GRANTING_TICKET, + lrealm, + DEFAULT_TKT_LIFE, + passw); + memset (passw, 0, strlen (passw)); + } + + if (kerno != KSUCCESS) { + if (kerno == KDC_PR_UNKNOWN) { + warnx ("principal unknown: %s", + krb_unparse_name_long ((uid == 0 ? username : user), + (uid == 0 ? root_inst : ""), + lrealm)); + return (1); + } + warnx ("unable to su: %s", krb_get_err_text (kerno)); + syslog (LOG_NOTICE | LOG_AUTH, + "BAD SU: %s to %s%s: %s", + username, user, ontty (), krb_get_err_text (kerno)); + return (1); + } + if (chown (krbtkfile, uid, -1) < 0) { + warn ("chown"); + unlink (krbtkfile); + return (1); + } + setpriority (PRIO_PROCESS, 0, -2); + + if (k_gethostname (hostname, sizeof (hostname)) == -1) { + warn ("gethostname"); + dest_tkt (); + return (1); + } + strncpy (savehost, krb_get_phost (hostname), sizeof (savehost)); + savehost[sizeof (savehost) - 1] = '\0'; + + kerno = krb_mk_req (&ticket, "rcmd", savehost, lrealm, 33); + + if (kerno == KDC_PR_UNKNOWN) { + warnx ("Warning: TGT not verified."); + syslog (LOG_NOTICE | LOG_AUTH, + "%s to %s%s, TGT not verified (%s); " + "%s.%s not registered?", + username, user, ontty (), krb_get_err_text (kerno), + "rcmd", savehost); +#ifdef KLOGIN_PARANOID + /* + * if the "VERIFY_SERVICE" doesn't exist in the KDC for this host, * + * don't allow kerberos login, also log the error condition. + */ + warnx ("Trying local password!"); + return (1); +#endif + } else if (kerno != KSUCCESS) { + warnx ("Unable to use TGT: %s", krb_get_err_text (kerno)); + syslog (LOG_NOTICE | LOG_AUTH, "failed su: %s to %s%s: %s", + username, user, ontty (), krb_get_err_text (kerno)); + dest_tkt (); + return (1); + } else { + if (!(hp = gethostbyname (hostname))) { + warnx ("can't get addr of %s", hostname); + dest_tkt (); + return (1); + } + memcpy (&faddr, hp->h_addr, sizeof (faddr)); + + if ((kerno = krb_rd_req (&ticket, "rcmd", savehost, faddr, + &authdata, "")) != KSUCCESS) { + warnx ("unable to verify rcmd ticket: %s", + krb_get_err_text (kerno)); + syslog (LOG_NOTICE | LOG_AUTH, + "failed su: %s to %s%s: %s", username, + user, ontty (), krb_get_err_text (kerno)); + dest_tkt (); + return (1); + } + } + fprintf (stderr, "Don't forget to kdestroy before exiting the shell.\n"); + return (0); +} + +static int +koktologin (char *name, char *realm, char *toname) +{ + return krb_kuserok (name, + strcmp (toname, "root") == 0 ? root_inst : "", + realm, + toname); +} diff --git a/crypto/kerberosIV/appl/bsd/sysv_default.c b/crypto/kerberosIV/appl/bsd/sysv_default.c new file mode 100644 index 0000000..cb36b84 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/sysv_default.c @@ -0,0 +1,95 @@ +/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */ + +#include "bsd_locl.h" + +RCSID("$Id: sysv_default.c,v 1.9 1997/03/31 01:47:59 assar Exp $"); + +#include "sysv_default.h" + + /* + * Default values for stuff that can be read from the defaults file. The + * SunOS 5.1 documentation is incomplete and often disagrees with reality. + */ + +static char default_umask_value[] = "022"; + +char *default_console = 0; +char *default_altsh = "YES"; +char *default_passreq = "NO"; +char *default_timezone= 0; +char *default_hz = 0; +char *default_path = _PATH_DEFPATH; +char *default_supath = _PATH_DEFSUPATH; +char *default_ulimit = 0; +char *default_timeout = "60"; +char *default_umask = default_umask_value; +char *default_sleep = "4"; +char *default_maxtrys = "5"; + +static struct sysv_default { + char **valptr; + char *prefix; + int prefix_len; +} defaults[] = { + {&default_console, "CONSOLE=", sizeof("CONSOLE=") -1}, + {&default_altsh, "ALTSHELL=", sizeof("ALTSHELL=") -1}, + {&default_passreq, "PASSREQ=", sizeof("PASSREQ=") -1}, + {&default_timezone, "TIMEZONE=", sizeof("TIMEZONE=") -1}, + {&default_hz, "HZ=", sizeof("HZ=") -1}, + {&default_path, "PATH=", sizeof("PATH=") -1}, + {&default_supath, "SUPATH=", sizeof("SUPATH=") -1}, + {&default_ulimit, "ULIMIT=", sizeof("ULIMIT=") -1}, + {&default_timeout, "TIMEOUT=", sizeof("TIMEOUT=") -1}, + {&default_umask, "UMASK=", sizeof("UMASK=") -1}, + {&default_sleep, "SLEEPTIME=", sizeof("SLEEPTIME=") -1}, + {&default_maxtrys, "MAXTRYS=", sizeof("MAXTRYS=") -1}, + {0}, +}; + +#define trim(s) { \ + char *cp = s + strlen(s); \ + while (cp > s && isspace(cp[-1])) \ + cp--; \ + *cp = 0; \ +} + +/* sysv_defaults - read login defaults file */ + +void +sysv_defaults() +{ + struct sysv_default *dp; + FILE *fp; + char buf[BUFSIZ]; + + if ((fp = fopen(_PATH_ETC_DEFAULT_LOGIN, "r"))) { + + /* Stupid quadratic algorithm. */ + + while (fgets(buf, sizeof(buf), fp)) { + + /* Skip comments and blank lines. */ + + if (buf[0] == '#') + continue; + trim(buf); + if (buf[0] == 0) + continue; + + /* Assign defaults from file. */ + +#define STREQN(x,y,l) (x[0] == y[0] && strncmp(x,y,l) == 0) + + for (dp = defaults; dp->valptr; dp++) { + if (STREQN(buf, dp->prefix, dp->prefix_len)) { + if ((*(dp->valptr) = strdup(buf + dp->prefix_len)) == 0) { + warnx("Insufficient memory resources - try later."); + sleepexit(1); + } + break; + } + } + } + fclose(fp); + } +} diff --git a/crypto/kerberosIV/appl/bsd/sysv_default.h b/crypto/kerberosIV/appl/bsd/sysv_default.h new file mode 100644 index 0000000..0056059 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/sysv_default.h @@ -0,0 +1,18 @@ +/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */ + +/* $Id: sysv_default.h,v 1.5 1996/10/27 23:51:14 assar Exp $ */ + +extern char *default_console; +extern char *default_altsh; +extern char *default_passreq; +extern char *default_timezone; +extern char *default_hz; +extern char *default_path; +extern char *default_supath; +extern char *default_ulimit; +extern char *default_timeout; +extern char *default_umask; +extern char *default_sleep; +extern char *default_maxtrys; + +void sysv_defaults(void); diff --git a/crypto/kerberosIV/appl/bsd/sysv_environ.c b/crypto/kerberosIV/appl/bsd/sysv_environ.c new file mode 100644 index 0000000..f5e782d --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/sysv_environ.c @@ -0,0 +1,192 @@ +/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */ + +#include "bsd_locl.h" + +RCSID("$Id: sysv_environ.c,v 1.21 1997/05/14 17:34:15 joda Exp $"); + +#ifdef HAVE_ULIMIT_H +#include <ulimit.h> +#endif + +#ifndef UL_SETFSIZE +#define UL_SETFSIZE 2 +#endif + +#include "sysv_default.h" + +/* + * Set + */ + +static void +read_etc_environment (void) +{ + FILE *f; + char buf[BUFSIZ]; + + f = fopen(_PATH_ETC_ENVIRONMENT, "r"); + if (f) { + char *val; + + while (fgets (buf, sizeof(buf), f) != NULL) { + if (buf[0] == '\n' || buf[0] == '#') + continue; + buf[strlen(buf) - 1] = '\0'; + val = strchr (buf, '='); + if (val == NULL) + continue; + *val = '\0'; + setenv(buf, val + 1, 1); + } + fclose (f); + } +} + + /* + * Environment variables that are preserved (but may still be overruled by + * other means). Only TERM and TZ appear to survive (SunOS 5.1). These are + * typically inherited from the ttymon process. + */ + +static struct preserved { + char *name; + char *value; +} preserved[] = { + {"TZ", 0}, + {"TERM", 0}, + {0}, +}; + + /* + * Environment variables that are not preserved and that cannot be specified + * via commandline or stdin. Except for the LD_xxx (runtime linker) stuff, + * the list applies to most SYSV systems. The manpage mentions only that + * SHELL and PATH are censored. HOME, LOGNAME and MAIL are always + * overwritten; they are in the list to make the censoring explicit. + */ + +static struct censored { + char *prefix; + int length; +} censored[] = { + {"SHELL=", sizeof("SHELL=") - 1}, + {"HOME=", sizeof("HOME=") - 1}, + {"LOGNAME=", sizeof("LOGNAME=") - 1}, + {"MAIL=", sizeof("MAIL=") - 1}, + {"CDPATH=", sizeof("CDPATH=") - 1}, + {"IFS=", sizeof("IFS=") - 1}, + {"PATH=", sizeof("PATH=") - 1}, + {"LD_", sizeof("LD_") - 1}, + {0}, +}; + +/* sysv_newenv - set up final environment after logging in */ + +void sysv_newenv(int argc, char **argv, struct passwd *pwd, + char *term, int pflag) +{ + unsigned umask_val; + long limit_val; + char buf[BUFSIZ]; + int count = 0; + struct censored *cp; + struct preserved *pp; + + /* Preserve a selection of the environment. */ + + for (pp = preserved; pp->name; pp++) + pp->value = getenv(pp->name); + + /* + * Note: it is a bad idea to assign a static array to the global environ + * variable. Reason is that putenv() can run into problems when it tries + * to realloc() the environment table. Instead, we just clear environ[0] + * and let putenv() work things out. + */ + + if (!pflag && environ) + environ[0] = 0; + + /* Restore preserved environment variables. */ + + for (pp = preserved; pp->name; pp++) + if (pp->value) + setenv(pp->name, pp->value, 1); + + /* The TERM definition from e.g. rlogind can override an existing one. */ + + if (term[0]) + setenv("TERM", term, 1); + + /* + * Environment definitions from the command line overrule existing ones, + * but can be overruled by definitions from stdin. Some variables are + * censored. + * + * Omission: we do not support environment definitions from stdin. + */ + +#define STREQN(x,y,l) (x[0] == y[0] && strncmp(x,y,l) == 0) + + while (argc && *argv) { + if (strchr(*argv, '=') == 0) { + snprintf(buf, sizeof(buf), "L%d", count++); + setenv(buf, *argv, 1); + } else { + for (cp = censored; cp->prefix; cp++) + if (STREQN(*argv, cp->prefix, cp->length)) + break; + if (cp->prefix == 0) + putenv(*argv); + } + argc--, argv++; + } + + /* PATH is always reset. */ + + setenv("PATH", pwd->pw_uid ? default_path : default_supath, 1); + + /* Undocumented: HOME, MAIL and LOGNAME are always reset (SunOS 5.1). */ + + setenv("HOME", pwd->pw_dir, 1); + { + char *sep = "/"; + if(KRB4_MAILDIR[strlen(KRB4_MAILDIR) - 1] == '/') + sep = ""; + k_concat(buf, sizeof(buf), KRB4_MAILDIR, sep, pwd->pw_name, NULL); + } + setenv("MAIL", buf, 1); + setenv("LOGNAME", pwd->pw_name, 1); + setenv("USER", pwd->pw_name, 1); + + /* + * Variables that may be set according to specifications in the defaults + * file. HZ and TZ are set only if they are still uninitialized. + * + * Extension: when ALTSHELL=YES, we set the SHELL variable even if it is + * /bin/sh. + */ + + if (strcasecmp(default_altsh, "YES") == 0) + setenv("SHELL", pwd->pw_shell, 1); + if (default_hz) + setenv("HZ", default_hz, 0); + if (default_timezone) + setenv("TZ", default_timezone, 0); + + /* Non-environment stuff. */ + + if (default_umask) { + if (sscanf(default_umask, "%o", &umask_val) == 1 && umask_val) + umask(umask_val); + } +#ifdef HAVE_ULIMIT + if (default_ulimit) { + if (sscanf(default_ulimit, "%ld", &limit_val) == 1 && limit_val) + if (ulimit(UL_SETFSIZE, limit_val) < 0) + warn ("ulimit(UL_SETFSIZE, %ld)", limit_val); + } +#endif + read_etc_environment(); +} + diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.c b/crypto/kerberosIV/appl/bsd/sysv_shadow.c new file mode 100644 index 0000000..6839441 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.c @@ -0,0 +1,45 @@ +/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */ + +#include "bsd_locl.h" + +RCSID("$Id: sysv_shadow.c,v 1.7 1997/03/23 04:56:05 assar Exp $"); + +#ifdef SYSV_SHADOW + +#include <sysv_shadow.h> + +/* sysv_expire - check account and password expiration times */ + +int +sysv_expire(struct spwd *spwd) +{ + long today; + + tzset(); + today = time(0); + + if (spwd->sp_expire > 0) { + if (today > spwd->sp_expire) { + printf("Your account has expired.\n"); + sleepexit(1); + } else if (spwd->sp_expire - today < 14) { + printf("Your account will expire in %d days.\n", + (int)(spwd->sp_expire - today)); + return (0); + } + } + if (spwd->sp_max > 0) { + if (today > (spwd->sp_lstchg + spwd->sp_max)) { + printf("Your password has expired. Choose a new one.\n"); + return (1); + } else if (spwd->sp_warn > 0 + && (today > (spwd->sp_lstchg + spwd->sp_max - spwd->sp_warn))) { + printf("Your password will expire in %d days.\n", + (int)(spwd->sp_lstchg + spwd->sp_max - today)); + return (0); + } + } + return (0); +} + +#endif /* SYSV_SHADOW */ diff --git a/crypto/kerberosIV/appl/bsd/sysv_shadow.h b/crypto/kerberosIV/appl/bsd/sysv_shadow.h new file mode 100644 index 0000000..4f07b49 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/sysv_shadow.h @@ -0,0 +1,5 @@ +/* $Id: sysv_shadow.h,v 1.6 1997/03/23 04:55:51 assar Exp $ */ + +#include <shadow.h> + +extern sysv_expire(struct spwd *); diff --git a/crypto/kerberosIV/appl/bsd/tty.c b/crypto/kerberosIV/appl/bsd/tty.c new file mode 100644 index 0000000..3192426 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/tty.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "bsd_locl.h" + +RCSID("$Id: tty.c,v 1.2 1997/05/25 01:14:22 assar Exp $"); + +/* + * Clean the tty name. Return a pointer to the cleaned version. + */ + +char * +clean_ttyname (char *tty) +{ + char *res = tty; + + if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0) + res += strlen(_PATH_DEV); + if (strncmp (res, "pty/", 4) == 0) + res += 4; + if (strncmp (res, "ptym/", 5) == 0) + res += 5; + return res; +} + +/* + * Generate a name usable as an `ut_id', typically without `tty'. + */ + +char * +make_id (char *tty) +{ + char *res = tty; + + if (strncmp (res, "pts/", 4) == 0) + res += 4; + if (strncmp (res, "tty", 3) == 0) + res += 3; + return res; +} diff --git a/crypto/kerberosIV/appl/bsd/utmp_login.c b/crypto/kerberosIV/appl/bsd/utmp_login.c new file mode 100644 index 0000000..da3f96a --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/utmp_login.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "bsd_locl.h" + +RCSID("$Id: utmp_login.c,v 1.13 1997/05/20 13:46:21 assar Exp $"); + +void +prepare_utmp (struct utmp *utmp, char *tty, char *username, char *hostname) +{ + char *ttyx = clean_ttyname (tty); + + memset(utmp, 0, sizeof(*utmp)); + utmp->ut_time = time(NULL); + strncpy(utmp->ut_line, ttyx, sizeof(utmp->ut_line)); + strncpy(utmp->ut_name, username, sizeof(utmp->ut_name)); + +# ifdef HAVE_UT_USER + strncpy(utmp->ut_user, username, sizeof(utmp->ut_user)); +# endif + +# ifdef HAVE_UT_ADDR + if (hostname[0]) { + struct hostent *he; + if ((he = gethostbyname(hostname))) + memcpy(&utmp->ut_addr, he->h_addr_list[0], + sizeof(utmp->ut_addr)); + } +# endif + +# ifdef HAVE_UT_HOST + strncpy(utmp->ut_host, hostname, sizeof(utmp->ut_host)); +# endif + +# ifdef HAVE_UT_TYPE + utmp->ut_type = USER_PROCESS; +# endif + +# ifdef HAVE_UT_PID + utmp->ut_pid = getpid(); +# endif + +# ifdef HAVE_UT_ID + strncpy(utmp->ut_id, make_id(ttyx), sizeof(utmp->ut_id)); +# endif +} + +#ifdef HAVE_UTMPX_H +void utmp_login(char *tty, char *username, char *hostname) { return; } +#else + +/* update utmp and wtmp - the BSD way */ + +void utmp_login(char *tty, char *username, char *hostname) +{ + struct utmp utmp; + int fd; + + prepare_utmp (&utmp, tty, username, hostname); + +#ifdef HAVE_SETUTENT + utmpname(_PATH_UTMP); + setutent(); + pututline(&utmp); + endutent(); +#else + +#ifdef HAVE_TTYSLOT + { + int ttyno; + ttyno = ttyslot(); + if (ttyno > 0 && (fd = open(_PATH_UTMP, O_WRONLY, 0)) >= 0) { + lseek(fd, (long)(ttyno * sizeof(struct utmp)), SEEK_SET); + write(fd, &utmp, sizeof(struct utmp)); + close(fd); + } + } +#endif /* HAVE_TTYSLOT */ +#endif /* HAVE_SETUTENT */ + + if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) { + write(fd, &utmp, sizeof(struct utmp)); + close(fd); + } +} +#endif /* !HAVE_UTMPX_H */ diff --git a/crypto/kerberosIV/appl/bsd/utmpx_login.c b/crypto/kerberosIV/appl/bsd/utmpx_login.c new file mode 100644 index 0000000..005eca5 --- /dev/null +++ b/crypto/kerberosIV/appl/bsd/utmpx_login.c @@ -0,0 +1,88 @@ +/* Author: Wietse Venema <wietse@wzv.win.tue.nl> */ + +#include "bsd_locl.h" + +RCSID("$Id: utmpx_login.c,v 1.20 1997/06/01 03:13:15 assar Exp $"); + +/* utmpx_login - update utmp and wtmp after login */ + +#ifndef HAVE_UTMPX_H +int utmpx_login(char *line, char *user, char *host) { return 0; } +#else + +static void +utmpx_update(struct utmpx *ut, char *line, char *user, char *host) +{ + struct timeval tmp; + char *clean_tty = clean_ttyname(line); + + strncpy(ut->ut_line, clean_tty, sizeof(ut->ut_line)); +#ifdef HAVE_UT_ID + strncpy(ut->ut_id, make_id(clean_tty), sizeof(ut->ut_id)); +#endif + strncpy(ut->ut_user, user, sizeof(ut->ut_user)); + strncpy(ut->ut_host, host, sizeof(ut->ut_host)); +#ifdef HAVE_UT_SYSLEN + ut->ut_syslen = strlen(host) + 1; + if (ut->ut_syslen > sizeof(ut->ut_host)) + ut->ut_syslen = sizeof(ut->ut_host); +#endif + ut->ut_type = USER_PROCESS; + gettimeofday (&tmp, 0); + ut->ut_tv.tv_sec = tmp.tv_sec; + ut->ut_tv.tv_usec = tmp.tv_usec; + pututxline(ut); +#ifdef WTMPX_FILE + updwtmpx(WTMPX_FILE, ut); +#elif defined(WTMP_FILE) + { + struct utmp utmp; + int fd; + + prepare_utmp (&utmp, line, user, host); + if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) { + write(fd, &utmp, sizeof(struct utmp)); + close(fd); + } + } +#endif +} + +int +utmpx_login(char *line, char *user, char *host) +{ + struct utmpx *ut; + pid_t mypid = getpid(); + int ret = (-1); + + /* + * SYSV4 ttymon and login use tty port names with the "/dev/" prefix + * stripped off. Rlogind and telnetd, on the other hand, make utmpx + * entries with device names like /dev/pts/nnn. We therefore cannot use + * getutxline(). Return nonzero if no utmp entry was found with our own + * process ID for a login or user process. + */ + + while ((ut = getutxent())) { + /* Try to find a reusable entry */ + if (ut->ut_pid == mypid + && ( ut->ut_type == INIT_PROCESS + || ut->ut_type == LOGIN_PROCESS + || ut->ut_type == USER_PROCESS)) { + utmpx_update(ut, line, user, host); + ret = 0; + break; + } + } + if (ret == -1) { + /* Grow utmpx file by one record. */ + struct utmpx newut; + memset(&newut, 0, sizeof(newut)); + newut.ut_pid = mypid; + utmpx_update(&newut, line, user, host); + ret = 0; + } + endutxent(); + return (ret); +} +#endif /* HAVE_UTMPX_H */ diff --git a/crypto/kerberosIV/appl/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/Makefile.in new file mode 100644 index 0000000..6d0c420 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/Makefile.in @@ -0,0 +1,41 @@ +# $Id: Makefile.in,v 1.9 1997/03/23 13:03:54 assar Exp $ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +SHELL = /bin/sh + +@SET_MAKE@ + +CC = @CC@ +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ + +INSTALL = @INSTALL@ + +prefix = @prefix@ + +SUBDIRS=common ftp ftpd + +all: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) all); done + +install: all + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) install); done + +uninstall: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) uninstall); done + +clean cleandir: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) clean); done + +distclean: + for i in $(SUBDIRS); \ + do (cd $$i && $(MAKE) $(MFLAGS) distclean); done + rm -f Makefile *~ diff --git a/crypto/kerberosIV/appl/ftp/common/Makefile.in b/crypto/kerberosIV/appl/ftp/common/Makefile.in new file mode 100644 index 0000000..9ce1aa5 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/Makefile.in @@ -0,0 +1,52 @@ +# $Id: Makefile.in,v 1.17 1997/05/18 20:00:06 assar Exp $ + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ + +INSTALL = @INSTALL@ + +prefix = @prefix@ + +SOURCES = base64.c glob.c sockbuf.c buffer.c +OBJECTS = $(libcommon_OBJS) + +libcommon_OBJS = base64.o glob.o sockbuf.o buffer.o + +LIBNAME = $(LIBPREFIX)common +LIBEXT = a +LIBPREFIX = @LIBPREFIX@ +LIB = $(LIBNAME).$(LIBEXT) + +all: $(LIB) + +.c.o: + $(CC) -c $(CFLAGS) -I$(srcdir) -I../../../include $(DEFS) $< + +$(LIB): $(libcommon_OBJS) + rm -f $@ + ar cr $@ $(libcommon_OBJS) + -$(RANLIB) $@ + +install: + +uninstall: + +TAGS: $(SOURCES) + etags $(SOURCES) + +clean cleandir: + rm -f *~ *.o libcommon.a core \#* + +distclean: + rm -f Makefile + +$(OBJECTS): ../../../include/config.h diff --git a/crypto/kerberosIV/appl/ftp/common/base64.c b/crypto/kerberosIV/appl/ftp/common/base64.c new file mode 100644 index 0000000..648f32d --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/base64.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +RCSID("$Id: base64.c,v 1.6 1997/05/30 17:24:06 assar Exp $"); +#endif +#include <stdlib.h> +#include <string.h> +#include "base64.h" + +static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static int pos(char c) +{ + char *p; + for(p = base64; *p; p++) + if(*p == c) + return p - base64; + return -1; +} + +int base64_encode(const void *data, int size, char **str) +{ + char *s, *p; + int i; + int c; + unsigned char *q; + + p = s = (char*)malloc(size*4/3+4); + q = (unsigned char*)data; + i=0; + for(i = 0; i < size;){ + c=q[i++]; + c*=256; + if(i < size) + c+=q[i]; + i++; + c*=256; + if(i < size) + c+=q[i]; + i++; + p[0]=base64[(c&0x00fc0000) >> 18]; + p[1]=base64[(c&0x0003f000) >> 12]; + p[2]=base64[(c&0x00000fc0) >> 6]; + p[3]=base64[(c&0x0000003f) >> 0]; + if(i > size) + p[3]='='; + if(i > size+1) + p[2]='='; + p+=4; + } + *p=0; + *str = s; + return strlen(s); +} + +int base64_decode(const char *str, void *data) +{ + const char *p; + unsigned char *q; + int c; + int x; + int done = 0; + q=(unsigned char*)data; + for(p=str; *p && !done; p+=4){ + x = pos(p[0]); + if(x >= 0) + c = x; + else{ + done = 3; + break; + } + c*=64; + + x = pos(p[1]); + if(x >= 0) + c += x; + else + return -1; + c*=64; + + if(p[2] == '=') + done++; + else{ + x = pos(p[2]); + if(x >= 0) + c += x; + else + return -1; + } + c*=64; + + if(p[3] == '=') + done++; + else{ + if(done) + return -1; + x = pos(p[3]); + if(x >= 0) + c += x; + else + return -1; + } + if(done < 3) + *q++=(c&0x00ff0000)>>16; + + if(done < 2) + *q++=(c&0x0000ff00)>>8; + if(done < 1) + *q++=(c&0x000000ff)>>0; + } + return q - (unsigned char*)data; +} diff --git a/crypto/kerberosIV/appl/ftp/common/base64.h b/crypto/kerberosIV/appl/ftp/common/base64.h new file mode 100644 index 0000000..fe799a2 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/base64.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: base64.h,v 1.5 1997/04/01 08:17:19 joda Exp $ */ + +#ifndef _BASE64_H_ +#define _BASE64_H_ + +int base64_encode(const void *data, int size, char **str); +int base64_decode(const char *str, void *data); + +#endif diff --git a/crypto/kerberosIV/appl/ftp/common/buffer.c b/crypto/kerberosIV/appl/ftp/common/buffer.c new file mode 100644 index 0000000..5b7829a --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/buffer.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "common.h" +#include <stdio.h> +#include "roken.h" + +RCSID("$Id: buffer.c,v 1.1 1997/05/18 19:59:24 assar Exp $"); + +/* + * Allocate a buffer enough to handle st->st_blksize, if + * there is such a field, otherwise BUFSIZ. + */ + +void * +alloc_buffer (void *oldbuf, size_t *sz, struct stat *st) +{ + size_t new_sz; + + new_sz = BUFSIZ; +#ifdef HAVE_ST_BLKSIZE + if (st) + new_sz = max(BUFSIZ, st->st_blksize); +#endif + if(new_sz > *sz) { + if (oldbuf) + free (oldbuf); + oldbuf = malloc (new_sz); + if (oldbuf == NULL) { + warn ("malloc"); + *sz = 0; + return NULL; + } + *sz = new_sz; + } + return oldbuf; +} + diff --git a/crypto/kerberosIV/appl/ftp/common/common.h b/crypto/kerberosIV/appl/ftp/common/common.h new file mode 100644 index 0000000..4ec3149 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/common.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: common.h,v 1.9 1997/05/18 19:59:58 assar Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "base64.h" + +void set_buffer_size(int, int); + +#include <stdlib.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +void *alloc_buffer (void *oldbuf, size_t *sz, struct stat *st); + +#endif /* __COMMON_H__ */ diff --git a/crypto/kerberosIV/appl/ftp/common/glob.c b/crypto/kerberosIV/appl/ftp/common/glob.c new file mode 100644 index 0000000..8f19d7c --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/glob.c @@ -0,0 +1,835 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * glob(3) -- a superset of the one defined in POSIX 1003.2. + * + * The [!...] convention to negate a range is supported (SysV, Posix, ksh). + * + * Optional extra services, controlled by flags not defined by POSIX: + * + * GLOB_QUOTE: + * Escaping convention: \ inhibits any special meaning the following + * character might have (except \ at end of string is retained). + * GLOB_MAGCHAR: + * Set in gl_flags if pattern contained a globbing character. + * GLOB_NOMAGIC: + * Same as GLOB_NOCHECK, but it will only append pattern if it did + * not contain any magic characters. [Used in csh style globbing] + * GLOB_ALTDIRFUNC: + * Use alternately specified directory access functions. + * GLOB_TILDE: + * expand ~user/foo to the /home/dir/of/user/foo + * GLOB_BRACE: + * expand {1,2}{a,b} to 1a 1b 2a 2b + * gl_matchc: + * Number of matches in the current invocation of glob. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#include <ctype.h> +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif +#include <errno.h> +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "glob.h" +#include "roken.h" + +#define CHAR_DOLLAR '$' +#define CHAR_DOT '.' +#define CHAR_EOS '\0' +#define CHAR_LBRACKET '[' +#define CHAR_NOT '!' +#define CHAR_QUESTION '?' +#define CHAR_QUOTE '\\' +#define CHAR_RANGE '-' +#define CHAR_RBRACKET ']' +#define CHAR_SEP '/' +#define CHAR_STAR '*' +#define CHAR_TILDE '~' +#define CHAR_UNDERSCORE '_' +#define CHAR_LBRACE '{' +#define CHAR_RBRACE '}' +#define CHAR_SLASH '/' +#define CHAR_COMMA ',' + +#ifndef DEBUG + +#define M_QUOTE 0x8000 +#define M_PROTECT 0x4000 +#define M_MASK 0xffff +#define M_ASCII 0x00ff + +typedef u_short Char; + +#else + +#define M_QUOTE 0x80 +#define M_PROTECT 0x40 +#define M_MASK 0xff +#define M_ASCII 0x7f + +typedef char Char; + +#endif + + +#define CHAR(c) ((Char)((c)&M_ASCII)) +#define META(c) ((Char)((c)|M_QUOTE)) +#define M_ALL META('*') +#define M_END META(']') +#define M_NOT META('!') +#define M_ONE META('?') +#define M_RNG META('-') +#define M_SET META('[') +#define ismeta(c) (((c)&M_QUOTE) != 0) + + +static int compare (const void *, const void *); +static void g_Ctoc (const Char *, char *); +static int g_lstat (Char *, struct stat *, glob_t *); +static DIR *g_opendir (Char *, glob_t *); +static Char *g_strchr (Char *, int); +#ifdef notdef +static Char *g_strcat (Char *, const Char *); +#endif +static int g_stat (Char *, struct stat *, glob_t *); +static int glob0 (const Char *, glob_t *); +static int glob1 (Char *, glob_t *); +static int glob2 (Char *, Char *, Char *, glob_t *); +static int glob3 (Char *, Char *, Char *, Char *, glob_t *); +static int globextend (const Char *, glob_t *); +static const Char * globtilde (const Char *, Char *, glob_t *); +static int globexp1 (const Char *, glob_t *); +static int globexp2 (const Char *, const Char *, glob_t *, int *); +static int match (Char *, Char *, Char *); +#ifdef DEBUG +static void qprintf (const char *, Char *); +#endif + +int +glob(const char *pattern, + int flags, + int (*errfunc)(const char *, int), + glob_t *pglob) +{ + const u_char *patnext; + int c; + Char *bufnext, *bufend, patbuf[MaxPathLen+1]; + + patnext = (u_char *) pattern; + if (!(flags & GLOB_APPEND)) { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_offs = 0; + } + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_errfunc = errfunc; + pglob->gl_matchc = 0; + + bufnext = patbuf; + bufend = bufnext + MaxPathLen; + if (flags & GLOB_QUOTE) { + /* Protect the quoted characters. */ + while (bufnext < bufend && (c = *patnext++) != CHAR_EOS) + if (c == CHAR_QUOTE) { + if ((c = *patnext++) == CHAR_EOS) { + c = CHAR_QUOTE; + --patnext; + } + *bufnext++ = c | M_PROTECT; + } + else + *bufnext++ = c; + } + else + while (bufnext < bufend && (c = *patnext++) != CHAR_EOS) + *bufnext++ = c; + *bufnext = CHAR_EOS; + + if (flags & GLOB_BRACE) + return globexp1(patbuf, pglob); + else + return glob0(patbuf, pglob); +} + +/* + * Expand recursively a glob {} pattern. When there is no more expansion + * invoke the standard globbing routine to glob the rest of the magic + * characters + */ +static int globexp1(const Char *pattern, glob_t *pglob) +{ + const Char* ptr = pattern; + int rv; + + /* Protect a single {}, for find(1), like csh */ + if (pattern[0] == CHAR_LBRACE && pattern[1] == CHAR_RBRACE && pattern[2] == CHAR_EOS) + return glob0(pattern, pglob); + + while ((ptr = (const Char *) g_strchr((Char *) ptr, CHAR_LBRACE)) != NULL) + if (!globexp2(ptr, pattern, pglob, &rv)) + return rv; + + return glob0(pattern, pglob); +} + + +/* + * Recursive brace globbing helper. Tries to expand a single brace. + * If it succeeds then it invokes globexp1 with the new pattern. + * If it fails then it tries to glob the rest of the pattern and returns. + */ +static int globexp2(const Char *ptr, const Char *pattern, + glob_t *pglob, int *rv) +{ + int i; + Char *lm, *ls; + const Char *pe, *pm, *pl; + Char patbuf[MaxPathLen + 1]; + + /* copy part up to the brace */ + for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) + continue; + ls = lm; + + /* Find the balanced brace */ + for (i = 0, pe = ++ptr; *pe; pe++) + if (*pe == CHAR_LBRACKET) { + /* Ignore everything between [] */ + for (pm = pe++; *pe != CHAR_RBRACKET && *pe != CHAR_EOS; pe++) + continue; + if (*pe == CHAR_EOS) { + /* + * We could not find a matching CHAR_RBRACKET. + * Ignore and just look for CHAR_RBRACE + */ + pe = pm; + } + } + else if (*pe == CHAR_LBRACE) + i++; + else if (*pe == CHAR_RBRACE) { + if (i == 0) + break; + i--; + } + + /* Non matching braces; just glob the pattern */ + if (i != 0 || *pe == CHAR_EOS) { + *rv = glob0(patbuf, pglob); + return 0; + } + + for (i = 0, pl = pm = ptr; pm <= pe; pm++) + switch (*pm) { + case CHAR_LBRACKET: + /* Ignore everything between [] */ + for (pl = pm++; *pm != CHAR_RBRACKET && *pm != CHAR_EOS; pm++) + continue; + if (*pm == CHAR_EOS) { + /* + * We could not find a matching CHAR_RBRACKET. + * Ignore and just look for CHAR_RBRACE + */ + pm = pl; + } + break; + + case CHAR_LBRACE: + i++; + break; + + case CHAR_RBRACE: + if (i) { + i--; + break; + } + /* FALLTHROUGH */ + case CHAR_COMMA: + if (i && *pm == CHAR_COMMA) + break; + else { + /* Append the current string */ + for (lm = ls; (pl < pm); *lm++ = *pl++) + continue; + /* + * Append the rest of the pattern after the + * closing brace + */ + for (pl = pe + 1; (*lm++ = *pl++) != CHAR_EOS;) + continue; + + /* Expand the current pattern */ +#ifdef DEBUG + qprintf("globexp2:", patbuf); +#endif + *rv = globexp1(patbuf, pglob); + + /* move after the comma, to the next string */ + pl = pm + 1; + } + break; + + default: + break; + } + *rv = 0; + return 0; +} + + + +/* + * expand tilde from the passwd file. + */ +static const Char * +globtilde(const Char *pattern, Char *patbuf, glob_t *pglob) +{ + struct passwd *pwd; + char *h; + const Char *p; + Char *b; + + if (*pattern != CHAR_TILDE || !(pglob->gl_flags & GLOB_TILDE)) + return pattern; + + /* Copy up to the end of the string or / */ + for (p = pattern + 1, h = (char *) patbuf; *p && *p != CHAR_SLASH; + *h++ = *p++) + continue; + + *h = CHAR_EOS; + + if (((char *) patbuf)[0] == CHAR_EOS) { + /* + * handle a plain ~ or ~/ by expanding $HOME + * first and then trying the password file + */ + if ((h = getenv("HOME")) == NULL) { + if ((pwd = k_getpwuid(getuid())) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + } + else { + /* + * Expand a ~user + */ + if ((pwd = k_getpwnam((char*) patbuf)) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + + /* Copy the home directory */ + for (b = patbuf; *h; *b++ = *h++) + continue; + + /* Append the rest of the pattern */ + while ((*b++ = *p++) != CHAR_EOS) + continue; + + return patbuf; +} + + +/* + * The main glob() routine: compiles the pattern (optionally processing + * quotes), calls glob1() to do the real pattern matching, and finally + * sorts the list (unless unsorted operation is requested). Returns 0 + * if things went well, nonzero if errors occurred. It is not an error + * to find no matches. + */ +static int +glob0(const Char *pattern, glob_t *pglob) +{ + const Char *qpatnext; + int c, err, oldpathc; + Char *bufnext, patbuf[MaxPathLen+1]; + + qpatnext = globtilde(pattern, patbuf, pglob); + oldpathc = pglob->gl_pathc; + bufnext = patbuf; + + /* We don't need to check for buffer overflow any more. */ + while ((c = *qpatnext++) != CHAR_EOS) { + switch (c) { + case CHAR_LBRACKET: + c = *qpatnext; + if (c == CHAR_NOT) + ++qpatnext; + if (*qpatnext == CHAR_EOS || + g_strchr((Char *) qpatnext+1, CHAR_RBRACKET) == NULL) { + *bufnext++ = CHAR_LBRACKET; + if (c == CHAR_NOT) + --qpatnext; + break; + } + *bufnext++ = M_SET; + if (c == CHAR_NOT) + *bufnext++ = M_NOT; + c = *qpatnext++; + do { + *bufnext++ = CHAR(c); + if (*qpatnext == CHAR_RANGE && + (c = qpatnext[1]) != CHAR_RBRACKET) { + *bufnext++ = M_RNG; + *bufnext++ = CHAR(c); + qpatnext += 2; + } + } while ((c = *qpatnext++) != CHAR_RBRACKET); + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_END; + break; + case CHAR_QUESTION: + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_ONE; + break; + case CHAR_STAR: + pglob->gl_flags |= GLOB_MAGCHAR; + /* collapse adjacent stars to one, + * to avoid exponential behavior + */ + if (bufnext == patbuf || bufnext[-1] != M_ALL) + *bufnext++ = M_ALL; + break; + default: + *bufnext++ = CHAR(c); + break; + } + } + *bufnext = CHAR_EOS; +#ifdef DEBUG + qprintf("glob0:", patbuf); +#endif + + if ((err = glob1(patbuf, pglob)) != 0) + return(err); + + /* + * If there was no match we are going to append the pattern + * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified + * and the pattern did not contain any magic characters + * GLOB_NOMAGIC is there just for compatibility with csh. + */ + if (pglob->gl_pathc == oldpathc && + ((pglob->gl_flags & GLOB_NOCHECK) || + ((pglob->gl_flags & GLOB_NOMAGIC) && + !(pglob->gl_flags & GLOB_MAGCHAR)))) + return(globextend(pattern, pglob)); + else if (!(pglob->gl_flags & GLOB_NOSORT)) + qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, + pglob->gl_pathc - oldpathc, sizeof(char *), compare); + return(0); +} + +static int +compare(const void *p, const void *q) +{ + return(strcmp(*(char **)p, *(char **)q)); +} + +static int +glob1(Char *pattern, glob_t *pglob) +{ + Char pathbuf[MaxPathLen+1]; + + /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ + if (*pattern == CHAR_EOS) + return(0); + return(glob2(pathbuf, pathbuf, pattern, pglob)); +} + +/* + * The functions glob2 and glob3 are mutually recursive; there is one level + * of recursion for each segment in the pattern that contains one or more + * meta characters. + */ + +#ifndef S_ISLNK +#if defined(S_IFLNK) && defined(S_IFMT) +#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#else +#define S_ISLNK(mode) 0 +#endif +#endif + +static int +glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob) +{ + struct stat sb; + Char *p, *q; + int anymeta; + + /* + * Loop over pattern segments until end of pattern or until + * segment with meta character found. + */ + for (anymeta = 0;;) { + if (*pattern == CHAR_EOS) { /* End of pattern? */ + *pathend = CHAR_EOS; + if (g_lstat(pathbuf, &sb, pglob)) + return(0); + + if (((pglob->gl_flags & GLOB_MARK) && + pathend[-1] != CHAR_SEP) && (S_ISDIR(sb.st_mode) + || (S_ISLNK(sb.st_mode) && + (g_stat(pathbuf, &sb, pglob) == 0) && + S_ISDIR(sb.st_mode)))) { + *pathend++ = CHAR_SEP; + *pathend = CHAR_EOS; + } + ++pglob->gl_matchc; + return(globextend(pathbuf, pglob)); + } + + /* Find end of next segment, copy tentatively to pathend. */ + q = pathend; + p = pattern; + while (*p != CHAR_EOS && *p != CHAR_SEP) { + if (ismeta(*p)) + anymeta = 1; + *q++ = *p++; + } + + if (!anymeta) { /* No expansion, do next segment. */ + pathend = q; + pattern = p; + while (*pattern == CHAR_SEP) + *pathend++ = *pattern++; + } else /* Need expansion, recurse. */ + return(glob3(pathbuf, pathend, pattern, p, pglob)); + } + /* CHAR_NOTREACHED */ +} + +static int +glob3(Char *pathbuf, Char *pathend, Char *pattern, Char *restpattern, + glob_t *pglob) +{ + struct dirent *dp; + DIR *dirp; + int err; + char buf[MaxPathLen]; + + /* + * The readdirfunc declaration can't be prototyped, because it is + * assigned, below, to two functions which are prototyped in glob.h + * and dirent.h as taking pointers to differently typed opaque + * structures. + */ + struct dirent *(*readdirfunc)(void *); + + *pathend = CHAR_EOS; + errno = 0; + + if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { + /* TODO: don't call for ENOENT or ENOTDIR? */ + if (pglob->gl_errfunc) { + g_Ctoc(pathbuf, buf); + if (pglob->gl_errfunc(buf, errno) || + pglob->gl_flags & GLOB_ERR) + return (GLOB_ABEND); + } + return(0); + } + + err = 0; + + /* Search directory for matching names. */ + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + readdirfunc = pglob->gl_readdir; + else + readdirfunc = (struct dirent *(*)(void *))readdir; + while ((dp = (*readdirfunc)(dirp))) { + u_char *sc; + Char *dc; + + /* Initial CHAR_DOT must be matched literally. */ + if (dp->d_name[0] == CHAR_DOT && *pattern != CHAR_DOT) + continue; + for (sc = (u_char *) dp->d_name, dc = pathend; + (*dc++ = *sc++) != CHAR_EOS;) + continue; + if (!match(pathend, pattern, restpattern)) { + *pathend = CHAR_EOS; + continue; + } + err = glob2(pathbuf, --dc, restpattern, pglob); + if (err) + break; + } + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir)(dirp); + else + closedir(dirp); + return(err); +} + + +/* + * Extend the gl_pathv member of a glob_t structure to accomodate a new item, + * add the new item, and update gl_pathc. + * + * This assumes the BSD realloc, which only copies the block when its size + * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic + * behavior. + * + * Return 0 if new item added, error code if memory couldn't be allocated. + * + * Invariant of the glob_t structure: + * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and + * gl_pathv points to (gl_offs + gl_pathc + 1) items. + */ +static int +globextend(const Char *path, glob_t *pglob) +{ + char **pathv; + int i; + u_int newsize; + char *copy; + const Char *p; + + newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); + pathv = pglob->gl_pathv ? + realloc(pglob->gl_pathv, newsize) : + malloc(newsize); + if (pathv == NULL) + return(GLOB_NOSPACE); + + if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { + /* first time around -- clear initial gl_offs items */ + pathv += pglob->gl_offs; + for (i = pglob->gl_offs; --i >= 0; ) + *--pathv = NULL; + } + pglob->gl_pathv = pathv; + + for (p = path; *p++;) + continue; + if ((copy = malloc(p - path)) != NULL) { + g_Ctoc(path, copy); + pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; + } + pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + return(copy == NULL ? GLOB_NOSPACE : 0); +} + + +/* + * pattern matching function for filenames. Each occurrence of the * + * pattern causes a recursion level. + */ +static int +match(Char *name, Char *pat, Char *patend) +{ + int ok, negate_range; + Char c, k; + + while (pat < patend) { + c = *pat++; + switch (c & M_MASK) { + case M_ALL: + if (pat == patend) + return(1); + do + if (match(name, pat, patend)) + return(1); + while (*name++ != CHAR_EOS); + return(0); + case M_ONE: + if (*name++ == CHAR_EOS) + return(0); + break; + case M_SET: + ok = 0; + if ((k = *name++) == CHAR_EOS) + return(0); + if ((negate_range = ((*pat & M_MASK) == M_NOT)) != CHAR_EOS) + ++pat; + while (((c = *pat++) & M_MASK) != M_END) + if ((*pat & M_MASK) == M_RNG) { + if (c <= k && k <= pat[1]) + ok = 1; + pat += 2; + } else if (c == k) + ok = 1; + if (ok == negate_range) + return(0); + break; + default: + if (*name++ != c) + return(0); + break; + } + } + return(*name == CHAR_EOS); +} + +/* Free allocated data belonging to a glob_t structure. */ +void +globfree(glob_t *pglob) +{ + int i; + char **pp; + + if (pglob->gl_pathv != NULL) { + pp = pglob->gl_pathv + pglob->gl_offs; + for (i = pglob->gl_pathc; i--; ++pp) + if (*pp) + free(*pp); + free(pglob->gl_pathv); + } +} + +static DIR * +g_opendir(Char *str, glob_t *pglob) +{ + char buf[MaxPathLen]; + + if (!*str) + strcpy(buf, "."); + else + g_Ctoc(str, buf); + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_opendir)(buf)); + + return(opendir(buf)); +} + +static int +g_lstat(Char *fn, struct stat *sb, glob_t *pglob) +{ + char buf[MaxPathLen]; + + g_Ctoc(fn, buf); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_lstat)(buf, sb)); + return(lstat(buf, sb)); +} + +static int +g_stat(Char *fn, struct stat *sb, glob_t *pglob) +{ + char buf[MaxPathLen]; + + g_Ctoc(fn, buf); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_stat)(buf, sb)); + return(stat(buf, sb)); +} + +static Char * +g_strchr(Char *str, int ch) +{ + do { + if (*str == ch) + return (str); + } while (*str++); + return (NULL); +} + +#ifdef notdef +static Char * +g_strcat(Char *dst, const Char *src) +{ + Char *sdst = dst; + + while (*dst++) + continue; + --dst; + while((*dst++ = *src++) != CHAR_EOS) + continue; + + return (sdst); +} +#endif + +static void +g_Ctoc(const Char *str, char *buf) +{ + char *dc; + + for (dc = buf; (*dc++ = *str++) != CHAR_EOS;) + continue; +} + +#ifdef DEBUG +static void +qprintf(const Char *str, Char *s) +{ + Char *p; + + printf("%s:\n", str); + for (p = s; *p; p++) + printf("%c", CHAR(*p)); + printf("\n"); + for (p = s; *p; p++) + printf("%c", *p & M_PROTECT ? '"' : ' '); + printf("\n"); + for (p = s; *p; p++) + printf("%c", ismeta(*p) ? '_' : ' '); + printf("\n"); +} +#endif diff --git a/crypto/kerberosIV/appl/ftp/common/glob.h b/crypto/kerberosIV/appl/ftp/common/glob.h new file mode 100644 index 0000000..bece48a --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/glob.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)glob.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _GLOB_H_ +#define _GLOB_H_ + +struct stat; +typedef struct { + int gl_pathc; /* Count of total paths so far. */ + int gl_matchc; /* Count of paths matching pattern. */ + int gl_offs; /* Reserved at beginning of gl_pathv. */ + int gl_flags; /* Copy of flags parameter to glob. */ + char **gl_pathv; /* List of paths matching pattern. */ + /* Copy of errfunc parameter to glob. */ + int (*gl_errfunc) (const char *, int); + + /* + * Alternate filesystem access methods for glob; replacement + * versions of closedir(3), readdir(3), opendir(3), stat(2) + * and lstat(2). + */ + void (*gl_closedir) (void *); + struct dirent *(*gl_readdir) (void *); + void *(*gl_opendir) (const char *); + int (*gl_lstat) (const char *, struct stat *); + int (*gl_stat) (const char *, struct stat *); +} glob_t; + +#define GLOB_APPEND 0x0001 /* Append to output from previous call. */ +#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ +#define GLOB_ERR 0x0004 /* Return on error. */ +#define GLOB_MARK 0x0008 /* Append / to matching directories. */ +#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ +#define GLOB_NOSORT 0x0020 /* Don't sort. */ + +#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ +#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ +#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ +#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ +#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ +#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ + +#define GLOB_NOSPACE (-1) /* Malloc call failed. */ +#define GLOB_ABEND (-2) /* Unignored error. */ + +int glob (const char *, int, int (*)(const char *, int), glob_t *); +void globfree (glob_t *); + +#endif /* !_GLOB_H_ */ diff --git a/crypto/kerberosIV/appl/ftp/common/sockbuf.c b/crypto/kerberosIV/appl/ftp/common/sockbuf.c new file mode 100644 index 0000000..ab8c293 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/sockbuf.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "common.h" +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +RCSID("$Id: sockbuf.c,v 1.2 1997/05/11 10:01:48 assar Exp $"); + +void +set_buffer_size(int fd, int read) +{ +#if defined(SO_RCVBUF) && defined(SO_SNDBUF) && defined(HAVE_SETSOCKOPT) + size_t size = 4194304; + while(size >= 131072 && + setsockopt(fd, SOL_SOCKET, read ? SO_RCVBUF : SO_SNDBUF, + (void *)&size, sizeof(size)) < 0) + size /= 2; +#endif +} + + diff --git a/crypto/kerberosIV/appl/ftp/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in new file mode 100644 index 0000000..62bde3b --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in @@ -0,0 +1,76 @@ +# +# $Id: Makefile.in,v 1.24 1997/03/23 13:03:55 assar Exp $ +# + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +topdir = ../../.. + +CC = @CC@ +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I$(topdir) -I$(top_srcdir) -I$(topdir)/include -I$(top_srcdir)/include -I$(srcdir)/../common @INCLUDE_readline@ +LD_FLAGS = @LD_FLAGS@ +LIB_tgetent = @LIB_tgetent@ +LIBS = @LIBS@ @LIB_readline@ +MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +INCTOP = $(topdir)/include + +LIBTOP = $(topdir)/lib + +PROGS = ftp$(EXECSUFFIX) + +ftp_OBJS = cmds.o cmdtab.o ftp.o krb4.o main.o ruserpass.o domacro.o \ + globals.o kauth.o + +ftp_SOURCES = cmds.c cmdtab.c ftp.c krb4.c main.c ruserpass.c \ + domacro.c globals.c kauth.c + +OBJECTS = $(ftp_OBJS) +SOURCES = $(ftp_SOURCES) + +all: $(PROGS) + +.c.o: + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(DEFS) $< + +install: all + $(MKINSTALLDIRS) $(bindir) + for x in $(PROGS); do \ + $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROGS); do \ + rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \ + done + +ftp$(EXECSUFFIX): $(ftp_OBJS) # ../common/libcommon.a + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(ftp_OBJS) -L../common -lcommon -L$(LIBTOP)/krb -lkrb -L$(LIBTOP)/des -ldes -L$(LIBTOP)/roken -lroken $(LIBS) -L$(LIBTOP)/roken -lroken + +TAGS: $(SOURCES) + etags $(SOURCES) + +clean cleandir: + rm -f *~ *.o core ftp \#* + +distclean: + rm -f Makefile + +$(OBJECTS): ../../../include/config.h diff --git a/crypto/kerberosIV/appl/ftp/ftp/cmds.c b/crypto/kerberosIV/appl/ftp/ftp/cmds.c new file mode 100644 index 0000000..5e1980b --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/cmds.c @@ -0,0 +1,2073 @@ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * FTP User Program -- Command Routines. + */ + +#include "ftp_locl.h" +RCSID("$Id: cmds.c,v 1.23 1997/06/01 22:52:37 assar Exp $"); + +typedef void (*sighand)(int); + +jmp_buf jabort; +char *mname; +char *home = "/"; + +/* + * `Another' gets another argument, and stores the new argc and argv. + * It reverts to the top level (via main.c's intr()) on EOF/error. + * + * Returns false if no new arguments have been added. + */ +int +another(int *pargc, char ***pargv, char *prompt) +{ + int len = strlen(line), ret; + + if (len >= sizeof(line) - 3) { + printf("sorry, arguments too long\n"); + intr(0); + } + printf("(%s) ", prompt); + line[len++] = ' '; + if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) + intr(0); + len += strlen(&line[len]); + if (len > 0 && line[len - 1] == '\n') + line[len - 1] = '\0'; + makeargv(); + ret = margc > *pargc; + *pargc = margc; + *pargv = margv; + return (ret); +} + +/* + * Connect to peer server and + * auto-login, if possible. + */ +void +setpeer(int argc, char **argv) +{ + char *host; + short port; + struct servent *sp; + + if (connected) { + printf("Already connected to %s, use close first.\n", + hostname); + code = -1; + return; + } + if (argc < 2) + another(&argc, &argv, "to"); + if (argc < 2 || argc > 3) { + printf("usage: %s host-name [port]\n", argv[0]); + code = -1; + return; + } + sp = getservbyname("ftp", "tcp"); + if (sp == NULL) + errx(1, "You bastard. You removed ftp/tcp from services"); + port = sp->s_port; + if (argc > 2) { + port = atoi(argv[2]); + if (port <= 0) { + printf("%s: bad port number-- %s\n", argv[1], argv[2]); + printf ("usage: %s host-name [port]\n", argv[0]); + code = -1; + return; + } + port = htons(port); + } + host = hookup(argv[1], port); + if (host) { + int overbose; + + connected = 1; + /* + * Set up defaults for FTP. + */ + strcpy(typename, "ascii"), type = TYPE_A; + curtype = TYPE_A; + strcpy(formname, "non-print"), form = FORM_N; + strcpy(modename, "stream"), mode = MODE_S; + strcpy(structname, "file"), stru = STRU_F; + strcpy(bytename, "8"), bytesize = 8; + if (autologin) + login(argv[1]); + +#if (defined(unix) || defined(__unix__) || defined(__unix) || defined(_AIX) || defined(_CRAY)) && NBBY == 8 +/* + * this ifdef is to keep someone form "porting" this to an incompatible + * system and not checking this out. This way they have to think about it. + */ + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("SYST") == COMPLETE && overbose) { + char *cp, c; + cp = strchr(reply_string+4, ' '); + if (cp == NULL) + cp = strchr(reply_string+4, '\r'); + if (cp) { + if (cp[-1] == '.') + cp--; + c = *cp; + *cp = '\0'; + } + + printf("Remote system type is %s.\n", + reply_string+4); + if (cp) + *cp = c; + } + if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { + if (proxy) + unix_proxy = 1; + else + unix_server = 1; + /* + * Set type to 0 (not specified by user), + * meaning binary by default, but don't bother + * telling server. We can use binary + * for text files unless changed by the user. + */ + type = 0; + strcpy(typename, "binary"); + if (overbose) + printf("Using %s mode to transfer files.\n", + typename); + } else { + if (proxy) + unix_proxy = 0; + else + unix_server = 0; + if (overbose && + !strncmp(reply_string, "215 TOPS20", 10)) + printf( +"Remember to set tenex mode when transfering binary files from this machine.\n"); + } + verbose = overbose; +#endif /* unix */ + } +} + +struct types { + char *t_name; + char *t_mode; + int t_type; + char *t_arg; +} types[] = { + { "ascii", "A", TYPE_A, 0 }, + { "binary", "I", TYPE_I, 0 }, + { "image", "I", TYPE_I, 0 }, + { "ebcdic", "E", TYPE_E, 0 }, + { "tenex", "L", TYPE_L, bytename }, + { NULL } +}; + +/* + * Set transfer type. + */ +void +settype(int argc, char **argv) +{ + struct types *p; + int comret; + + if (argc > 2) { + char *sep; + + printf("usage: %s [", argv[0]); + sep = " "; + for (p = types; p->t_name; p++) { + printf("%s%s", sep, p->t_name); + sep = " | "; + } + printf(" ]\n"); + code = -1; + return; + } + if (argc < 2) { + printf("Using %s mode to transfer files.\n", typename); + code = 0; + return; + } + for (p = types; p->t_name; p++) + if (strcmp(argv[1], p->t_name) == 0) + break; + if (p->t_name == 0) { + printf("%s: unknown mode\n", argv[1]); + code = -1; + return; + } + if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) + comret = command ("TYPE %s %s", p->t_mode, p->t_arg); + else + comret = command("TYPE %s", p->t_mode); + if (comret == COMPLETE) { + strcpy(typename, p->t_name); + curtype = type = p->t_type; + } +} + +/* + * Internal form of settype; changes current type in use with server + * without changing our notion of the type for data transfers. + * Used to change to and from ascii for listings. + */ +void +changetype(int newtype, int show) +{ + struct types *p; + int comret, oldverbose = verbose; + + if (newtype == 0) + newtype = TYPE_I; + if (newtype == curtype) + return; + if (debug == 0 && show == 0) + verbose = 0; + for (p = types; p->t_name; p++) + if (newtype == p->t_type) + break; + if (p->t_name == 0) { + printf("ftp: internal error: unknown type %d\n", newtype); + return; + } + if (newtype == TYPE_L && bytename[0] != '\0') + comret = command("TYPE %s %s", p->t_mode, bytename); + else + comret = command("TYPE %s", p->t_mode); + if (comret == COMPLETE) + curtype = newtype; + verbose = oldverbose; +} + +char *stype[] = { + "type", + "", + 0 +}; + +/* + * Set binary transfer type. + */ +/*VARARGS*/ +void +setbinary(int argc, char **argv) +{ + + stype[1] = "binary"; + settype(2, stype); +} + +/* + * Set ascii transfer type. + */ +/*VARARGS*/ +void +setascii(int argc, char **argv) +{ + + stype[1] = "ascii"; + settype(2, stype); +} + +/* + * Set tenex transfer type. + */ +/*VARARGS*/ +void +settenex(int argc, char **argv) +{ + + stype[1] = "tenex"; + settype(2, stype); +} + +/* + * Set file transfer mode. + */ +/*ARGSUSED*/ +void +setftmode(int argc, char **argv) +{ + + printf("We only support %s mode, sorry.\n", modename); + code = -1; +} + +/* + * Set file transfer format. + */ +/*ARGSUSED*/ +void +setform(int argc, char **argv) +{ + + printf("We only support %s format, sorry.\n", formname); + code = -1; +} + +/* + * Set file transfer structure. + */ +/*ARGSUSED*/ +void +setstruct(int argc, char **argv) +{ + + printf("We only support %s structure, sorry.\n", structname); + code = -1; +} + +/* + * Send a single file. + */ +void +put(int argc, char **argv) +{ + char *cmd; + int loc = 0; + char *oldargv1, *oldargv2; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc < 2 && !another(&argc, &argv, "local-file")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "remote-file")) { +usage: + printf("usage: %s local-file remote-file\n", argv[0]); + code = -1; + return; + } + oldargv1 = argv[1]; + oldargv2 = argv[2]; + if (!globulize(&argv[1])) { + code = -1; + return; + } + /* + * If "globulize" modifies argv[1], and argv[2] is a copy of + * the old argv[1], make it a copy of the new argv[1]. + */ + if (argv[1] != oldargv1 && argv[2] == oldargv1) { + argv[2] = argv[1]; + } + cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); + if (loc && ntflag) { + argv[2] = dotrans(argv[2]); + } + if (loc && mapflag) { + argv[2] = domap(argv[2]); + } + sendrequest(cmd, argv[1], argv[2], + argv[1] != oldargv1 || argv[2] != oldargv2); +} + +/* ARGSUSED */ +static RETSIGTYPE +mabort(int signo) +{ + int ointer; + + printf("\n"); + fflush(stdout); + if (mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", mname)) { + interactive = ointer; + longjmp(jabort,0); + } + interactive = ointer; + } + mflag = 0; + longjmp(jabort,0); +} + +/* + * Send multiple files. + */ +void +mput(int argc, char **argv) +{ + int i; + RETSIGTYPE (*oldintr)(); + int ointer; + char *tp; + + if (argc < 2 && !another(&argc, &argv, "local-files")) { + printf("usage: %s local-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + setjmp(jabort); + if (proxy) { + char *cp, *tp2, tmpbuf[MaxPathLen]; + + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == 0) { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + tp = cp; + if (mcase) { + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = cp; + tp2 = tmpbuf; + while ((*tp2 = *tp) != '\0') { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; + } + } + tp = tmpbuf; + } + if (ntflag) { + tp = dotrans(tp); + } + if (mapflag) { + tp = domap(tp); + } + sendrequest((sunique) ? "STOU" : "STOR", + cp, tp, cp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + } + signal(SIGINT, oldintr); + mflag = 0; + return; + } + for (i = 1; i < argc; i++) { + char **cpp; + glob_t gl; + int flags; + + if (!doglob) { + if (mflag && confirm(argv[0], argv[i])) { + tp = (ntflag) ? dotrans(argv[i]) : argv[i]; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + argv[i], tp, tp != argv[i] || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + continue; + } + + memset(&gl, 0, sizeof(gl)); + flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { + warnx("%s: not found", argv[i]); + globfree(&gl); + continue; + } + for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) { + if (mflag && confirm(argv[0], *cpp)) { + tp = (ntflag) ? dotrans(*cpp) : *cpp; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + *cpp, tp, *cpp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + } + globfree(&gl); + } + signal(SIGINT, oldintr); + mflag = 0; +} + +void +reget(int argc, char **argv) +{ + + getit(argc, argv, 1, "r+w"); +} + +void +get(int argc, char **argv) +{ + + getit(argc, argv, 0, restart_point ? "r+w" : "w" ); +} + +/* + * Receive one file. + */ +int +getit(int argc, char **argv, int restartit, char *mode) +{ + int loc = 0; + char *oldargv1, *oldargv2; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc < 2 && !another(&argc, &argv, "remote-file")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "local-file")) { +usage: + printf("usage: %s remote-file [ local-file ]\n", argv[0]); + code = -1; + return (0); + } + oldargv1 = argv[1]; + oldargv2 = argv[2]; + if (!globulize(&argv[2])) { + code = -1; + return (0); + } + if (loc && mcase) { + char *tp = argv[1], *tp2, tmpbuf[MaxPathLen]; + + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = argv[2]; + tp2 = tmpbuf; + while ((*tp2 = *tp) != '\0') { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; + } + argv[2] = tmpbuf; + } + } + if (loc && ntflag) + argv[2] = dotrans(argv[2]); + if (loc && mapflag) + argv[2] = domap(argv[2]); + if (restartit) { + struct stat stbuf; + int ret; + + ret = stat(argv[2], &stbuf); + if (restartit == 1) { + if (ret < 0) { + warn("local: %s", argv[2]); + return (0); + } + restart_point = stbuf.st_size; + } else { + if (ret == 0) { + int overbose; + + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("MDTM %s", argv[1]) == COMPLETE) { + int yy, mo, day, hour, min, sec; + struct tm *tm; + verbose = overbose; + sscanf(reply_string, + "%*s %04d%02d%02d%02d%02d%02d", + &yy, &mo, &day, &hour, &min, &sec); + tm = gmtime(&stbuf.st_mtime); + tm->tm_mon++; + if (tm->tm_year > yy%100) + return (1); + if ((tm->tm_year == yy%100 && + tm->tm_mon > mo) || + (tm->tm_mon == mo && + tm->tm_mday > day) || + (tm->tm_mday == day && + tm->tm_hour > hour) || + (tm->tm_hour == hour && + tm->tm_min > min) || + (tm->tm_min == min && + tm->tm_sec > sec)) + return (1); + } else { + printf("%s\n", reply_string); + verbose = overbose; + return (0); + } + } + } + } + + recvrequest("RETR", argv[2], argv[1], mode, + argv[1] != oldargv1 || argv[2] != oldargv2); + restart_point = 0; + return (0); +} + +/* + * Get multiple files. + */ +void +mget(int argc, char **argv) +{ + sighand oldintr; + int ch, ointer; + char *cp, *tp, *tp2, tmpbuf[MaxPathLen]; + + if (argc < 2 && !another(&argc, &argv, "remote-files")) { + printf("usage: %s remote-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + setjmp(jabort); + while ((cp = remglob(argv,proxy)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + tp = cp; + if (mcase) { + for (tp2 = tmpbuf; (ch = *tp++);) + *tp2++ = isupper(ch) ? tolower(ch) : ch; + *tp2 = '\0'; + tp = tmpbuf; + } + if (ntflag) { + tp = dotrans(tp); + } + if (mapflag) { + tp = domap(tp); + } + recvrequest("RETR", tp, cp, "w", + tp != cp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mget")) { + mflag++; + } + interactive = ointer; + } + } + } + signal(SIGINT,oldintr); + mflag = 0; +} + +char * +remglob(char **argv, int doswitch) +{ + char temp[16]; + static char buf[MaxPathLen]; + static FILE *ftemp = NULL; + static char **args; + int oldverbose, oldhash; + char *cp, *mode; + + if (!mflag) { + if (!doglob) { + args = NULL; + } + else { + if (ftemp) { + fclose(ftemp); + ftemp = NULL; + } + } + return (NULL); + } + if (!doglob) { + if (args == NULL) + args = argv; + if ((cp = *++args) == NULL) + args = NULL; + return (cp); + } + if (ftemp == NULL) { + strcpy(temp, _PATH_TMP_XXX); + mktemp(temp); + oldverbose = verbose, verbose = 0; + oldhash = hash, hash = 0; + if (doswitch) { + pswitch(!proxy); + } + for (mode = "w"; *++argv != NULL; mode = "a") + recvrequest ("NLST", temp, *argv, mode, 0); + if (doswitch) { + pswitch(!proxy); + } + verbose = oldverbose; hash = oldhash; + ftemp = fopen(temp, "r"); + unlink(temp); + if (ftemp == NULL) { + printf("can't find list of remote files, oops\n"); + return (NULL); + } + } + if (fgets(buf, sizeof (buf), ftemp) == NULL) { + fclose(ftemp); + ftemp = NULL; + return (NULL); + } + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + return (buf); +} + +char * +onoff(int bool) +{ + + return (bool ? "on" : "off"); +} + +/* + * Show status. + */ +/*ARGSUSED*/ +void +status(int argc, char **argv) +{ + int i; + + if (connected) + printf("Connected to %s.\n", hostname); + else + printf("Not connected.\n"); + if (!proxy) { + pswitch(1); + if (connected) { + printf("Connected for proxy commands to %s.\n", hostname); + } + else { + printf("No proxy connection.\n"); + } + pswitch(0); + } + sec_status(); + printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", + modename, typename, formname, structname); + printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", + onoff(verbose), onoff(bell), onoff(interactive), + onoff(doglob)); + printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), + onoff(runique)); + printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); + if (ntflag) { + printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); + } + else { + printf("Ntrans: off\n"); + } + if (mapflag) { + printf("Nmap: (in) %s (out) %s\n", mapin, mapout); + } + else { + printf("Nmap: off\n"); + } + printf("Hash mark printing: %s; Use of PORT cmds: %s\n", + onoff(hash), onoff(sendport)); + if (macnum > 0) { + printf("Macros:\n"); + for (i=0; i<macnum; i++) { + printf("\t%s\n",macros[i].mac_name); + } + } + code = 0; +} + +/* + * Set beep on cmd completed mode. + */ +/*VARARGS*/ +void +setbell(int argc, char **argv) +{ + + bell = !bell; + printf("Bell mode %s.\n", onoff(bell)); + code = bell; +} + +/* + * Turn on packet tracing. + */ +/*VARARGS*/ +void +settrace(int argc, char **argv) +{ + + trace = !trace; + printf("Packet tracing %s.\n", onoff(trace)); + code = trace; +} + +/* + * Toggle hash mark printing during transfers. + */ +/*VARARGS*/ +void +sethash(int argc, char **argv) +{ + + hash = !hash; + printf("Hash mark printing %s", onoff(hash)); + code = hash; + if (hash) + printf(" (%d bytes/hash mark)", 1024); + printf(".\n"); +} + +/* + * Turn on printing of server echo's. + */ +/*VARARGS*/ +void +setverbose(int argc, char **argv) +{ + + verbose = !verbose; + printf("Verbose mode %s.\n", onoff(verbose)); + code = verbose; +} + +/* + * Toggle PORT cmd use before each data connection. + */ +/*VARARGS*/ +void +setport(int argc, char **argv) +{ + + sendport = !sendport; + printf("Use of PORT cmds %s.\n", onoff(sendport)); + code = sendport; +} + +/* + * Turn on interactive prompting + * during mget, mput, and mdelete. + */ +/*VARARGS*/ +void +setprompt(int argc, char **argv) +{ + + interactive = !interactive; + printf("Interactive mode %s.\n", onoff(interactive)); + code = interactive; +} + +/* + * Toggle metacharacter interpretation + * on local file names. + */ +/*VARARGS*/ +void +setglob(int argc, char **argv) +{ + + doglob = !doglob; + printf("Globbing %s.\n", onoff(doglob)); + code = doglob; +} + +/* + * Set debugging mode on/off and/or + * set level of debugging. + */ +/*VARARGS*/ +void +setdebug(int argc, char **argv) +{ + int val; + + if (argc > 1) { + val = atoi(argv[1]); + if (val < 0) { + printf("%s: bad debugging value.\n", argv[1]); + code = -1; + return; + } + } else + val = !debug; + debug = val; + if (debug) + options |= SO_DEBUG; + else + options &= ~SO_DEBUG; + printf("Debugging %s (debug=%d).\n", onoff(debug), debug); + code = debug > 0; +} + +/* + * Set current working directory + * on remote machine. + */ +void +cd(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "remote-directory")) { + printf("usage: %s remote-directory\n", argv[0]); + code = -1; + return; + } + if (command("CWD %s", argv[1]) == ERROR && code == 500) { + if (verbose) + printf("CWD command not recognized, trying XCWD\n"); + command("XCWD %s", argv[1]); + } +} + +/* + * Set current working directory + * on local machine. + */ +void +lcd(int argc, char **argv) +{ + char buf[MaxPathLen]; + + if (argc < 2) + argc++, argv[1] = home; + if (argc != 2) { + printf("usage: %s local-directory\n", argv[0]); + code = -1; + return; + } + if (!globulize(&argv[1])) { + code = -1; + return; + } + if (chdir(argv[1]) < 0) { + warn("local: %s", argv[1]); + code = -1; + return; + } + if (getcwd(buf, sizeof(buf)) != NULL) + printf("Local directory now %s\n", buf); + else + warnx("getwd: %s", buf); + code = 0; +} + +/* + * Delete a single file. + */ +void +delete(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "remote-file")) { + printf("usage: %s remote-file\n", argv[0]); + code = -1; + return; + } + command("DELE %s", argv[1]); +} + +/* + * Delete multiple files. + */ +void +mdelete(int argc, char **argv) +{ + sighand oldintr; + int ointer; + char *cp; + + if (argc < 2 && !another(&argc, &argv, "remote-files")) { + printf("usage: %s remote-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + setjmp(jabort); + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + command("DELE %s", cp); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mdelete")) { + mflag++; + } + interactive = ointer; + } + } + } + signal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Rename a remote file. + */ +void +renamefile(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "from-name")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "to-name")) { +usage: + printf("%s from-name to-name\n", argv[0]); + code = -1; + return; + } + if (command("RNFR %s", argv[1]) == CONTINUE) + command("RNTO %s", argv[2]); +} + +/* + * Get a directory listing + * of remote files. + */ +void +ls(int argc, char **argv) +{ + char *cmd; + + if (argc < 2) + argc++, argv[1] = NULL; + if (argc < 3) + argc++, argv[2] = "-"; + if (argc > 3) { + printf("usage: %s remote-directory local-file\n", argv[0]); + code = -1; + return; + } + cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; + if (strcmp(argv[2], "-") && !globulize(&argv[2])) { + code = -1; + return; + } + if (strcmp(argv[2], "-") && *argv[2] != '|') + if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { + code = -1; + return; + } + recvrequest(cmd, argv[2], argv[1], "w", 0); +} + +/* + * Get a directory listing + * of multiple remote files. + */ +void +mls(int argc, char **argv) +{ + sighand oldintr; + int ointer, i; + char *cmd, mode[1], *dest; + + if (argc < 2 && !another(&argc, &argv, "remote-files")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "local-file")) { +usage: + printf("usage: %s remote-files local-file\n", argv[0]); + code = -1; + return; + } + dest = argv[argc - 1]; + argv[argc - 1] = NULL; + if (strcmp(dest, "-") && *dest != '|') + if (!globulize(&dest) || + !confirm("output to local-file:", dest)) { + code = -1; + return; + } + cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + setjmp(jabort); + for (i = 1; mflag && i < argc-1; ++i) { + *mode = (i == 1) ? 'w' : 'a'; + recvrequest(cmd, dest, argv[i], mode, 0); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", argv[0])) { + mflag ++; + } + interactive = ointer; + } + } + signal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Do a shell escape + */ +/*ARGSUSED*/ +void +shell(int argc, char **argv) +{ + pid_t pid; + RETSIGTYPE (*old1)(), (*old2)(); + char shellnam[40], *shell, *namep; + int status; + + old1 = signal (SIGINT, SIG_IGN); + old2 = signal (SIGQUIT, SIG_IGN); + if ((pid = fork()) == 0) { + for (pid = 3; pid < 20; pid++) + close(pid); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + shell = getenv("SHELL"); + if (shell == NULL) + shell = _PATH_BSHELL; + namep = strrchr(shell,'/'); + if (namep == NULL) + namep = shell; + strcpy(shellnam,"-"); + strcat(shellnam, ++namep); + if (strcmp(namep, "sh") != 0) + shellnam[0] = '+'; + if (debug) { + printf ("%s\n", shell); + fflush (stdout); + } + if (argc > 1) { + execl(shell,shellnam,"-c",altarg,(char *)0); + } + else { + execl(shell,shellnam,(char *)0); + } + warn("%s", shell); + code = -1; + exit(1); + } + if (pid > 0) + while (waitpid(-1, &status, 0) != pid) + ; + signal(SIGINT, old1); + signal(SIGQUIT, old2); + if (pid == -1) { + warn("%s", "Try again later"); + code = -1; + } + else { + code = 0; + } +} + +/* + * Send new user information (re-login) + */ +void +user(int argc, char **argv) +{ + char acct[80]; + int n, aflag = 0; + char tmp[256]; + + if (argc < 2) + another(&argc, &argv, "username"); + if (argc < 2 || argc > 4) { + printf("usage: %s username [password] [account]\n", argv[0]); + code = -1; + return; + } + n = command("USER %s", argv[1]); + if (n == CONTINUE) { + if (argc < 3 ) { + des_read_pw_string (tmp, + sizeof(tmp), + "Password: ", 0); + argv[2] = tmp; + argc++; + } + n = command("PASS %s", argv[2]); + } + if (n == CONTINUE) { + if (argc < 4) { + printf("Account: "); fflush(stdout); + fgets(acct, sizeof(acct) - 1, stdin); + acct[strlen(acct) - 1] = '\0'; + argv[3] = acct; argc++; + } + n = command("ACCT %s", argv[3]); + aflag++; + } + if (n != COMPLETE) { + fprintf(stdout, "Login failed.\n"); + return; + } + if (!aflag && argc == 4) { + command("ACCT %s", argv[3]); + } +} + +/* + * Print working directory. + */ +/*VARARGS*/ +void +pwd(int argc, char **argv) +{ + int oldverbose = verbose; + + /* + * If we aren't verbose, this doesn't do anything! + */ + verbose = 1; + if (command("PWD") == ERROR && code == 500) { + printf("PWD command not recognized, trying XPWD\n"); + command("XPWD"); + } + verbose = oldverbose; +} + +/* + * Make a directory. + */ +void +makedir(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "directory-name")) { + printf("usage: %s directory-name\n", argv[0]); + code = -1; + return; + } + if (command("MKD %s", argv[1]) == ERROR && code == 500) { + if (verbose) + printf("MKD command not recognized, trying XMKD\n"); + command("XMKD %s", argv[1]); + } +} + +/* + * Remove a directory. + */ +void +removedir(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "directory-name")) { + printf("usage: %s directory-name\n", argv[0]); + code = -1; + return; + } + if (command("RMD %s", argv[1]) == ERROR && code == 500) { + if (verbose) + printf("RMD command not recognized, trying XRMD\n"); + command("XRMD %s", argv[1]); + } +} + +/* + * Send a line, verbatim, to the remote machine. + */ +void +quote(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "command line to send")) { + printf("usage: %s line-to-send\n", argv[0]); + code = -1; + return; + } + quote1("", argc, argv); +} + +/* + * Send a SITE command to the remote machine. The line + * is sent verbatim to the remote machine, except that the + * word "SITE" is added at the front. + */ +void +site(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { + printf("usage: %s line-to-send\n", argv[0]); + code = -1; + return; + } + quote1("SITE ", argc, argv); +} + +/* + * Turn argv[1..argc) into a space-separated string, then prepend initial text. + * Send the result as a one-line command and get response. + */ +void +quote1(char *initial, int argc, char **argv) +{ + int i, len; + char buf[BUFSIZ]; /* must be >= sizeof(line) */ + + strcpy(buf, initial); + if (argc > 1) { + len = strlen(buf); + len += strlen(strcpy(&buf[len], argv[1])); + for (i = 2; i < argc; i++) { + buf[len++] = ' '; + len += strlen(strcpy(&buf[len], argv[i])); + } + } + if (command(buf) == PRELIM) { + while (getreply(0) == PRELIM) + continue; + } +} + +void +do_chmod(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "mode")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "file-name")) { +usage: + printf("usage: %s mode file-name\n", argv[0]); + code = -1; + return; + } + command("SITE CHMOD %s %s", argv[1], argv[2]); +} + +void +do_umask(int argc, char **argv) +{ + int oldverbose = verbose; + + verbose = 1; + command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); + verbose = oldverbose; +} + +void +ftp_idle(int argc, char **argv) +{ + int oldverbose = verbose; + + verbose = 1; + command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); + verbose = oldverbose; +} + +/* + * Ask the other side for help. + */ +void +rmthelp(int argc, char **argv) +{ + int oldverbose = verbose; + + verbose = 1; + command(argc == 1 ? "HELP" : "HELP %s", argv[1]); + verbose = oldverbose; +} + +/* + * Terminate session and exit. + */ +/*VARARGS*/ +void +quit(int argc, char **argv) +{ + + if (connected) + disconnect(0, 0); + pswitch(1); + if (connected) { + disconnect(0, 0); + } + exit(0); +} + +/* + * Terminate session, but don't exit. + */ +void +disconnect(int argc, char **argv) +{ + + if (!connected) + return; + command("QUIT"); + if (cout) { + fclose(cout); + } + cout = NULL; + connected = 0; + krb4_quit(); + data = -1; + if (!proxy) { + macnum = 0; + } +} + +int +confirm(char *cmd, char *file) +{ + char line[BUFSIZ]; + + if (!interactive) + return (1); + printf("%s %s? ", cmd, file); + fflush(stdout); + if (fgets(line, sizeof line, stdin) == NULL) + return (0); + return (*line != 'n' && *line != 'N'); +} + +void +fatal(char *msg) +{ + + errx(1, "%s", msg); +} + +/* + * Glob a local file name specification with + * the expectation of a single return value. + * Can't control multiple values being expanded + * from the expression, we return only the first. + */ +int +globulize(char **cpp) +{ + glob_t gl; + int flags; + + if (!doglob) + return (1); + + flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + memset(&gl, 0, sizeof(gl)); + if (glob(*cpp, flags, NULL, &gl) || + gl.gl_pathc == 0) { + warnx("%s: not found", *cpp); + globfree(&gl); + return (0); + } + *cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */ + globfree(&gl); + return (1); +} + +void +account(int argc, char **argv) +{ + char acct[50]; + + if (argc > 1) { + ++argv; + --argc; + strncpy(acct,*argv,49); + acct[49] = '\0'; + while (argc > 1) { + --argc; + ++argv; + strncat(acct,*argv, 49-strlen(acct)); + } + } + else { + des_read_pw_string(acct, sizeof(acct), "Account:", 0); + } + command("ACCT %s", acct); +} + +jmp_buf abortprox; + +static RETSIGTYPE +proxabort(int sig) +{ + + if (!proxy) { + pswitch(1); + } + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); + longjmp(abortprox,1); +} + +void +doproxy(int argc, char **argv) +{ + struct cmd *c; + RETSIGTYPE (*oldintr)(); + + if (argc < 2 && !another(&argc, &argv, "command")) { + printf("usage: %s command\n", argv[0]); + code = -1; + return; + } + c = getcmd(argv[1]); + if (c == (struct cmd *) -1) { + printf("?Ambiguous command\n"); + fflush(stdout); + code = -1; + return; + } + if (c == 0) { + printf("?Invalid command\n"); + fflush(stdout); + code = -1; + return; + } + if (!c->c_proxy) { + printf("?Invalid proxy command\n"); + fflush(stdout); + code = -1; + return; + } + if (setjmp(abortprox)) { + code = -1; + return; + } + oldintr = signal(SIGINT, proxabort); + pswitch(1); + if (c->c_conn && !connected) { + printf("Not connected\n"); + fflush(stdout); + pswitch(0); + signal(SIGINT, oldintr); + code = -1; + return; + } + (*c->c_handler)(argc-1, argv+1); + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); + signal(SIGINT, oldintr); +} + +void +setcase(int argc, char **argv) +{ + + mcase = !mcase; + printf("Case mapping %s.\n", onoff(mcase)); + code = mcase; +} + +void +setcr(int argc, char **argv) +{ + + crflag = !crflag; + printf("Carriage Return stripping %s.\n", onoff(crflag)); + code = crflag; +} + +void +setntrans(int argc, char **argv) +{ + if (argc == 1) { + ntflag = 0; + printf("Ntrans off.\n"); + code = ntflag; + return; + } + ntflag++; + code = ntflag; + strncpy(ntin, argv[1], 16); + ntin[16] = '\0'; + if (argc == 2) { + ntout[0] = '\0'; + return; + } + strncpy(ntout, argv[2], 16); + ntout[16] = '\0'; +} + +char * +dotrans(char *name) +{ + static char new[MaxPathLen]; + char *cp1, *cp2 = new; + int i, ostop, found; + + for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++) + continue; + for (cp1 = name; *cp1; cp1++) { + found = 0; + for (i = 0; *(ntin + i) && i < 16; i++) { + if (*cp1 == *(ntin + i)) { + found++; + if (i < ostop) { + *cp2++ = *(ntout + i); + } + break; + } + } + if (!found) { + *cp2++ = *cp1; + } + } + *cp2 = '\0'; + return (new); +} + +void +setnmap(int argc, char **argv) +{ + char *cp; + + if (argc == 1) { + mapflag = 0; + printf("Nmap off.\n"); + code = mapflag; + return; + } + if (argc < 3 && !another(&argc, &argv, "mapout")) { + printf("Usage: %s [mapin mapout]\n",argv[0]); + code = -1; + return; + } + mapflag = 1; + code = 1; + cp = strchr(altarg, ' '); + if (proxy) { + while(*++cp == ' ') + continue; + altarg = cp; + cp = strchr(altarg, ' '); + } + *cp = '\0'; + strncpy(mapin, altarg, MaxPathLen - 1); + while (*++cp == ' ') + continue; + strncpy(mapout, cp, MaxPathLen - 1); +} + +char * +domap(char *name) +{ + static char new[MaxPathLen]; + char *cp1 = name, *cp2 = mapin; + char *tp[9], *te[9]; + int i, toks[9], toknum = 0, match = 1; + + for (i=0; i < 9; ++i) { + toks[i] = 0; + } + while (match && *cp1 && *cp2) { + switch (*cp2) { + case '\\': + if (*++cp2 != *cp1) { + match = 0; + } + break; + case '$': + if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { + if (*cp1 != *(++cp2+1)) { + toks[toknum = *cp2 - '1']++; + tp[toknum] = cp1; + while (*++cp1 && *(cp2+1) + != *cp1); + te[toknum] = cp1; + } + cp2++; + break; + } + /* FALLTHROUGH */ + default: + if (*cp2 != *cp1) { + match = 0; + } + break; + } + if (match && *cp1) { + cp1++; + } + if (match && *cp2) { + cp2++; + } + } + if (!match && *cp1) /* last token mismatch */ + { + toks[toknum] = 0; + } + cp1 = new; + *cp1 = '\0'; + cp2 = mapout; + while (*cp2) { + match = 0; + switch (*cp2) { + case '\\': + if (*(cp2 + 1)) { + *cp1++ = *++cp2; + } + break; + case '[': +LOOP: + if (*++cp2 == '$' && isdigit(*(cp2+1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + match = 1; + } + else if (toks[toknum = *cp2 - '1']) { + char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp1++ = *cp3++; + } + match = 1; + } + } + else { + while (*cp2 && *cp2 != ',' && + *cp2 != ']') { + if (*cp2 == '\\') { + cp2++; + } + else if (*cp2 == '$' && + isdigit(*(cp2+1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + } + else if (toks[toknum = + *cp2 - '1']) { + char *cp3=tp[toknum]; + + while (cp3 != + te[toknum]) { + *cp1++ = *cp3++; + } + } + } + else if (*cp2) { + *cp1++ = *cp2++; + } + } + if (!*cp2) { + printf("nmap: unbalanced brackets\n"); + return (name); + } + match = 1; + cp2--; + } + if (match) { + while (*++cp2 && *cp2 != ']') { + if (*cp2 == '\\' && *(cp2 + 1)) { + cp2++; + } + } + if (!*cp2) { + printf("nmap: unbalanced brackets\n"); + return (name); + } + break; + } + switch (*++cp2) { + case ',': + goto LOOP; + case ']': + break; + default: + cp2--; + goto LOOP; + } + break; + case '$': + if (isdigit(*(cp2 + 1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + } + else if (toks[toknum = *cp2 - '1']) { + char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp1++ = *cp3++; + } + } + break; + } + /* intentional drop through */ + default: + *cp1++ = *cp2; + break; + } + cp2++; + } + *cp1 = '\0'; + if (!*new) { + return (name); + } + return (new); +} + +void +setpassive(int argc, char **argv) +{ + + passivemode = !passivemode; + printf("Passive mode %s.\n", onoff(passivemode)); + code = passivemode; +} + +void +setsunique(int argc, char **argv) +{ + + sunique = !sunique; + printf("Store unique %s.\n", onoff(sunique)); + code = sunique; +} + +void +setrunique(int argc, char **argv) +{ + + runique = !runique; + printf("Receive unique %s.\n", onoff(runique)); + code = runique; +} + +/* change directory to perent directory */ +void +cdup(int argc, char **argv) +{ + + if (command("CDUP") == ERROR && code == 500) { + if (verbose) + printf("CDUP command not recognized, trying XCUP\n"); + command("XCUP"); + } +} + +/* restart transfer at specific point */ +void +restart(int argc, char **argv) +{ + + if (argc != 2) + printf("restart: offset not specified\n"); + else { + restart_point = atol(argv[1]); + printf("restarting at %ld. %s\n", (long)restart_point, + "execute get, put or append to initiate transfer"); + } +} + +/* show remote system type */ +void +syst(int argc, char **argv) +{ + + command("SYST"); +} + +void +macdef(int argc, char **argv) +{ + char *tmp; + int c; + + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + code = -1; + return; + } + if (argc < 2 && !another(&argc, &argv, "macro name")) { + printf("Usage: %s macro_name\n",argv[0]); + code = -1; + return; + } + if (interactive) { + printf("Enter macro line by line, terminating it with a null line\n"); + } + strncpy(macros[macnum].mac_name, argv[1], 8); + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf+4096) { + if ((c = getchar()) == EOF) { + printf("macdef:end of file encountered\n"); + code = -1; + return; + } + if ((*tmp = c) == '\n') { + if (tmp == macros[macnum].mac_start) { + macros[macnum++].mac_end = tmp; + code = 0; + return; + } + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + code = 0; + return; + } + *tmp = '\0'; + } + tmp++; + } + while (1) { + while ((c = getchar()) != '\n' && c != EOF) + /* LOOP */; + if (c == EOF || getchar() == '\n') { + printf("Macro not defined - 4k buffer exceeded\n"); + code = -1; + return; + } + } +} + +/* + * get size of file on remote machine + */ +void +sizecmd(int argc, char **argv) +{ + + if (argc < 2 && !another(&argc, &argv, "filename")) { + printf("usage: %s filename\n", argv[0]); + code = -1; + return; + } + command("SIZE %s", argv[1]); +} + +/* + * get last modification time of file on remote machine + */ +void +modtime(int argc, char **argv) +{ + int overbose; + + if (argc < 2 && !another(&argc, &argv, "filename")) { + printf("usage: %s filename\n", argv[0]); + code = -1; + return; + } + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("MDTM %s", argv[1]) == COMPLETE) { + int yy, mo, day, hour, min, sec; + sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, + &day, &hour, &min, &sec); + /* might want to print this in local time */ + printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], + mo, day, yy, hour, min, sec); + } else + printf("%s\n", reply_string); + verbose = overbose; +} + +/* + * show status on reomte machine + */ +void +rmtstatus(int argc, char **argv) +{ + + command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); +} + +/* + * get file if modtime is more recent than current file + */ +void +newer(int argc, char **argv) +{ + + if (getit(argc, argv, -1, "w")) + printf("Local file \"%s\" is newer than remote file \"%s\"\n", + argv[2], argv[1]); +} diff --git a/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c new file mode 100644 index 0000000..9567e3c --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "ftp_locl.h" + +/* + * User FTP -- Command Tables. + */ + +char accounthelp[] = "send account command to remote server"; +char appendhelp[] = "append to a file"; +char asciihelp[] = "set ascii transfer type"; +char beephelp[] = "beep when command completed"; +char binaryhelp[] = "set binary transfer type"; +char casehelp[] = "toggle mget upper/lower case id mapping"; +char cdhelp[] = "change remote working directory"; +char cduphelp[] = "change remote working directory to parent directory"; +char chmodhelp[] = "change file permissions of remote file"; +char connecthelp[] = "connect to remote tftp"; +char crhelp[] = "toggle carriage return stripping on ascii gets"; +char deletehelp[] = "delete remote file"; +char debughelp[] = "toggle/set debugging mode"; +char dirhelp[] = "list contents of remote directory"; +char disconhelp[] = "terminate ftp session"; +char domachelp[] = "execute macro"; +char formhelp[] = "set file transfer format"; +char globhelp[] = "toggle metacharacter expansion of local file names"; +char hashhelp[] = "toggle printing `#' for each buffer transferred"; +char helphelp[] = "print local help information"; +char idlehelp[] = "get (set) idle timer on remote side"; +char lcdhelp[] = "change local working directory"; +char lshelp[] = "list contents of remote directory"; +char macdefhelp[] = "define a macro"; +char mdeletehelp[] = "delete multiple files"; +char mdirhelp[] = "list contents of multiple remote directories"; +char mgethelp[] = "get multiple files"; +char mkdirhelp[] = "make directory on the remote machine"; +char mlshelp[] = "list contents of multiple remote directories"; +char modtimehelp[] = "show last modification time of remote file"; +char modehelp[] = "set file transfer mode"; +char mputhelp[] = "send multiple files"; +char newerhelp[] = "get file if remote file is newer than local file "; +char nlisthelp[] = "nlist contents of remote directory"; +char nmaphelp[] = "set templates for default file name mapping"; +char ntranshelp[] = "set translation table for default file name mapping"; +char porthelp[] = "toggle use of PORT cmd for each data connection"; +char prompthelp[] = "force interactive prompting on multiple commands"; +char proxyhelp[] = "issue command on alternate connection"; +char pwdhelp[] = "print working directory on remote machine"; +char quithelp[] = "terminate ftp session and exit"; +char quotehelp[] = "send arbitrary ftp command"; +char receivehelp[] = "receive file"; +char regethelp[] = "get file restarting at end of local file"; +char remotehelp[] = "get help from remote server"; +char renamehelp[] = "rename file"; +char restarthelp[]= "restart file transfer at bytecount"; +char rmdirhelp[] = "remove directory on the remote machine"; +char rmtstatushelp[]="show status of remote machine"; +char runiquehelp[] = "toggle store unique for local files"; +char resethelp[] = "clear queued command replies"; +char sendhelp[] = "send one file"; +char passivehelp[] = "enter passive transfer mode"; +char sitehelp[] = "send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information"; +char shellhelp[] = "escape to the shell"; +char sizecmdhelp[] = "show size of remote file"; +char statushelp[] = "show current status"; +char structhelp[] = "set file transfer structure"; +char suniquehelp[] = "toggle store unique on remote machine"; +char systemhelp[] = "show remote system type"; +char tenexhelp[] = "set tenex file transfer type"; +char tracehelp[] = "toggle packet tracing"; +char typehelp[] = "set file transfer type"; +char umaskhelp[] = "get (set) umask on remote side"; +char userhelp[] = "send new user information"; +char verbosehelp[] = "toggle verbose mode"; + +char prothelp[] = "set protection level"; +char kauthhelp[] = "get remote tokens"; +char klisthelp[] = "show remote tickets"; +char aklog[] = "obtain remote AFS tokens"; + +struct cmd cmdtab[] = { + { "!", shellhelp, 0, 0, 0, shell }, + { "$", domachelp, 1, 0, 0, domacro }, + { "account", accounthelp, 0, 1, 1, account}, + { "append", appendhelp, 1, 1, 1, put }, + { "ascii", asciihelp, 0, 1, 1, setascii }, + { "bell", beephelp, 0, 0, 0, setbell }, + { "binary", binaryhelp, 0, 1, 1, setbinary }, + { "bye", quithelp, 0, 0, 0, quit }, + { "case", casehelp, 0, 0, 1, setcase }, + { "cd", cdhelp, 0, 1, 1, cd }, + { "cdup", cduphelp, 0, 1, 1, cdup }, + { "chmod", chmodhelp, 0, 1, 1, do_chmod }, + { "close", disconhelp, 0, 1, 1, disconnect }, + { "cr", crhelp, 0, 0, 0, setcr }, + { "delete", deletehelp, 0, 1, 1, delete }, + { "debug", debughelp, 0, 0, 0, setdebug }, + { "dir", dirhelp, 1, 1, 1, ls }, + { "disconnect", disconhelp, 0, 1, 1, disconnect }, + { "form", formhelp, 0, 1, 1, setform }, + { "get", receivehelp, 1, 1, 1, get }, + { "glob", globhelp, 0, 0, 0, setglob }, + { "hash", hashhelp, 0, 0, 0, sethash }, + { "help", helphelp, 0, 0, 1, help }, + { "idle", idlehelp, 0, 1, 1, ftp_idle }, + { "image", binaryhelp, 0, 1, 1, setbinary }, + { "lcd", lcdhelp, 0, 0, 0, lcd }, + { "ls", lshelp, 1, 1, 1, ls }, + { "macdef", macdefhelp, 0, 0, 0, macdef }, + { "mdelete", mdeletehelp, 1, 1, 1, mdelete }, + { "mdir", mdirhelp, 1, 1, 1, mls }, + { "mget", mgethelp, 1, 1, 1, mget }, + { "mkdir", mkdirhelp, 0, 1, 1, makedir }, + { "mls", mlshelp, 1, 1, 1, mls }, + { "mode", modehelp, 0, 1, 1, setftmode }, + { "modtime", modtimehelp, 0, 1, 1, modtime }, + { "mput", mputhelp, 1, 1, 1, mput }, + { "newer", newerhelp, 1, 1, 1, newer }, + { "nmap", nmaphelp, 0, 0, 1, setnmap }, + { "nlist", nlisthelp, 1, 1, 1, ls }, + { "ntrans", ntranshelp, 0, 0, 1, setntrans }, + { "open", connecthelp, 0, 0, 1, setpeer }, + { "passive", passivehelp, 0, 0, 0, setpassive }, + { "prompt", prompthelp, 0, 0, 0, setprompt }, + { "proxy", proxyhelp, 0, 0, 1, doproxy }, + { "sendport", porthelp, 0, 0, 0, setport }, + { "put", sendhelp, 1, 1, 1, put }, + { "pwd", pwdhelp, 0, 1, 1, pwd }, + { "quit", quithelp, 0, 0, 0, quit }, + { "quote", quotehelp, 1, 1, 1, quote }, + { "recv", receivehelp, 1, 1, 1, get }, + { "reget", regethelp, 1, 1, 1, reget }, + { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus }, + { "rhelp", remotehelp, 0, 1, 1, rmthelp }, + { "rename", renamehelp, 0, 1, 1, renamefile }, + { "reset", resethelp, 0, 1, 1, reset }, + { "restart", restarthelp, 1, 1, 1, restart }, + { "rmdir", rmdirhelp, 0, 1, 1, removedir }, + { "runique", runiquehelp, 0, 0, 1, setrunique }, + { "send", sendhelp, 1, 1, 1, put }, + { "site", sitehelp, 0, 1, 1, site }, + { "size", sizecmdhelp, 1, 1, 1, sizecmd }, + { "status", statushelp, 0, 0, 1, status }, + { "struct", structhelp, 0, 1, 1, setstruct }, + { "system", systemhelp, 0, 1, 1, syst }, + { "sunique", suniquehelp, 0, 0, 1, setsunique }, + { "tenex", tenexhelp, 0, 1, 1, settenex }, + { "trace", tracehelp, 0, 0, 0, settrace }, + { "type", typehelp, 0, 1, 1, settype }, + { "user", userhelp, 0, 1, 1, user }, + { "umask", umaskhelp, 0, 1, 1, do_umask }, + { "verbose", verbosehelp, 0, 0, 0, setverbose }, + { "?", helphelp, 0, 0, 1, help }, + + { "prot", prothelp, 0, 1, 0, sec_prot }, + { "kauth", kauthhelp, 0, 1, 0, kauth }, + { "klist", klisthelp, 0, 1, 0, klist }, + + { 0 }, +}; + +int NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1; diff --git a/crypto/kerberosIV/appl/ftp/ftp/domacro.c b/crypto/kerberosIV/appl/ftp/ftp/domacro.c new file mode 100644 index 0000000..f5a89b9 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/domacro.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1985, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "ftp_locl.h" +RCSID("$Id: domacro.c,v 1.5 1996/11/17 20:23:10 assar Exp $"); + +void +domacro(int argc, char **argv) +{ + int i, j, count = 2, loopflg = 0; + char *cp1, *cp2, line2[200]; + struct cmd *c; + + if (argc < 2 && !another(&argc, &argv, "macro name")) { + printf("Usage: %s macro_name.\n", argv[0]); + code = -1; + return; + } + for (i = 0; i < macnum; ++i) { + if (!strncmp(argv[1], macros[i].mac_name, 9)) { + break; + } + } + if (i == macnum) { + printf("'%s' macro not found.\n", argv[1]); + code = -1; + return; + } + strcpy(line2, line); +TOP: + cp1 = macros[i].mac_start; + while (cp1 != macros[i].mac_end) { + while (isspace(*cp1)) { + cp1++; + } + cp2 = line; + while (*cp1 != '\0') { + switch(*cp1) { + case '\\': + *cp2++ = *++cp1; + break; + case '$': + if (isdigit(*(cp1+1))) { + j = 0; + while (isdigit(*++cp1)) { + j = 10*j + *cp1 - '0'; + } + cp1--; + if (argc - 2 >= j) { + strcpy(cp2, argv[j+1]); + cp2 += strlen(argv[j+1]); + } + break; + } + if (*(cp1+1) == 'i') { + loopflg = 1; + cp1++; + if (count < argc) { + strcpy(cp2, argv[count]); + cp2 += strlen(argv[count]); + } + break; + } + /* intentional drop through */ + default: + *cp2++ = *cp1; + break; + } + if (*cp1 != '\0') { + cp1++; + } + } + *cp2 = '\0'; + makeargv(); + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + code = -1; + } + else if (c == 0) { + printf("?Invalid command\n"); + code = -1; + } + else if (c->c_conn && !connected) { + printf("Not connected.\n"); + code = -1; + } + else { + if (verbose) { + printf("%s\n",line); + } + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) { + putchar('\007'); + } + strcpy(line, line2); + makeargv(); + argc = margc; + argv = margv; + } + if (cp1 != macros[i].mac_end) { + cp1++; + } + } + if (loopflg && ++count < argc) { + goto TOP; + } +} diff --git a/crypto/kerberosIV/appl/ftp/ftp/extern.h b/crypto/kerberosIV/appl/ftp/ftp/extern.h new file mode 100644 index 0000000..b830999 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/extern.h @@ -0,0 +1,167 @@ +/*- + * Copyright (c) 1994 The Regents of the University of California. + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)extern.h 8.3 (Berkeley) 10/9/94 + */ + +/* $Id: extern.h,v 1.13 1997/04/20 05:46:48 assar Exp $ */ + +#include <setjmp.h> +#include <stdlib.h> +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +void abort_remote (FILE *); +void abortpt (int); +void abortrecv (int); +void account (int, char **); +int another (int *, char ***, char *); +void blkfree (char **); +void cd (int, char **); +void cdup (int, char **); +void changetype (int, int); +void cmdabort (int); +void cmdscanner (int); +int command (char *fmt, ...); +int confirm (char *, char *); +FILE *dataconn (char *); +void delete (int, char **); +void disconnect (int, char **); +void do_chmod (int, char **); +void do_umask (int, char **); +void domacro (int, char **); +char *domap (char *); +void doproxy (int, char **); +char *dotrans (char *); +int empty (fd_set *, int); +void fatal (char *); +void get (int, char **); +struct cmd *getcmd (char *); +int getit (int, char **, int, char *); +int getreply (int); +int globulize (char **); +char *gunique (char *); +void help (int, char **); +char *hookup (char *, int); +void ftp_idle (int, char **); +int initconn (void); +void intr (int); +void lcd (int, char **); +int login (char *); +RETSIGTYPE lostpeer (int); +void ls (int, char **); +void macdef (int, char **); +void makeargv (void); +void makedir (int, char **); +void mdelete (int, char **); +void mget (int, char **); +void mls (int, char **); +void modtime (int, char **); +void mput (int, char **); +char *onoff (int); +void newer (int, char **); +void proxtrans (char *, char *, char *); +void psabort (int); +void pswitch (int); +void ptransfer (char *, long, struct timeval *, struct timeval *); +void put (int, char **); +void pwd (int, char **); +void quit (int, char **); +void quote (int, char **); +void quote1 (char *, int, char **); +void recvrequest (char *, char *, char *, char *, int); +void reget (int, char **); +char *remglob (char **, int); +void removedir (int, char **); +void renamefile (int, char **); +void reset (int, char **); +void restart (int, char **); +void rmthelp (int, char **); +void rmtstatus (int, char **); +int ruserpass (char *, char **, char **, char **); +void sendrequest (char *, char *, char *, int); +void setascii (int, char **); +void setbell (int, char **); +void setbinary (int, char **); +void setcase (int, char **); +void setcr (int, char **); +void setdebug (int, char **); +void setform (int, char **); +void setftmode (int, char **); +void setglob (int, char **); +void sethash (int, char **); +void setnmap (int, char **); +void setntrans (int, char **); +void setpassive (int, char **); +void setpeer (int, char **); +void setport (int, char **); +void setprompt (int, char **); +void setrunique (int, char **); +void setstruct (int, char **); +void setsunique (int, char **); +void settenex (int, char **); +void settrace (int, char **); +void settype (int, char **); +void setverbose (int, char **); +void shell (int, char **); +void site (int, char **); +void sizecmd (int, char **); +char *slurpstring (void); +void status (int, char **); +void syst (int, char **); +void tvsub (struct timeval *, struct timeval *, struct timeval *); +void user (int, char **); + +extern jmp_buf abortprox; +extern int abrtflag; +extern struct cmd cmdtab[]; +extern FILE *cout; +extern int data; +extern char *home; +extern jmp_buf jabort; +extern int proxy; +extern char reply_string[]; +extern off_t restart_point; +extern int NCMDS; + +extern char username[32]; +extern char myhostname[]; +extern char *mydomain; diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp.c b/crypto/kerberosIV/appl/ftp/ftp/ftp.c new file mode 100644 index 0000000..cfabda6 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/ftp.c @@ -0,0 +1,1658 @@ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "ftp_locl.h" +RCSID("$Id: ftp.c,v 1.44 1997/05/18 20:00:31 assar Exp $"); + +struct sockaddr_in hisctladdr; +struct sockaddr_in data_addr; +int data = -1; +int abrtflag = 0; +jmp_buf ptabort; +int ptabflg; +int ptflag = 0; +struct sockaddr_in myctladdr; +off_t restart_point = 0; + + +FILE *cin, *cout; + +typedef void (*sighand)(int); + +char * +hookup(char *host, int port) +{ + struct hostent *hp = 0; + int s, len, tos; + static char hostnamebuf[80]; + + memset(&hisctladdr, 0, sizeof (hisctladdr)); + if(inet_aton(host, &hisctladdr.sin_addr)){ + hisctladdr.sin_family = AF_INET; + strncpy(hostnamebuf, host, sizeof(hostnamebuf)); + } else { + hp = gethostbyname(host); + if (hp == NULL) { +#ifdef HAVE_H_ERRNO + warnx("%s: %s", host, hstrerror(h_errno)); +#else + warnx("%s: %s", host, "unknown error"); +#endif + code = -1; + return NULL; + } + hisctladdr.sin_family = hp->h_addrtype; + memmove(&hisctladdr.sin_addr, + hp->h_addr_list[0], + sizeof(hisctladdr.sin_addr)); + strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); + hostnamebuf[sizeof(hostnamebuf) - 1] = '\0'; + } + hostname = hostnamebuf; + s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + if (s < 0) { + warn("socket"); + code = -1; + return (0); + } + hisctladdr.sin_port = port; + while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { + if (hp && hp->h_addr_list[1]) { + int oerrno = errno; + char *ia; + + ia = inet_ntoa(hisctladdr.sin_addr); + errno = oerrno; + warn("connect to address %s", ia); + hp->h_addr_list++; + memmove(&hisctladdr.sin_addr, + hp->h_addr_list[0], + sizeof(hisctladdr.sin_addr)); + fprintf(stdout, "Trying %s...\n", + inet_ntoa(hisctladdr.sin_addr)); + close(s); + s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + if (s < 0) { + warn("socket"); + code = -1; + return (0); + } + continue; + } + warn("connect"); + code = -1; + goto bad; + } + len = sizeof (myctladdr); + if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { + warn("getsockname"); + code = -1; + goto bad; + } +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + tos = IPTOS_LOWDELAY; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) + warn("setsockopt TOS (ignored)"); +#endif + cin = fdopen(s, "r"); + cout = fdopen(s, "w"); + if (cin == NULL || cout == NULL) { + warnx("fdopen failed."); + if (cin) + fclose(cin); + if (cout) + fclose(cout); + code = -1; + goto bad; + } + if (verbose) + printf("Connected to %s.\n", hostname); + if (getreply(0) > 2) { /* read startup message from server */ + if (cin) + fclose(cin); + if (cout) + fclose(cout); + code = -1; + goto bad; + } +#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) + { + int on = 1; + + if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) + < 0 && debug) { + warn("setsockopt"); + } + } +#endif /* SO_OOBINLINE */ + + return (hostname); +bad: + close(s); + return NULL; +} + +int +login(char *host) +{ + char tmp[80]; + char defaultpass[128]; + char *user, *pass, *acct; + int n, aflag = 0; + + char *myname = NULL; + struct passwd *pw = k_getpwuid(getuid()); + if (pw != NULL) + myname = pw->pw_name; + + user = pass = acct = 0; + + if(do_klogin(host)) + printf("\n*** Using plaintext user and password ***\n\n"); + else{ + printf("Kerberos authentication successful.\n\n"); + } + + if (ruserpass(host, &user, &pass, &acct) < 0) { + code = -1; + return (0); + } + while (user == NULL) { + if (myname) + printf("Name (%s:%s): ", host, myname); + else + printf("Name (%s): ", host); + fgets(tmp, sizeof(tmp) - 1, stdin); + tmp[strlen(tmp) - 1] = '\0'; + if (*tmp == '\0') + user = myname; + else + user = tmp; + } + strcpy(username, user); + n = command("USER %s", user); + if (n == CONTINUE) { + if(auth_complete) + pass = myname; + else if (pass == NULL) { + char prompt[128]; + if(myname && + (!strcmp(user, "ftp") || !strcmp(user, "anonymous"))){ + snprintf(defaultpass, sizeof(defaultpass), "%s@%s", myname, mydomain); + snprintf(prompt, sizeof(prompt), "Password (%s): ", defaultpass); + }else{ + strcpy(defaultpass, ""); + snprintf(prompt, sizeof(prompt), "Password: "); + } + pass = defaultpass; + des_read_pw_string (tmp, sizeof(tmp), prompt, 0); + if(tmp[0]) + pass = tmp; + } + n = command("PASS %s", pass); + } + if (n == CONTINUE) { + aflag++; + acct = tmp; + des_read_pw_string(acct, 128, "Account:", 0); + n = command("ACCT %s", acct); + } + if (n != COMPLETE) { + warnx("Login failed."); + return (0); + } + if (!aflag && acct != NULL) + command("ACCT %s", acct); + if (proxy) + return (1); + for (n = 0; n < macnum; ++n) { + if (!strcmp("init", macros[n].mac_name)) { + strcpy(line, "$init"); + makeargv(); + domacro(margc, margv); + break; + } + } + sec_set_protection_level(); + return (1); +} + +void +cmdabort(int sig) +{ + + printf("\n"); + fflush(stdout); + abrtflag++; + if (ptflag) + longjmp(ptabort,1); +} + +int +command(char *fmt, ...) +{ + va_list ap; + int r; + sighand oldintr; + + abrtflag = 0; + if (cout == NULL) { + warn("No control connection for command"); + code = -1; + return (0); + } + oldintr = signal(SIGINT, cmdabort); + va_start(ap, fmt); + if(debug){ + printf("---> "); + if (strncmp("PASS ", fmt, 5) == 0) + printf("PASS XXXX"); + else + vfprintf(stdout, fmt, ap); + va_start(ap, fmt); + } + if(auth_complete) + krb4_write_enc(cout, fmt, ap); + else + vfprintf(cout, fmt, ap); + va_end(ap); + if(debug){ + printf("\n"); + fflush(stdout); + } + fprintf(cout, "\r\n"); + fflush(cout); + cpend = 1; + r = getreply(!strcmp(fmt, "QUIT")); + if (abrtflag && oldintr != SIG_IGN) + (*oldintr)(SIGINT); + signal(SIGINT, oldintr); + return (r); +} + +char reply_string[BUFSIZ]; /* last line of previous reply */ + +int +getreply(int expecteof) +{ + char *p; + char *lead_string; + int c; + struct sigaction sa, osa; + char buf[1024]; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = cmdabort; + sigaction(SIGINT, &sa, &osa); + + p = buf; + + while(1){ + c = getc(cin); + switch(c){ + case EOF: + if (expecteof) { + sigaction(SIGINT,&osa, NULL); + code = 221; + return 0; + } + lostpeer(0); + if (verbose) { + printf("421 Service not available, " + "remote server has closed connection\n"); + fflush(stdout); + } + code = 421; + return (4); + break; + case IAC: + c = getc(cin); + if(c == WILL || c == WONT) + fprintf(cout, "%c%c%c", IAC, DONT, getc(cin)); + if(c == DO || c == DONT) + fprintf(cout, "%c%c%c", IAC, WONT, getc(cin)); + continue; + case '\n': + *p++ = 0; + if(isdigit(buf[0])){ + sscanf(buf, "%d", &code); + if(code == 631){ + krb4_read_mic(buf); + sscanf(buf, "%d", &code); + lead_string = "S:"; + } else if(code == 632){ + krb4_read_enc(buf); + sscanf(buf, "%d", &code); + lead_string = "P:"; + }else if(code == 633){ + printf("Received confidential reply!\n"); + }else if(auth_complete) + lead_string = "!!"; + else + lead_string = ""; + if(verbose > 0 || (verbose > -1 && code > 499)) + fprintf(stdout, "%s%s\n", lead_string, buf); + if(buf[3] == ' '){ + strcpy(reply_string, buf); + if (code >= 200) + cpend = 0; + sigaction(SIGINT, &osa, NULL); + if (code == 421) + lostpeer(0); +#if 1 + if (abrtflag && + osa.sa_handler != cmdabort && + osa.sa_handler != SIG_IGN) + osa.sa_handler(SIGINT); +#endif + if(code == 227){ + char *p, *q; + pasv[0] = 0; + p = strchr(reply_string, '('); + if(p){ + p++; + q = strchr(p, ')'); + if(q){ + strncpy(pasv, p, q - p); + pasv[q - p] = 0; + } + } + } + return code / 100; + } + }else{ + if(verbose > 0 || (verbose > -1 && code > 499)){ + if(auth_complete) + fprintf(stdout, "!!"); + fprintf(stdout, "%s\n", buf); + } + } + p = buf; + continue; + default: + *p++ = c; + } + } + +} + + +#if 0 +int +getreply(int expecteof) +{ + int c, n; + int dig; + int originalcode = 0, continuation = 0; + sighand oldintr; + int pflag = 0; + char *cp, *pt = pasv; + + oldintr = signal(SIGINT, cmdabort); + for (;;) { + dig = n = code = 0; + cp = reply_string; + while ((c = getc(cin)) != '\n') { + if (c == IAC) { /* handle telnet commands */ + switch (c = getc(cin)) { + case WILL: + case WONT: + c = getc(cin); + fprintf(cout, "%c%c%c", IAC, DONT, c); + fflush(cout); + break; + case DO: + case DONT: + c = getc(cin); + fprintf(cout, "%c%c%c", IAC, WONT, c); + fflush(cout); + break; + default: + break; + } + continue; + } + dig++; + if (c == EOF) { + if (expecteof) { + signal(SIGINT,oldintr); + code = 221; + return (0); + } + lostpeer(0); + if (verbose) { + printf("421 Service not available, remote server has closed connection\n"); + fflush(stdout); + } + code = 421; + return (4); + } + if (c != '\r' && (verbose > 0 || + (verbose > -1 && n == '5' && dig > 4))) { + if (proxflag && + (dig == 1 || dig == 5 && verbose == 0)) + printf("%s:",hostname); + putchar(c); + } + if (dig < 4 && isdigit(c)) + code = code * 10 + (c - '0'); + if (!pflag && code == 227) + pflag = 1; + if (dig > 4 && pflag == 1 && isdigit(c)) + pflag = 2; + if (pflag == 2) { + if (c != '\r' && c != ')') + *pt++ = c; + else { + *pt = '\0'; + pflag = 3; + } + } + if (dig == 4 && c == '-') { + if (continuation) + code = 0; + continuation++; + } + if (n == 0) + n = c; + if (cp < &reply_string[sizeof(reply_string) - 1]) + *cp++ = c; + } + if (verbose > 0 || verbose > -1 && n == '5') { + putchar(c); + fflush (stdout); + } + if (continuation && code != originalcode) { + if (originalcode == 0) + originalcode = code; + continue; + } + *cp = '\0'; + if(auth_complete){ + if(code == 631) + krb4_read_mic(reply_string); + else + krb4_read_enc(reply_string); + n = code / 100 + '0'; + } + + if (n != '1') + cpend = 0; + signal(SIGINT,oldintr); + if (code == 421 || originalcode == 421) + lostpeer(0); + if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) + (*oldintr)(SIGINT); + return (n - '0'); + } +} +#endif + +int +empty(fd_set *mask, int sec) +{ + struct timeval t; + + t.tv_sec = (long) sec; + t.tv_usec = 0; + return (select(32, mask, NULL, NULL, &t)); +} + +jmp_buf sendabort; + +static RETSIGTYPE +abortsend(int sig) +{ + + mflag = 0; + abrtflag = 0; + printf("\nsend aborted\nwaiting for remote to finish abort\n"); + fflush(stdout); + longjmp(sendabort, 1); +} + +#define HASHBYTES 1024 + +static int +copy_stream(FILE *from, FILE *to) +{ + static size_t bufsize; + static char *buf; + int n; + int bytes = 0; + int werr; + int hashbytes = HASHBYTES; + struct stat st; + +#ifdef HAVE_MMAP + void *chunk; + +#ifndef MAP_FAILED +#define MAP_FAILED (-1) +#endif + + if(fstat(fileno(from), &st) == 0 && S_ISREG(st.st_mode)){ + chunk = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fileno(from), 0); + if (chunk != (void *)MAP_FAILED) { + int res; + + res = sec_write(fileno(to), chunk, st.st_size); + if (munmap(chunk, st.st_size) < 0) + warn ("munmap"); + sec_fflush(to); + return res; + } + } +#endif + + buf = alloc_buffer (buf, &bufsize, + fstat(fileno(from), &st) >= 0 ? &st : NULL); + if (buf == NULL) + return -1; + + while((n = read(fileno(from), buf, bufsize)) > 0){ + werr = sec_write(fileno(to), buf, n); + if(werr < 0) + break; + bytes += werr; + while(hash && bytes > hashbytes){ + putchar('#'); + hashbytes += HASHBYTES; + } + } + sec_fflush(to); + if(n < 0) + warn("local"); + + if(werr < 0){ + if(errno != EPIPE) + warn("netout"); + bytes = -1; + } + return bytes; +} + +void +sendrequest(char *cmd, char *local, char *remote, int printnames) +{ + struct stat st; + struct timeval start, stop; + int c, d; + FILE *fin, *dout = 0; + int (*closefunc) (FILE *); + RETSIGTYPE (*oldintr)(), (*oldintp)(); + long bytes = 0, hashbytes = HASHBYTES; + char *lmode; + + if (verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + } + if (proxy) { + proxtrans(cmd, local, remote); + return; + } + if (curtype != type) + changetype(type, 0); + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + lmode = "w"; + if (setjmp(sendabort)) { + while (cpend) { + getreply(0); + } + if (data >= 0) { + close(data); + data = -1; + } + if (oldintr) + signal(SIGINT,oldintr); + if (oldintp) + signal(SIGPIPE,oldintp); + code = -1; + return; + } + oldintr = signal(SIGINT, abortsend); + if (strcmp(local, "-") == 0) + fin = stdin; + else if (*local == '|') { + oldintp = signal(SIGPIPE,SIG_IGN); + fin = popen(local + 1, "r"); + if (fin == NULL) { + warn("%s", local + 1); + signal(SIGINT, oldintr); + signal(SIGPIPE, oldintp); + code = -1; + return; + } + closefunc = pclose; + } else { + fin = fopen(local, "r"); + if (fin == NULL) { + warn("local: %s", local); + signal(SIGINT, oldintr); + code = -1; + return; + } + closefunc = fclose; + if (fstat(fileno(fin), &st) < 0 || + (st.st_mode&S_IFMT) != S_IFREG) { + fprintf(stdout, "%s: not a plain file.\n", local); + signal(SIGINT, oldintr); + fclose(fin); + code = -1; + return; + } + } + if (initconn()) { + signal(SIGINT, oldintr); + if (oldintp) + signal(SIGPIPE, oldintp); + code = -1; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + if (setjmp(sendabort)) + goto abort; + + if (restart_point && + (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { + int rc; + + switch (curtype) { + case TYPE_A: + rc = fseek(fin, (long) restart_point, SEEK_SET); + break; + case TYPE_I: + case TYPE_L: + rc = lseek(fileno(fin), restart_point, SEEK_SET); + break; + } + if (rc < 0) { + warn("local: %s", local); + restart_point = 0; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + if (command("REST %ld", (long) restart_point) + != CONTINUE) { + restart_point = 0; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + restart_point = 0; + lmode = "r+w"; + } + if (remote) { + if (command("%s %s", cmd, remote) != PRELIM) { + signal(SIGINT, oldintr); + if (oldintp) + signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + } else + if (command("%s", cmd) != PRELIM) { + signal(SIGINT, oldintr); + if (oldintp) + signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + dout = dataconn(lmode); + if (dout == NULL) + goto abort; + set_buffer_size(fileno(dout), 0); + gettimeofday(&start, (struct timezone *)0); + oldintp = signal(SIGPIPE, SIG_IGN); + switch (curtype) { + + case TYPE_I: + case TYPE_L: + errno = d = c = 0; + bytes = copy_stream(fin, dout); + break; + + case TYPE_A: + while ((c = getc(fin)) != EOF) { + if (c == '\n') { + while (hash && (bytes >= hashbytes)) { + putchar('#'); + fflush(stdout); + hashbytes += HASHBYTES; + } + if (ferror(dout)) + break; + sec_putc('\r', dout); + bytes++; + } + sec_putc(c, dout); + bytes++; + } + sec_fflush(dout); + if (hash) { + if (bytes < hashbytes) + putchar('#'); + putchar('\n'); + fflush(stdout); + } + if (ferror(fin)) + warn("local: %s", local); + if (ferror(dout)) { + if (errno != EPIPE) + warn("netout"); + bytes = -1; + } + break; + } + if (closefunc != NULL) + (*closefunc)(fin); + fclose(dout); + gettimeofday(&stop, (struct timezone *)0); + getreply(0); + signal(SIGINT, oldintr); + if (oldintp) + signal(SIGPIPE, oldintp); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); + return; +abort: + signal(SIGINT, oldintr); + if (oldintp) + signal(SIGPIPE, oldintp); + if (!cpend) { + code = -1; + return; + } + if (data >= 0) { + close(data); + data = -1; + } + if (dout) + fclose(dout); + getreply(0); + code = -1; + if (closefunc != NULL && fin != NULL) + (*closefunc)(fin); + gettimeofday(&stop, (struct timezone *)0); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); +} + +jmp_buf recvabort; + +void +abortrecv(int sig) +{ + + mflag = 0; + abrtflag = 0; + printf("\nreceive aborted\nwaiting for remote to finish abort\n"); + fflush(stdout); + longjmp(recvabort, 1); +} + +void +recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) +{ + FILE *fout, *din = 0; + int (*closefunc) (FILE *); + sighand oldintr, oldintp; + int c, d, is_retr, tcrflag, bare_lfs = 0; + static size_t bufsize; + static char *buf; + long bytes = 0, hashbytes = HASHBYTES; + struct timeval start, stop; + struct stat st; + + is_retr = strcmp(cmd, "RETR") == 0; + if (is_retr && verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + } + if (proxy && is_retr) { + proxtrans(cmd, local, remote); + return; + } + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + tcrflag = !crflag && is_retr; + if (setjmp(recvabort)) { + while (cpend) { + getreply(0); + } + if (data >= 0) { + close(data); + data = -1; + } + if (oldintr) + signal(SIGINT, oldintr); + code = -1; + return; + } + oldintr = signal(SIGINT, abortrecv); + if (strcmp(local, "-") && *local != '|') { + if (access(local, 2) < 0) { + char *dir = strrchr(local, '/'); + + if (errno != ENOENT && errno != EACCES) { + warn("local: %s", local); + signal(SIGINT, oldintr); + code = -1; + return; + } + if (dir != NULL) + *dir = 0; + d = access(dir ? local : ".", 2); + if (dir != NULL) + *dir = '/'; + if (d < 0) { + warn("local: %s", local); + signal(SIGINT, oldintr); + code = -1; + return; + } + if (!runique && errno == EACCES && + chmod(local, 0600) < 0) { + warn("local: %s", local); + signal(SIGINT, oldintr); + signal(SIGINT, oldintr); + code = -1; + return; + } + if (runique && errno == EACCES && + (local = gunique(local)) == NULL) { + signal(SIGINT, oldintr); + code = -1; + return; + } + } + else if (runique && (local = gunique(local)) == NULL) { + signal(SIGINT, oldintr); + code = -1; + return; + } + } + if (!is_retr) { + if (curtype != TYPE_A) + changetype(TYPE_A, 0); + } else if (curtype != type) + changetype(type, 0); + if (initconn()) { + signal(SIGINT, oldintr); + code = -1; + return; + } + if (setjmp(recvabort)) + goto abort; + if (is_retr && restart_point && + command("REST %ld", (long) restart_point) != CONTINUE) + return; + if (remote) { + if (command("%s %s", cmd, remote) != PRELIM) { + signal(SIGINT, oldintr); + return; + } + } else { + if (command("%s", cmd) != PRELIM) { + signal(SIGINT, oldintr); + return; + } + } + din = dataconn("r"); + if (din == NULL) + goto abort; + set_buffer_size(fileno(din), 1); + if (strcmp(local, "-") == 0) + fout = stdout; + else if (*local == '|') { + oldintp = signal(SIGPIPE, SIG_IGN); + fout = popen(local + 1, "w"); + if (fout == NULL) { + warn("%s", local+1); + goto abort; + } + closefunc = pclose; + } else { + fout = fopen(local, lmode); + if (fout == NULL) { + warn("local: %s", local); + goto abort; + } + closefunc = fclose; + } + buf = alloc_buffer (buf, &bufsize, + fstat(fileno(fout), &st) >= 0 ? &st : NULL); + if (buf == NULL) + goto abort; + + gettimeofday(&start, (struct timezone *)0); + switch (curtype) { + + case TYPE_I: + case TYPE_L: + if (restart_point && + lseek(fileno(fout), restart_point, SEEK_SET) < 0) { + warn("local: %s", local); + if (closefunc != NULL) + (*closefunc)(fout); + return; + } + errno = d = 0; + while ((c = sec_read(fileno(din), buf, bufsize)) > 0) { + if ((d = write(fileno(fout), buf, c)) != c) + break; + bytes += c; + if (hash) { + while (bytes >= hashbytes) { + putchar('#'); + hashbytes += HASHBYTES; + } + fflush(stdout); + } + } + if (hash && bytes > 0) { + if (bytes < HASHBYTES) + putchar('#'); + putchar('\n'); + fflush(stdout); + } + if (c < 0) { + if (errno != EPIPE) + warn("netin"); + bytes = -1; + } + if (d < c) { + if (d < 0) + warn("local: %s", local); + else + warnx("%s: short write", local); + } + break; + + case TYPE_A: + if (restart_point) { + int i, n, ch; + + if (fseek(fout, 0L, SEEK_SET) < 0) + goto done; + n = restart_point; + for (i = 0; i++ < n;) { + if ((ch = sec_getc(fout)) == EOF) + goto done; + if (ch == '\n') + i++; + } + if (fseek(fout, 0L, SEEK_CUR) < 0) { + done: + warn("local: %s", local); + if (closefunc != NULL) + (*closefunc)(fout); + return; + } + } + + while ((c = sec_getc(din)) != EOF) { + if (c == '\n') + bare_lfs++; + while (c == '\r') { + while (hash && (bytes >= hashbytes)) { + putchar('#'); + fflush(stdout); + hashbytes += HASHBYTES; + } + bytes++; + if ((c = sec_getc(din)) != '\n' || tcrflag) { + if (ferror(fout)) + goto break2; + putc('\r', fout); + if (c == '\0') { + bytes++; + goto contin2; + } + if (c == EOF) + goto contin2; + } + } + putc(c, fout); + bytes++; + contin2: ; + } + break2: + if (bare_lfs) { + printf("WARNING! %d bare linefeeds received in ASCII mode\n", + bare_lfs); + printf("File may not have transferred correctly.\n"); + } + if (hash) { + if (bytes < hashbytes) + putchar('#'); + putchar('\n'); + fflush(stdout); + } + if (ferror(din)) { + if (errno != EPIPE) + warn("netin"); + bytes = -1; + } + if (ferror(fout)) + warn("local: %s", local); + break; + } + if (closefunc != NULL) + (*closefunc)(fout); + signal(SIGINT, oldintr); + if (oldintp) + signal(SIGPIPE, oldintp); + fclose(din); + gettimeofday(&stop, (struct timezone *)0); + getreply(0); + if (bytes > 0 && is_retr) + ptransfer("received", bytes, &start, &stop); + return; +abort: + + /* abort using RFC959 recommended IP,SYNC sequence */ + + if (oldintp) + signal(SIGPIPE, oldintr); + signal(SIGINT, SIG_IGN); + if (!cpend) { + code = -1; + signal(SIGINT, oldintr); + return; + } + + abort_remote(din); + code = -1; + if (data >= 0) { + close(data); + data = -1; + } + if (closefunc != NULL && fout != NULL) + (*closefunc)(fout); + if (din) + fclose(din); + gettimeofday(&stop, (struct timezone *)0); + if (bytes > 0) + ptransfer("received", bytes, &start, &stop); + signal(SIGINT, oldintr); +} + +/* + * Need to start a listen on the data channel before we send the command, + * otherwise the server's connect may fail. + */ +int +initconn(void) +{ + int result, len, tmpno = 0; + int on = 1; + int a0, a1, a2, a3, p0, p1; + + if (passivemode) { + data = socket(AF_INET, SOCK_STREAM, 0); + if (data < 0) { + perror("ftp: socket"); + return(1); + } +#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) + if ((options & SO_DEBUG) && + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, + sizeof (on)) < 0) + perror("ftp: setsockopt (ignored)"); +#endif + if (command("PASV") != COMPLETE) { + printf("Passive mode refused.\n"); + goto bad; + } + + /* + * What we've got at this point is a string of comma + * separated one-byte unsigned integer values. + * The first four are the an IP address. The fifth is + * the MSB of the port number, the sixth is the LSB. + * From that we'll prepare a sockaddr_in. + */ + + if (sscanf(pasv,"%d,%d,%d,%d,%d,%d", + &a0, &a1, &a2, &a3, &p0, &p1) != 6) { + printf("Passive mode address scan failure. " + "Shouldn't happen!\n"); + goto bad; + } + if(a0 < 0 || a0 > 255 || + a1 < 0 || a1 > 255 || + a2 < 0 || a2 > 255 || + a3 < 0 || a3 > 255 || + p0 < 0 || p0 > 255 || + p1 < 0 || p1 > 255){ + printf("Can't parse passive mode string.\n"); + goto bad; + } + + memset(&data_addr, 0, sizeof(data_addr)); + data_addr.sin_family = AF_INET; + data_addr.sin_addr.s_addr = htonl((a0 << 24) | (a1 << 16) | + (a2 << 8) | a3); + data_addr.sin_port = htons((p0 << 8) | p1); + + if (connect(data, (struct sockaddr *)&data_addr, + sizeof(data_addr)) < 0) { + perror("ftp: connect"); + goto bad; + } +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, + sizeof(int)) < 0) + perror("ftp: setsockopt TOS (ignored)"); +#endif + return(0); + } + +noport: + data_addr = myctladdr; + if (sendport) + data_addr.sin_port = 0; /* let system pick one */ + if (data != -1) + close(data); + data = socket(AF_INET, SOCK_STREAM, 0); + if (data < 0) { + warn("socket"); + if (tmpno) + sendport = 1; + return (1); + } +#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) + if (!sendport) + if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { + warn("setsockopt (reuse address)"); + goto bad; + } +#endif + if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { + warn("bind"); + goto bad; + } +#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT) + if (options & SO_DEBUG && + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) + warn("setsockopt (ignored)"); +#endif + len = sizeof (data_addr); + if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { + warn("getsockname"); + goto bad; + } + if (listen(data, 1) < 0) + warn("listen"); + if (sendport) { + unsigned int a = ntohl(data_addr.sin_addr.s_addr); + unsigned int p = ntohs(data_addr.sin_port); + result = command("PORT %d,%d,%d,%d,%d,%d", + (a >> 24) & 0xff, + (a >> 16) & 0xff, + (a >> 8) & 0xff, + a & 0xff, + (p >> 8) & 0xff, + p & 0xff); + if (result == ERROR && sendport == -1) { + sendport = 0; + tmpno = 1; + goto noport; + } + return (result != COMPLETE); + } + if (tmpno) + sendport = 1; +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) + warn("setsockopt TOS (ignored)"); +#endif + return (0); +bad: + close(data), data = -1; + if (tmpno) + sendport = 1; + return (1); +} + +FILE * +dataconn(char *lmode) +{ + struct sockaddr_in from; + int s, fromlen = sizeof (from), tos; + + if (passivemode) + return (fdopen(data, lmode)); + + s = accept(data, (struct sockaddr *) &from, &fromlen); + if (s < 0) { + warn("accept"); + close(data), data = -1; + return (NULL); + } + close(data); + data = s; +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + tos = IPTOS_THROUGHPUT; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) + warn("setsockopt TOS (ignored)"); +#endif + return (fdopen(data, lmode)); +} + +void +ptransfer(char *direction, long int bytes, + struct timeval *t0, struct timeval *t1) +{ + struct timeval td; + float s; + float bs; + int prec; + char *unit; + + if (verbose) { + td.tv_sec = t1->tv_sec - t0->tv_sec; + td.tv_usec = t1->tv_usec - t0->tv_usec; + if(td.tv_usec < 0){ + td.tv_sec--; + td.tv_usec += 1000000; + } + s = td.tv_sec + (td.tv_usec / 1000000.); + bs = bytes / (s?s:1); + if(bs >= 1048576){ + bs /= 1048576; + unit = "M"; + prec = 2; + }else if(bs >= 1024){ + bs /= 1024; + unit = "k"; + prec = 1; + }else{ + unit = ""; + prec = 0; + } + + printf("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n", + bytes, direction, s, prec, bs, unit); + } +} + +void +psabort(int sig) +{ + + abrtflag++; +} + +void +pswitch(int flag) +{ + sighand oldintr; + static struct comvars { + int connect; + char name[MaxHostNameLen]; + struct sockaddr_in mctl; + struct sockaddr_in hctl; + FILE *in; + FILE *out; + int tpe; + int curtpe; + int cpnd; + int sunqe; + int runqe; + int mcse; + int ntflg; + char nti[17]; + char nto[17]; + int mapflg; + char mi[MaxPathLen]; + char mo[MaxPathLen]; + } proxstruct, tmpstruct; + struct comvars *ip, *op; + + abrtflag = 0; + oldintr = signal(SIGINT, psabort); + if (flag) { + if (proxy) + return; + ip = &tmpstruct; + op = &proxstruct; + proxy++; + } else { + if (!proxy) + return; + ip = &proxstruct; + op = &tmpstruct; + proxy = 0; + } + ip->connect = connected; + connected = op->connect; + if (hostname) { + strncpy(ip->name, hostname, sizeof(ip->name) - 1); + ip->name[strlen(ip->name)] = '\0'; + } else + ip->name[0] = 0; + hostname = op->name; + ip->hctl = hisctladdr; + hisctladdr = op->hctl; + ip->mctl = myctladdr; + myctladdr = op->mctl; + ip->in = cin; + cin = op->in; + ip->out = cout; + cout = op->out; + ip->tpe = type; + type = op->tpe; + ip->curtpe = curtype; + curtype = op->curtpe; + ip->cpnd = cpend; + cpend = op->cpnd; + ip->sunqe = sunique; + sunique = op->sunqe; + ip->runqe = runique; + runique = op->runqe; + ip->mcse = mcase; + mcase = op->mcse; + ip->ntflg = ntflag; + ntflag = op->ntflg; + strncpy(ip->nti, ntin, 16); + (ip->nti)[strlen(ip->nti)] = '\0'; + strcpy(ntin, op->nti); + strncpy(ip->nto, ntout, 16); + (ip->nto)[strlen(ip->nto)] = '\0'; + strcpy(ntout, op->nto); + ip->mapflg = mapflag; + mapflag = op->mapflg; + strncpy(ip->mi, mapin, MaxPathLen - 1); + (ip->mi)[strlen(ip->mi)] = '\0'; + strcpy(mapin, op->mi); + strncpy(ip->mo, mapout, MaxPathLen - 1); + (ip->mo)[strlen(ip->mo)] = '\0'; + strcpy(mapout, op->mo); + signal(SIGINT, oldintr); + if (abrtflag) { + abrtflag = 0; + (*oldintr)(SIGINT); + } +} + +void +abortpt(int sig) +{ + + printf("\n"); + fflush(stdout); + ptabflg++; + mflag = 0; + abrtflag = 0; + longjmp(ptabort, 1); +} + +void +proxtrans(char *cmd, char *local, char *remote) +{ + sighand oldintr; + int secndflag = 0, prox_type, nfnd; + char *cmd2; + fd_set mask; + + if (strcmp(cmd, "RETR")) + cmd2 = "RETR"; + else + cmd2 = runique ? "STOU" : "STOR"; + if ((prox_type = type) == 0) { + if (unix_server && unix_proxy) + prox_type = TYPE_I; + else + prox_type = TYPE_A; + } + if (curtype != prox_type) + changetype(prox_type, 1); + if (command("PASV") != COMPLETE) { + printf("proxy server does not support third party transfers.\n"); + return; + } + pswitch(0); + if (!connected) { + printf("No primary connection\n"); + pswitch(1); + code = -1; + return; + } + if (curtype != prox_type) + changetype(prox_type, 1); + if (command("PORT %s", pasv) != COMPLETE) { + pswitch(1); + return; + } + if (setjmp(ptabort)) + goto abort; + oldintr = signal(SIGINT, abortpt); + if (command("%s %s", cmd, remote) != PRELIM) { + signal(SIGINT, oldintr); + pswitch(1); + return; + } + sleep(2); + pswitch(1); + secndflag++; + if (command("%s %s", cmd2, local) != PRELIM) + goto abort; + ptflag++; + getreply(0); + pswitch(0); + getreply(0); + signal(SIGINT, oldintr); + pswitch(1); + ptflag = 0; + printf("local: %s remote: %s\n", local, remote); + return; +abort: + signal(SIGINT, SIG_IGN); + ptflag = 0; + if (strcmp(cmd, "RETR") && !proxy) + pswitch(1); + else if (!strcmp(cmd, "RETR") && proxy) + pswitch(0); + if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ + if (command("%s %s", cmd2, local) != PRELIM) { + pswitch(0); + if (cpend) + abort_remote((FILE *) NULL); + } + pswitch(1); + if (ptabflg) + code = -1; + signal(SIGINT, oldintr); + return; + } + if (cpend) + abort_remote((FILE *) NULL); + pswitch(!proxy); + if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ + if (command("%s %s", cmd2, local) != PRELIM) { + pswitch(0); + if (cpend) + abort_remote((FILE *) NULL); + pswitch(1); + if (ptabflg) + code = -1; + signal(SIGINT, oldintr); + return; + } + } + if (cpend) + abort_remote((FILE *) NULL); + pswitch(!proxy); + if (cpend) { + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask, 10)) <= 0) { + if (nfnd < 0) { + warn("abort"); + } + if (ptabflg) + code = -1; + lostpeer(0); + } + getreply(0); + getreply(0); + } + if (proxy) + pswitch(0); + pswitch(1); + if (ptabflg) + code = -1; + signal(SIGINT, oldintr); +} + +void +reset(int argc, char **argv) +{ + fd_set mask; + int nfnd = 1; + + FD_ZERO(&mask); + while (nfnd > 0) { + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,0)) < 0) { + warn("reset"); + code = -1; + lostpeer(0); + } + else if (nfnd) { + getreply(0); + } + } +} + +char * +gunique(char *local) +{ + static char new[MaxPathLen]; + char *cp = strrchr(local, '/'); + int d, count=0; + char ext = '1'; + + if (cp) + *cp = '\0'; + d = access(cp ? local : ".", 2); + if (cp) + *cp = '/'; + if (d < 0) { + warn("local: %s", local); + return NULL; + } + strcpy(new, local); + cp = new + strlen(new); + *cp++ = '.'; + while (!d) { + if (++count == 100) { + printf("runique: can't find unique file name.\n"); + return NULL; + } + *cp++ = ext; + *cp = '\0'; + if (ext == '9') + ext = '0'; + else + ext++; + if ((d = access(new, 0)) < 0) + break; + if (ext != '0') + cp--; + else if (*(cp - 2) == '.') + *(cp - 1) = '1'; + else { + *(cp - 2) = *(cp - 2) + 1; + cp--; + } + } + return (new); +} + +void +abort_remote(FILE *din) +{ + char buf[BUFSIZ]; + int nfnd; + fd_set mask; + + /* + * send IAC in urgent mode instead of DM because 4.3BSD places oob mark + * after urgent byte rather than before as is protocol now + */ + snprintf(buf, sizeof(buf), "%c%c%c", IAC, IP, IAC); + if (send(fileno(cout), buf, 3, MSG_OOB) != 3) + warn("abort"); + fprintf(cout,"%cABOR\r\n", DM); + fflush(cout); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if (din) { + FD_SET(fileno(din), &mask); + } + if ((nfnd = empty(&mask, 10)) <= 0) { + if (nfnd < 0) { + warn("abort"); + } + if (ptabflg) + code = -1; + lostpeer(0); + } + if (din && FD_ISSET(fileno(din), &mask)) { + while (read(fileno(din), buf, BUFSIZ) > 0) + /* LOOP */; + } + if (getreply(0) == ERROR && code == 552) { + /* 552 needed for nic style abort */ + getreply(0); + } + getreply(0); +} diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h new file mode 100644 index 0000000..6ead793 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: ftp_locl.h,v 1.29 1997/05/20 18:40:28 bg Exp $ */ + +#ifndef __FTP_LOCL_H__ +#define __FTP_LOCL_H__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/cdefs.h> + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif + +#ifdef HAVE_ARPA_FTP_H +#include <arpa/ftp.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif + +#include <errno.h> +#include <ctype.h> +#include <glob.h> +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +#include <err.h> + +#ifdef SOCKS +#include <socks.h> +extern int LIBPREFIX(fclose) __P((FILE *)); +#endif + +#include "ftp_var.h" +#include "extern.h" +#include "common.h" +#include "pathnames.h" + +#include <des.h> + +#include <krb.h> + +#include "krb4.h" + +#include "roken.h" + +#if defined(__sun__) && !defined(__svr4) +int fclose(FILE*); +int pclose(FILE*); +#endif + +#endif /* __FTP_LOCL_H__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp_var.h b/crypto/kerberosIV/appl/ftp/ftp/ftp_var.h new file mode 100644 index 0000000..ffac59a --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/ftp_var.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)ftp_var.h 8.4 (Berkeley) 10/9/94 + */ + +/* + * FTP global variables. + */ + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#include <setjmp.h> + +/* + * Options and other state info. + */ +extern int trace; /* trace packets exchanged */ +extern int hash; /* print # for each buffer transferred */ +extern int sendport; /* use PORT cmd for each data connection */ +extern int verbose; /* print messages coming back from server */ +extern int connected; /* connected to server */ +extern int fromatty; /* input is from a terminal */ +extern int interactive; /* interactively prompt on m* cmds */ +extern int debug; /* debugging level */ +extern int bell; /* ring bell on cmd completion */ +extern int doglob; /* glob local file names */ +extern int autologin; /* establish user account on connection */ +extern int proxy; /* proxy server connection active */ +extern int proxflag; /* proxy connection exists */ +extern int sunique; /* store files on server with unique name */ +extern int runique; /* store local files with unique name */ +extern int mcase; /* map upper to lower case for mget names */ +extern int ntflag; /* use ntin ntout tables for name translation */ +extern int mapflag; /* use mapin mapout templates on file names */ +extern int code; /* return/reply code for ftp command */ +extern int crflag; /* if 1, strip car. rets. on ascii gets */ +extern char pasv[64]; /* passive port for proxy data connection */ +extern int passivemode; /* passive mode enabled */ +extern char *altarg; /* argv[1] with no shell-like preprocessing */ +extern char ntin[17]; /* input translation table */ +extern char ntout[17]; /* output translation table */ +extern char mapin[MaxPathLen]; /* input map template */ +extern char mapout[MaxPathLen]; /* output map template */ +extern char typename[32]; /* name of file transfer type */ +extern int type; /* requested file transfer type */ +extern int curtype; /* current file transfer type */ +extern char structname[32]; /* name of file transfer structure */ +extern int stru; /* file transfer structure */ +extern char formname[32]; /* name of file transfer format */ +extern int form; /* file transfer format */ +extern char modename[32]; /* name of file transfer mode */ +extern int mode; /* file transfer mode */ +extern char bytename[32]; /* local byte size in ascii */ +extern int bytesize; /* local byte size in binary */ + +extern char *hostname; /* name of host connected to */ +extern int unix_server; /* server is unix, can use binary for ascii */ +extern int unix_proxy; /* proxy is unix, can use binary for ascii */ + +extern jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ + +extern char line[200]; /* input line buffer */ +extern char *stringbase; /* current scan point in line buffer */ +extern char argbuf[200]; /* argument storage buffer */ +extern char *argbase; /* current storage point in arg buffer */ +extern int margc; /* count of arguments on input line */ +extern char **margv; /* args parsed from input line */ +extern int margvlen; /* how large margv is currently */ +extern int cpend; /* flag: if != 0, then pending server reply */ +extern int mflag; /* flag: if != 0, then active multi command */ + +extern int options; /* used during socket creation */ + +/* + * Format of command table. + */ +struct cmd { + char *c_name; /* name of command */ + char *c_help; /* help string */ + char c_bell; /* give bell when command completes */ + char c_conn; /* must be connected to use command */ + char c_proxy; /* proxy server may execute */ + void (*c_handler) (int, char **); /* function to call */ +}; + +struct macel { + char mac_name[9]; /* macro name */ + char *mac_start; /* start of macro in macbuf */ + char *mac_end; /* end of macro in macbuf */ +}; + +extern int macnum; /* number of defined macros */ +extern struct macel macros[16]; +extern char macbuf[4096]; + + diff --git a/crypto/kerberosIV/appl/ftp/ftp/globals.c b/crypto/kerberosIV/appl/ftp/ftp/globals.c new file mode 100644 index 0000000..7199e65 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/globals.c @@ -0,0 +1,76 @@ +#include "ftp_locl.h" +RCSID("$Id: globals.c,v 1.6 1996/08/26 22:46:26 assar Exp $"); + +/* + * Options and other state info. + */ +int trace; /* trace packets exchanged */ +int hash; /* print # for each buffer transferred */ +int sendport; /* use PORT cmd for each data connection */ +int verbose; /* print messages coming back from server */ +int connected; /* connected to server */ +int fromatty; /* input is from a terminal */ +int interactive; /* interactively prompt on m* cmds */ +int debug; /* debugging level */ +int bell; /* ring bell on cmd completion */ +int doglob; /* glob local file names */ +int autologin; /* establish user account on connection */ +int proxy; /* proxy server connection active */ +int proxflag; /* proxy connection exists */ +int sunique; /* store files on server with unique name */ +int runique; /* store local files with unique name */ +int mcase; /* map upper to lower case for mget names */ +int ntflag; /* use ntin ntout tables for name translation */ +int mapflag; /* use mapin mapout templates on file names */ +int code; /* return/reply code for ftp command */ +int crflag; /* if 1, strip car. rets. on ascii gets */ +char pasv[64]; /* passive port for proxy data connection */ +int passivemode; /* passive mode enabled */ +char *altarg; /* argv[1] with no shell-like preprocessing */ +char ntin[17]; /* input translation table */ +char ntout[17]; /* output translation table */ +char mapin[MaxPathLen]; /* input map template */ +char mapout[MaxPathLen]; /* output map template */ +char typename[32]; /* name of file transfer type */ +int type; /* requested file transfer type */ +int curtype; /* current file transfer type */ +char structname[32]; /* name of file transfer structure */ +int stru; /* file transfer structure */ +char formname[32]; /* name of file transfer format */ +int form; /* file transfer format */ +char modename[32]; /* name of file transfer mode */ +int mode; /* file transfer mode */ +char bytename[32]; /* local byte size in ascii */ +int bytesize; /* local byte size in binary */ + +char *hostname; /* name of host connected to */ +int unix_server; /* server is unix, can use binary for ascii */ +int unix_proxy; /* proxy is unix, can use binary for ascii */ + +jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ + +char line[200]; /* input line buffer */ +char *stringbase; /* current scan point in line buffer */ +char argbuf[200]; /* argument storage buffer */ +char *argbase; /* current storage point in arg buffer */ +int margc; /* count of arguments on input line */ +char **margv; /* args parsed from input line */ +int margvlen; /* how large margv is currently */ +int cpend; /* flag: if != 0, then pending server reply */ +int mflag; /* flag: if != 0, then active multi command */ + +int options; /* used during socket creation */ + +/* + * Format of command table. + */ + +int macnum; /* number of defined macros */ +struct macel macros[16]; +char macbuf[4096]; + +char username[32]; + +/* these are set in ruserpass */ +char myhostname[MaxHostNameLen]; +char *mydomain; diff --git a/crypto/kerberosIV/appl/ftp/ftp/kauth.c b/crypto/kerberosIV/appl/ftp/ftp/kauth.c new file mode 100644 index 0000000..8bc9b9b --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/kauth.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "ftp_locl.h" +RCSID("$Id: kauth.c,v 1.14 1997/05/11 04:08:04 assar Exp $"); + +void kauth(int argc, char **argv) +{ + int ret; + char buf[1024]; + des_cblock key; + des_key_schedule schedule; + KTEXT_ST tkt, tktcopy; + char *name; + char *p; + int overbose; + char passwd[100]; + int tmp; + + if(argc > 2){ + printf("usage: %s [principal]\n", argv[0]); + code = -1; + return; + } + if(argc == 2) + name = argv[1]; + else + name = username; + + overbose = verbose; + verbose = 0; + + ret = command("SITE KAUTH %s", name); + if(ret != CONTINUE){ + verbose = overbose; + code = -1; + return; + } + verbose = overbose; + p = strstr(reply_string, "T="); + if(!p){ + printf("Bad reply from server.\n"); + code = -1; + return; + } + p += 2; + tmp = base64_decode(p, &tkt.dat); + if(tmp < 0){ + printf("Failed to decode base64 in reply.\n"); + code = -1; + return; + } + tkt.length = tmp; + tktcopy.length = tkt.length; + + p = strstr(reply_string, "P="); + if(!p){ + printf("Bad reply from server.\n"); + verbose = overbose; + code = -1; + return; + } + name = p + 2; + for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++); + *p = 0; + + snprintf(buf, sizeof(buf), "Password for %s:", name); + if (des_read_pw_string (passwd, sizeof(passwd)-1, buf, 0)) + *passwd = '\0'; + des_string_to_key (passwd, &key); + + des_key_sched(&key, schedule); + + des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat, + tkt.length, + schedule, &key, DES_DECRYPT); + if (strcmp ((char*)tktcopy.dat + 8, + KRB_TICKET_GRANTING_TICKET) != 0) { + afs_string_to_key (passwd, krb_realmofhost(hostname), &key); + des_key_sched (&key, schedule); + des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat, + tkt.length, + schedule, &key, DES_DECRYPT); + } + memset(key, 0, sizeof(key)); + memset(schedule, 0, sizeof(schedule)); + memset(passwd, 0, sizeof(passwd)); + base64_encode(tktcopy.dat, tktcopy.length, &p); + memset (tktcopy.dat, 0, tktcopy.length); + ret = command("SITE KAUTH %s %s", name, p); + free(p); + if(ret != COMPLETE){ + code = -1; + return; + } + code = 0; +} + +void klist(int argc, char **argv) +{ + int ret; + if(argc != 1){ + printf("usage: %s\n", argv[0]); + code = -1; + return; + } + + ret = command("SITE KLIST"); + code = (ret == COMPLETE); +} diff --git a/crypto/kerberosIV/appl/ftp/ftp/krb4.c b/crypto/kerberosIV/appl/ftp/ftp/krb4.c new file mode 100644 index 0000000..872c5bc --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/krb4.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "ftp_locl.h" + +RCSID("$Id: krb4.c,v 1.18 1997/05/11 04:08:05 assar Exp $"); + +static KTEXT_ST krb4_adat; + +static des_cblock key; +static des_key_schedule schedule; + +static char *data_buffer; + +extern struct sockaddr_in hisctladdr, myctladdr; + +int auth_complete; + +static int command_prot; + +static int auth_pbsz; +static int data_prot; + +static int request_data_prot; + + +static struct { + int level; + char *name; +} level_names[] = { + { prot_clear, "clear" }, + { prot_safe, "safe" }, + { prot_confidential, "confidential" }, + { prot_private, "private" } +}; + +static char *level_to_name(int level) +{ + int i; + for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) + if(level_names[i].level == level) + return level_names[i].name; + return "unknown"; +} + +static int name_to_level(char *name) +{ + int i; + for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) + if(!strncasecmp(level_names[i].name, name, strlen(name))) + return level_names[i].level; + return -1; +} + +void sec_status(void) +{ + if(auth_complete){ + printf("Using KERBEROS_V4 for authentication.\n"); + + command_prot = prot_private; /* this variable is not used */ + + printf("Using %s command channel.\n", + level_to_name(command_prot)); + + printf("Using %s data channel.\n", + level_to_name(data_prot)); + if(auth_pbsz > 0) + printf("Protection buffer size: %d.\n", auth_pbsz); + }else{ + printf("Not using any security mechanism.\n"); + } +} + +static int +sec_prot_internal(int level) +{ + int ret; + char *p; + int s = 1048576; + + int old_verbose = verbose; + verbose = 0; + + if(!auth_complete){ + printf("No security data exchange has taken place.\n"); + return -1; + } + + if(level){ + ret = command("PBSZ %d", s); + if(ret != COMPLETE){ + printf("Failed to set protection buffer size.\n"); + return -1; + } + auth_pbsz = s; + p = strstr(reply_string, "PBSZ="); + if(p) + sscanf(p, "PBSZ=%d", &s); + if(s < auth_pbsz) + auth_pbsz = s; + if(data_buffer) + free(data_buffer); + data_buffer = malloc(auth_pbsz); + } + verbose = old_verbose; + ret = command("PROT %c", level["CSEP"]); /* XXX :-) */ + if(ret != COMPLETE){ + printf("Failed to set protection level.\n"); + return -1; + } + + data_prot = level; + return 0; +} + + +void +sec_prot(int argc, char **argv) +{ + int level = -1; + + if(argc != 2){ + printf("usage: %s (clear | safe | confidential | private)\n", + argv[0]); + code = -1; + return; + } + if(!auth_complete){ + printf("No security data exchange has taken place.\n"); + code = -1; + return; + } + level = name_to_level(argv[1]); + + if(level == -1){ + printf("usage: %s (clear | safe | confidential | private)\n", + argv[0]); + code = -1; + return; + } + + if(level == prot_confidential){ + printf("Confidential protection is not defined with Kerberos.\n"); + code = -1; + return; + } + + if(sec_prot_internal(level) < 0){ + code = -1; + return; + } + code = 0; +} + +void +sec_set_protection_level(void) +{ + if(auth_complete && data_prot != request_data_prot) + sec_prot_internal(request_data_prot); +} + + +int +sec_request_prot(char *level) +{ + int l = name_to_level(level); + if(l == -1) + return -1; + request_data_prot = l; + return 0; +} + + +int sec_getc(FILE *F) +{ + if(auth_complete && data_prot) + return krb4_getc(F); + else + return getc(F); +} + +int sec_read(int fd, void *data, int length) +{ + if(auth_complete && data_prot) + return krb4_read(fd, data, length); + else + return read(fd, data, length); +} + +static int +krb4_recv(int fd) +{ + int len; + MSG_DAT m; + int kerror; + + krb_net_read(fd, &len, sizeof(len)); + len = ntohl(len); + krb_net_read(fd, data_buffer, len); + if(data_prot == prot_safe) + kerror = krb_rd_safe(data_buffer, len, &key, + &hisctladdr, &myctladdr, &m); + else + kerror = krb_rd_priv(data_buffer, len, schedule, &key, + &hisctladdr, &myctladdr, &m); + if(kerror){ + return -1; + } + memmove(data_buffer, m.app_data, m.app_length); + return m.app_length; +} + + +int krb4_getc(FILE *F) +{ + static int bytes; + static int index; + if(bytes == 0){ + bytes = krb4_recv(fileno(F)); + index = 0; + } + if(bytes){ + bytes--; + return (unsigned char)data_buffer[index++]; + } + return EOF; +} + +int krb4_read(int fd, char *data, int length) +{ + static int left; + static int index; + static int eof; + int len = left; + int rx = 0; + + if(eof){ + eof = 0; + return 0; + } + + if(left){ + if(length < len) + len = length; + memmove(data, data_buffer + index, len); + length -= len; + index += len; + rx += len; + left -= len; + } + + while(length){ + len = krb4_recv(fd); + if(len == 0){ + if(rx) + eof = 1; + return rx; + } + if(len > length){ + left = len - length; + len = index = length; + } + memmove(data, data_buffer, len); + length -= len; + data += len; + rx += len; + } + return rx; +} + + +static int +krb4_encode(char *from, char *to, int length) +{ + if(data_prot == prot_safe) + return krb_mk_safe(from, to, length, &key, + &myctladdr, &hisctladdr); + else + return krb_mk_priv(from, to, length, schedule, &key, + &myctladdr, &hisctladdr); +} + +static int +krb4_overhead(int len) +{ + if(data_prot == prot_safe) + return 31; + else + return 26; +} + +static char p_buf[1024]; +static int p_index; + +int +sec_putc(int c, FILE *F) +{ + if(data_prot){ + if((c == '\n' && p_index) || p_index == sizeof(p_buf)){ + sec_write(fileno(F), p_buf, p_index); + p_index = 0; + } + p_buf[p_index++] = c; + return c; + } + return putc(c, F); +} + +static int +sec_send(int fd, char *from, int length) +{ + int bytes; + bytes = krb4_encode(from, data_buffer, length); + bytes = htonl(bytes); + krb_net_write(fd, &bytes, sizeof(bytes)); + krb_net_write(fd, data_buffer, ntohl(bytes)); + return length; +} + +int +sec_fflush(FILE *F) +{ + if(data_prot){ + if(p_index){ + sec_write(fileno(F), p_buf, p_index); + p_index = 0; + } + sec_send(fileno(F), NULL, 0); + } + fflush(F); + return 0; +} + +int +sec_write(int fd, char *data, int length) +{ + int len = auth_pbsz; + int tx = 0; + + if(data_prot == prot_clear) + return write(fd, data, length); + + len -= krb4_overhead(len); + while(length){ + if(length < len) + len = length; + sec_send(fd, data, len); + length -= len; + data += len; + tx += len; + } + return tx; +} + +static int +do_auth(char *service, char *host, int checksum) +{ + int ret; + CREDENTIALS cred; + char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ]; + strcpy(sname, service); + strcpy(inst, krb_get_phost(host)); + strcpy(realm, krb_realmofhost(host)); + ret = krb_mk_req(&krb4_adat, sname, inst, realm, checksum); + if(ret) + return ret; + strcpy(sname, service); + strcpy(inst, krb_get_phost(host)); + strcpy(realm, krb_realmofhost(host)); + ret = krb_get_cred(sname, inst, realm, &cred); + memmove(&key, &cred.session, sizeof(des_cblock)); + des_key_sched(&key, schedule); + memset(&cred, 0, sizeof(cred)); + return ret; +} + + +int +do_klogin(char *host) +{ + int ret; + char *p; + int len; + char adat[1024]; + MSG_DAT msg_data; + int checksum; + + int old_verbose = verbose; + + verbose = 0; + printf("Trying KERBEROS_V4...\n"); + ret = command("AUTH KERBEROS_V4"); + if(ret != CONTINUE){ + if(code == 504){ + printf("Kerberos 4 is not supported by the server.\n"); + }else if(code == 534){ + printf("KERBEROS_V4 rejected as security mechanism.\n"); + }else if(ret == ERROR) + printf("The server doesn't understand the FTP " + "security extensions.\n"); + verbose = old_verbose; + return -1; + } + + checksum = getpid(); + ret = do_auth("ftp", host, checksum); + if(ret == KDC_PR_UNKNOWN) + ret = do_auth("rcmd", host, checksum); + if(ret){ + printf("%s\n", krb_get_err_text(ret)); + verbose = old_verbose; + return ret; + } + + base64_encode(krb4_adat.dat, krb4_adat.length, &p); + ret = command("ADAT %s", p); + free(p); + + if(ret != COMPLETE){ + printf("Server didn't accept auth data.\n"); + verbose = old_verbose; + return -1; + } + + p = strstr(reply_string, "ADAT="); + if(!p){ + printf("Remote host didn't send adat reply.\n"); + verbose = old_verbose; + return -1; + } + p+=5; + len = base64_decode(p, adat); + if(len < 0){ + printf("Failed to decode base64 from server.\n"); + verbose = old_verbose; + return -1; + } + ret = krb_rd_safe(adat, len, &key, + &hisctladdr, &myctladdr, &msg_data); + if(ret){ + printf("Error reading reply from server: %s.\n", + krb_get_err_text(ret)); + verbose = old_verbose; + return -1; + } + { + /* the draft doesn't tell what size the return has */ + int i; + u_int32_t cs = 0; + for(i = 0; i < msg_data.app_length; i++) + cs = (cs<<8) + msg_data.app_data[i]; + if(cs - checksum != 1){ + printf("Bad checksum returned from server.\n"); + verbose = old_verbose; + return -1; + } + } + auth_complete = 1; + verbose = old_verbose; + return 0; +} + +void +krb4_quit(void) +{ + auth_complete = 0; +} + +int krb4_write_enc(FILE *F, char *fmt, va_list ap) +{ + int len; + char *p; + char buf[1024]; + char enc[1024]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + len = krb_mk_priv(buf, enc, strlen(buf), schedule, &key, + &myctladdr, &hisctladdr); + base64_encode(enc, len, &p); + + fprintf(F, "ENC %s", p); + free (p); + return 0; +} + + +int krb4_read_msg(char *s, int priv) +{ + int len; + int ret; + char buf[1024]; + MSG_DAT m; + int code; + + len = base64_decode(s + 4, buf); + if(priv) + ret = krb_rd_priv(buf, len, schedule, &key, + &hisctladdr, &myctladdr, &m); + else + ret = krb_rd_safe(buf, len, &key, &hisctladdr, &myctladdr, &m); + if(ret){ + printf("%s\n", krb_get_err_text(ret)); + return -1; + } + + m.app_data[m.app_length] = 0; + if(m.app_data[3] == '-') + code = 0; + else + sscanf((char*)m.app_data, "%d", &code); + strncpy(s, (char*)m.app_data, strlen((char*)m.app_data)); + + s[m.app_length] = 0; + len = strlen(s); + if(s[len-1] == '\n') + s[len-1] = 0; + + return code; +} + +int +krb4_read_mic(char *s) +{ + return krb4_read_msg(s, 0); +} + +int +krb4_read_enc(char *s) +{ + return krb4_read_msg(s, 1); +} + diff --git a/crypto/kerberosIV/appl/ftp/ftp/krb4.h b/crypto/kerberosIV/appl/ftp/ftp/krb4.h new file mode 100644 index 0000000..7cf8cec --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/krb4.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: krb4.h,v 1.10 1997/04/01 08:17:22 joda Exp $ */ + +#ifndef __KRB4_H__ +#define __KRB4_H__ + +#include <stdio.h> +#include <stdarg.h> + +extern int auth_complete; + +void sec_status(void); + +enum { prot_clear, prot_safe, prot_confidential, prot_private }; + +void sec_prot(int, char**); + +int sec_getc(FILE *F); +int sec_putc(int c, FILE *F); +int sec_fflush(FILE *F); +int sec_read(int fd, void *data, int length); +int sec_write(int fd, char *data, int length); + +int krb4_getc(FILE *F); +int krb4_read(int fd, char *data, int length); + + + +void sec_set_protection_level(void); +int sec_request_prot(char *level); + +void kauth(int, char **); +void klist(int, char **); + +void krb4_quit(void); + +int krb4_write_enc(FILE *F, char *fmt, va_list ap); +int krb4_read_msg(char *s, int priv); +int krb4_read_mic(char *s); +int krb4_read_enc(char *s); + +int do_klogin(char *host); + +#endif /* __KRB4_H__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftp/main.c b/crypto/kerberosIV/appl/ftp/ftp/main.c new file mode 100644 index 0000000..4d1b6a5 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/main.c @@ -0,0 +1,542 @@ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +/* + * FTP User Program -- Command Interface. + */ + +#include "ftp_locl.h" +RCSID("$Id: main.c,v 1.20 1997/04/20 16:14:55 joda Exp $"); + +int +main(int argc, char **argv) +{ + int ch, top; + struct passwd *pw = NULL; + char homedir[MaxPathLen]; + struct servent *sp; + + set_progname(argv[0]); + + sp = getservbyname("ftp", "tcp"); + if (sp == 0) + errx(1, "ftp/tcp: unknown service"); + doglob = 1; + interactive = 1; + autologin = 1; + + while ((ch = getopt(argc, argv, "dgintv")) != EOF) { + switch (ch) { + case 'd': + options |= SO_DEBUG; + debug++; + break; + + case 'g': + doglob = 0; + break; + + case 'i': + interactive = 0; + break; + + case 'n': + autologin = 0; + break; + + case 't': + trace++; + break; + + case 'v': + verbose++; + break; + + default: + fprintf(stderr, + "usage: ftp [-dgintv] [host [port]]\n"); + exit(1); + } + } + argc -= optind; + argv += optind; + + fromatty = isatty(fileno(stdin)); + if (fromatty) + verbose++; + cpend = 0; /* no pending replies */ + proxy = 0; /* proxy not active */ + passivemode = 0; /* passive mode not active */ + crflag = 1; /* strip c.r. on ascii gets */ + sendport = -1; /* not using ports */ + /* + * Set up the home directory in case we're globbing. + */ + pw = k_getpwuid(getuid()); + if (pw != NULL) { + home = homedir; + strcpy(home, pw->pw_dir); + } + if (argc > 0) { + char *xargv[5]; + + if (setjmp(toplevel)) + exit(0); + signal(SIGINT, intr); + signal(SIGPIPE, lostpeer); + xargv[0] = (char*)__progname; + xargv[1] = argv[0]; + xargv[2] = argv[1]; + xargv[3] = argv[2]; + xargv[4] = NULL; + setpeer(argc+1, xargv); + } + if(setjmp(toplevel) == 0) + top = 1; + else + top = 0; + if (top) { + signal(SIGINT, intr); + signal(SIGPIPE, lostpeer); + } + for (;;) { + cmdscanner(top); + top = 1; + } +} + +void +intr(int sig) +{ + + longjmp(toplevel, 1); +} + +#ifndef SHUT_RDWR +#define SHUT_RDWR 2 +#endif + +RETSIGTYPE +lostpeer(int sig) +{ + + if (connected) { + if (cout != NULL) { + shutdown(fileno(cout), SHUT_RDWR); + fclose(cout); + cout = NULL; + } + if (data >= 0) { + shutdown(data, SHUT_RDWR); + close(data); + data = -1; + } + connected = 0; + } + pswitch(1); + if (connected) { + if (cout != NULL) { + shutdown(fileno(cout), SHUT_RDWR); + fclose(cout); + cout = NULL; + } + connected = 0; + } + proxflag = 0; + pswitch(0); + SIGRETURN(0); +} + +/* +char * +tail(filename) + char *filename; +{ + char *s; + + while (*filename) { + s = strrchr(filename, '/'); + if (s == NULL) + break; + if (s[1]) + return (s + 1); + *s = '\0'; + } + return (filename); +} +*/ + +#ifndef HAVE_READLINE + +static char * +readline(char *prompt) +{ + char buf[BUFSIZ]; + printf ("%s", prompt); + fflush (stdout); + if(fgets(buf, sizeof(buf), stdin) == NULL) + return NULL; + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + return strdup(buf); +} + +static void +add_history(char *p) +{ +} + +#else + +/* These should not really be here */ + +char *readline(char *); +void add_history(char *); + +#endif + +/* + * Command parser. + */ +void +cmdscanner(int top) +{ + struct cmd *c; + int l; + + if (!top) + putchar('\n'); + for (;;) { + if (fromatty) { + char *p; + p = readline("ftp> "); + if(p == NULL) + quit(0, 0); + strncpy(line, p, sizeof(line)); + line[sizeof(line) - 1] = 0; + add_history(p); + free(p); + } else{ + if (fgets(line, sizeof line, stdin) == NULL) + quit(0, 0); + } + /* XXX will break on long lines */ + l = strlen(line); + if (l == 0) + break; + if (line[--l] == '\n') { + if (l == 0) + break; + line[l] = '\0'; + } else if (l == sizeof(line) - 2) { + printf("sorry, input line too long\n"); + while ((l = getchar()) != '\n' && l != EOF) + /* void */; + break; + } /* else it was a line without a newline */ + makeargv(); + if (margc == 0) { + continue; + } + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + if (c->c_conn && !connected) { + printf("Not connected.\n"); + continue; + } + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) + putchar('\007'); + if (c->c_handler != help) + break; + } + signal(SIGINT, intr); + signal(SIGPIPE, lostpeer); +} + +struct cmd * +getcmd(char *name) +{ + char *p, *q; + struct cmd *c, *found; + int nmatches, longest; + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; (p = c->c_name); c++) { + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return (c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return ((struct cmd *)-1); + return (found); +} + +/* + * Slice a string up into argc/argv. + */ + +int slrflag; + +void +makeargv(void) +{ + char **argp; + + argp = margv; + stringbase = line; /* scan from first of buffer */ + argbase = argbuf; /* store from first of buffer */ + slrflag = 0; + for (margc = 0; ; margc++) { + /* Expand array if necessary */ + if (margc == margvlen) { + margv = (margvlen == 0) + ? (char **)malloc(20 * sizeof(char *)) + : (char **)realloc(margv, + (margvlen + 20)*sizeof(char *)); + if (margv == NULL) + errx(1, "cannot realloc argv array"); + margvlen += 20; + argp = margv + margc; + } + + if ((*argp++ = slurpstring()) == NULL) + break; + } + +} + +/* + * Parse string into argbuf; + * implemented with FSM to + * handle quoting and strings + */ +char * +slurpstring(void) +{ + int got_one = 0; + char *sb = stringbase; + char *ap = argbase; + char *tmp = argbase; /* will return this if token found */ + + if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */ + switch (slrflag) { /* and $ as token for macro invoke */ + case 0: + slrflag++; + stringbase++; + return ((*sb == '!') ? "!" : "$"); + /* NOTREACHED */ + case 1: + slrflag++; + altarg = stringbase; + break; + default: + break; + } + } + +S0: + switch (*sb) { + + case '\0': + goto OUT; + + case ' ': + case '\t': + sb++; goto S0; + + default: + switch (slrflag) { + case 0: + slrflag++; + break; + case 1: + slrflag++; + altarg = sb; + break; + default: + break; + } + goto S1; + } + +S1: + switch (*sb) { + + case ' ': + case '\t': + case '\0': + goto OUT; /* end of token */ + + case '\\': + sb++; goto S2; /* slurp next character */ + + case '"': + sb++; goto S3; /* slurp quoted string */ + + default: + *ap++ = *sb++; /* add character to token */ + got_one = 1; + goto S1; + } + +S2: + switch (*sb) { + + case '\0': + goto OUT; + + default: + *ap++ = *sb++; + got_one = 1; + goto S1; + } + +S3: + switch (*sb) { + + case '\0': + goto OUT; + + case '"': + sb++; goto S1; + + default: + *ap++ = *sb++; + got_one = 1; + goto S3; + } + +OUT: + if (got_one) + *ap++ = '\0'; + argbase = ap; /* update storage pointer */ + stringbase = sb; /* update scan pointer */ + if (got_one) { + return (tmp); + } + switch (slrflag) { + case 0: + slrflag++; + break; + case 1: + slrflag++; + altarg = (char *) 0; + break; + default: + break; + } + return NULL; +} + +#define HELPINDENT ((int) sizeof ("directory")) + +/* + * Help command. + * Call each command handler with argc == 0 and argv[0] == name. + */ +void +help(int argc, char **argv) +{ + struct cmd *c; + + if (argc == 1) { + int i, j, w, k; + int columns, width = 0, lines; + + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { + int len = strlen(c->c_name); + + if (len > width) + width = len; + } + width = (width + 8) &~ 7; + columns = 80 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + c = cmdtab + j * lines + i; + if (c->c_name && (!proxy || c->c_proxy)) { + printf("%s", c->c_name); + } + else if (c->c_name) { + for (k=0; k < strlen(c->c_name); k++) { + putchar(' '); + } + } + if (c + lines >= &cmdtab[NCMDS]) { + printf("\n"); + break; + } + w = strlen(c->c_name); + while (w < width) { + w = (w + 8) &~ 7; + putchar('\t'); + } + } + } + return; + } + while (--argc > 0) { + char *arg; + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + printf("?Ambiguous help command %s\n", arg); + else if (c == (struct cmd *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%-*s\t%s\n", HELPINDENT, + c->c_name, c->c_help); + } +} diff --git a/crypto/kerberosIV/appl/ftp/ftp/pathnames.h b/crypto/kerberosIV/appl/ftp/ftp/pathnames.h new file mode 100644 index 0000000..f7c1fb3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/pathnames.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif + +#define _PATH_TMP_XXX "/tmp/ftpXXXXXX" + +#ifndef _PATH_BSHELL +#define _PATH_BSHELL "/bin/sh" +#endif diff --git a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c new file mode 100644 index 0000000..8cea6d4 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 1985, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "ftp_locl.h" +RCSID("$Id: ruserpass.c,v 1.10 1997/05/02 14:27:55 assar Exp $"); + +static int token (void); +static FILE *cfile; + +#define DEFAULT 1 +#define LOGIN 2 +#define PASSWD 3 +#define ACCOUNT 4 +#define MACDEF 5 +#define PROT 6 +#define ID 10 +#define MACH 11 + +static char tokval[100]; + +static struct toktab { + char *tokstr; + int tval; +} toktab[]= { + { "default", DEFAULT }, + { "login", LOGIN }, + { "password", PASSWD }, + { "passwd", PASSWD }, + { "account", ACCOUNT }, + { "machine", MACH }, + { "macdef", MACDEF }, + { "prot", PROT }, + { NULL, 0 } +}; + +int +ruserpass(char *host, char **aname, char **apass, char **aacct) +{ + char *hdir, buf[BUFSIZ], *tmp; + int t, i, c, usedefault = 0; + struct stat stb; + + if(k_gethostname(myhostname, MaxHostNameLen) < 0) + strcpy(myhostname, ""); + if((mydomain = strchr(myhostname, '.')) == NULL) + mydomain = myhostname; + else + mydomain++; + hdir = getenv("HOME"); + if (hdir == NULL) + hdir = "."; + snprintf(buf, sizeof(buf), "%s/.netrc", hdir); + cfile = fopen(buf, "r"); + if (cfile == NULL) { + if (errno != ENOENT) + warn("%s", buf); + return (0); + } + +next: + while ((t = token())) switch(t) { + + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ + + case MACH: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's input host name + * or official hostname. Also allow match of + * incompletely-specified host in local domain. + */ + if (strcasecmp(host, tokval) == 0) + goto match; + if (strcasecmp(hostname, tokval) == 0) + goto match; + if ((tmp = strchr(hostname, '.')) != NULL && + tmp++ && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(hostname, tokval, tmp-hostname) == 0 && + tokval[tmp - hostname] == '\0') + goto match; + if ((tmp = strchr(host, '.')) != NULL && + tmp++ && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(host, tokval, tmp - host) == 0 && + tokval[tmp - host] == '\0') + goto match; + continue; + } + match: + while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { + + case LOGIN: + if (token()) + if (*aname == 0) { + *aname = strdup(tokval); + } else { + if (strcmp(*aname, tokval)) + goto next; + } + break; + case PASSWD: + if ((*aname == NULL || strcmp(*aname, "anonymous")) && + fstat(fileno(cfile), &stb) >= 0 && + (stb.st_mode & 077) != 0) { + warnx("Error: .netrc file is readable by others."); + warnx("Remove password or make file unreadable by others."); + goto bad; + } + if (token() && *apass == 0) { + *apass = strdup(tokval); + } + break; + case ACCOUNT: + if (fstat(fileno(cfile), &stb) >= 0 + && (stb.st_mode & 077) != 0) { + warnx("Error: .netrc file is readable by others."); + warnx("Remove account or make file unreadable by others."); + goto bad; + } + if (token() && *aacct == 0) { + *aacct = strdup(tokval); + } + break; + case MACDEF: + if (proxy) { + fclose(cfile); + return (0); + } + while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t'); + if (c == EOF || c == '\n') { + printf("Missing macdef name argument.\n"); + goto bad; + } + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + goto bad; + } + tmp = macros[macnum].mac_name; + *tmp++ = c; + for (i=0; i < 8 && (c=getc(cfile)) != EOF && + !isspace(c); ++i) { + *tmp++ = c; + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = '\0'; + if (c != '\n') { + while ((c=getc(cfile)) != EOF && c != '\n'); + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum-1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf + 4096) { + if ((c=getc(cfile)) == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = c; + if (*tmp == '\n') { + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + break; + } + *tmp = '\0'; + } + tmp++; + } + if (tmp == macbuf + 4096) { + printf("4K macro buffer exceeded\n"); + goto bad; + } + break; + case PROT: + token(); + if(sec_request_prot(tokval) < 0) + warnx("Unknown protection level \"%s\"", tokval); + break; + default: + warnx("Unknown .netrc keyword %s", tokval); + break; + } + goto done; + } +done: + fclose(cfile); + return (0); +bad: + fclose(cfile); + return (-1); +} + +static int +token(void) +{ + char *cp; + int c; + struct toktab *t; + + if (feof(cfile) || ferror(cfile)) + return (0); + while ((c = getc(cfile)) != EOF && + (c == '\n' || c == '\t' || c == ' ' || c == ',')) + continue; + if (c == EOF) + return (0); + cp = tokval; + if (c == '"') { + while ((c = getc(cfile)) != EOF && c != '"') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } else { + *cp++ = c; + while ((c = getc(cfile)) != EOF + && c != '\n' && c != '\t' && c != ' ' && c != ',') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } + *cp = 0; + if (tokval[0] == 0) + return (0); + for (t = toktab; t->tokstr; t++) + if (!strcmp(t->tokstr, tokval)) + return (t->tval); + return (ID); +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in new file mode 100644 index 0000000..55981de --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in @@ -0,0 +1,84 @@ +# +# $Id: Makefile.in,v 1.31 1997/05/02 17:49:27 assar Exp $ +# + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +topdir = ../../.. + +SHELL = /bin/sh + +CC = @CC@ +YACC = @YACC@ +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +LD_FLAGS = @LD_FLAGS@ +LIBS = @LIBS@ +LIB_DBM = @LIB_DBM@ +MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +ATHENA = ../../.. + +INCTOP = $(ATHENA)/include + +LIBTOP = $(ATHENA)/lib + +LIBKAFS = @KRB_KAFS_LIB@ +LIBKRB = -L$(LIBTOP)/krb -lkrb +LIBDES = -L$(LIBTOP)/des -ldes +LIBOTP = -L$(LIBTOP)/otp -lotp +LIBROKEN= -L$(LIBTOP)/roken -lroken + +PROGS = ftpd$(EXECSUFFIX) + +ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c popen.c auth.c krb4.c kauth.c +ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o auth.o krb4.o kauth.o + +SOURCES = $(ftpd_SOURCES) +OBJECTS = $(ftpd_OBJS) + +all: $(PROGS) + +.c.o: + $(CC) -c $(CFLAGS) -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $< + +install: all + $(MKINSTALLDIRS) $(libexecdir) + for x in $(PROGS); do \ + $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROGS); do \ + rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + +ftpd$(EXECSUFFIX): $(ftpd_OBJS) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(ftpd_OBJS) -L../common -lcommon $(LIBKAFS) $(LIBKRB) $(LIBOTP) $(LIBDES) $(LIBROKEN) $(LIB_DBM) $(LIBS) $(LIBROKEN) + +ftpcmd.c: ftpcmd.y + $(YACC) $(YFLAGS) $< + chmod a-w y.tab.c + mv -f y.tab.c ftpcmd.c + +TAGS: $(SOURCES) + etags $(SOURCES) + +clean cleandir: + rm -f *~ *.o core ftpd ftpcmd.c \#* + +distclean: + rm -f Makefile diff --git a/crypto/kerberosIV/appl/ftp/ftpd/auth.c b/crypto/kerberosIV/appl/ftp/ftpd/auth.c new file mode 100644 index 0000000..862eb6d --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/auth.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +RCSID("$Id: auth.c,v 1.11 1997/05/04 23:09:00 assar Exp $"); +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4 +#include <sys/ioctl.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "extern.h" +#include "krb4.h" +#include "auth.h" + +static struct at auth_types [] = { + { "KERBEROS_V4", krb4_auth, krb4_adat, krb4_pbsz, krb4_prot, krb4_ccc, + krb4_mic, krb4_conf, krb4_enc, krb4_read, krb4_write, krb4_userok, + krb4_vprintf }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +struct at *ct; + +int data_protection; +int buffer_size; +unsigned char *data_buffer; +int auth_complete; + + +char *protection_names[] = { + "clear", "safe", + "confidential", "private" +}; + + +void auth_init(void) +{ +} + +char *ftp_command; +int prot_level; + +void new_ftp_command(char *command) +{ + ftp_command = command; +} + +void delete_ftp_command(void) +{ + if(ftp_command){ + free(ftp_command); + ftp_command = NULL; + } +} + +int auth_ok(void) +{ + return ct && auth_complete; +} + +void auth(char *auth) +{ + for(ct=auth_types; ct->name; ct++){ + if(!strcasecmp(auth, ct->name)){ + ct->auth(auth); + return; + } + } + reply(504, "%s is not a known security mechanism", auth); +} + +void adat(char *auth) +{ + if(ct && !auth_complete) + ct->adat(auth); + else + reply(503, "You must (re)issue an AUTH first."); +} + +void pbsz(int size) +{ + int old = buffer_size; + if(auth_ok()) + ct->pbsz(size); + else + reply(503, "Incomplete security data exchange."); + if(buffer_size != old){ + if(data_buffer) + free(data_buffer); + data_buffer = malloc(buffer_size + 4); + } +} + +void prot(char *pl) +{ + int p = -1; + + if(buffer_size == 0){ + reply(503, "No protection buffer size negotiated."); + return; + } + + if(!strcasecmp(pl, "C")) + p = prot_clear; + + if(!strcasecmp(pl, "S")) + p = prot_safe; + + if(!strcasecmp(pl, "E")) + p = prot_confidential; + + if(!strcasecmp(pl, "P")) + p = prot_private; + + if(p == -1){ + reply(504, "Unrecognized protection level."); + return; + } + + if(auth_ok()){ + if(ct->prot(p)){ + reply(536, "%s does not support %s protection.", + ct->name, protection_names[p]); + }else{ + data_protection = p; + reply(200, "Data protection is %s.", + protection_names[data_protection]); + } + }else{ + reply(503, "Incomplete security data exchange."); + } +} + +void ccc(void) +{ + if(auth_ok()){ + if(!ct->ccc()) + prot_level = prot_clear; + }else + reply(503, "Incomplete security data exchange."); +} + +void mic(char *msg) +{ + if(auth_ok()){ + if(!ct->mic(msg)) + prot_level = prot_safe; + }else + reply(503, "Incomplete security data exchange."); +} + +void conf(char *msg) +{ + if(auth_ok()){ + if(!ct->conf(msg)) + prot_level = prot_confidential; + }else + reply(503, "Incomplete security data exchange."); +} + +void enc(char *msg) +{ + if(auth_ok()){ + if(!ct->enc(msg)) + prot_level = prot_private; + }else + reply(503, "Incomplete security data exchange."); +} + +int auth_read(int fd, void *data, int length) +{ + if(auth_ok() && data_protection) + return ct->read(fd, data, length); + else + return read(fd, data, length); +} + +int auth_write(int fd, void *data, int length) +{ + if(auth_ok() && data_protection) + return ct->write(fd, data, length); + else + return write(fd, data, length); +} + +void auth_vprintf(const char *fmt, va_list ap) +{ + if(auth_ok() && prot_level){ + ct->vprintf(fmt, ap); + }else + vprintf(fmt, ap); +} + +void auth_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + auth_vprintf(fmt, ap); + va_end(ap); +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/auth.h b/crypto/kerberosIV/appl/ftp/ftpd/auth.h new file mode 100644 index 0000000..17d9a13 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/auth.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: auth.h,v 1.9 1997/05/11 11:04:28 assar Exp $ */ + +#ifndef __AUTH_H__ +#define __AUTH_H__ + +#include <stdarg.h> + +struct at { + char *name; + int (*auth)(char*); + int (*adat)(char*); + int (*pbsz)(int); + int (*prot)(int); + int (*ccc)(void); + int (*mic)(char*); + int (*conf)(char*); + int (*enc)(char*); + int (*read)(int, void*, int); + int (*write)(int, void*, int); + int (*userok)(char*); + int (*vprintf)(const char*, va_list); +}; + +extern struct at *ct; + +enum protection_levels { + prot_clear, prot_safe, prot_confidential, prot_private +}; + +extern char *protection_names[]; + +extern char *ftp_command; +extern int prot_level; + +void delete_ftp_command(void); + +extern int data_protection; +extern int buffer_size; +extern unsigned char *data_buffer; +extern int auth_complete; + +void auth_init(void); + +int auth_ok(void); + +void auth(char*); +void adat(char*); +void pbsz(int); +void prot(char*); +void ccc(void); +void mic(char*); +void conf(char*); +void enc(char*); + +int auth_read(int, void*, int); +int auth_write(int, void*, int); + +void auth_vprintf(const char *fmt, va_list ap) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 0))) +#endif +; +void auth_printf(const char *fmt, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + +void new_ftp_command(char *command); + +#endif /* __AUTH_H__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/extern.h b/crypto/kerberosIV/appl/ftp/ftpd/extern.h new file mode 100644 index 0000000..f9b800f --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/extern.h @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)extern.h 8.2 (Berkeley) 4/4/94 + */ + +#ifndef _EXTERN_H_ +#define _EXTERN_H_ + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <stdio.h> +#include <stdarg.h> +#include <setjmp.h> +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +void abor(void); +void blkfree(char **); +char **copyblk(char **); +void cwd(char *); +void do_delete(char *); +void dologout(int); +void fatal(char *); +int filename_check(char *); +int ftpd_pclose(FILE *); +FILE *ftpd_popen(char *, char *, int, int); +char *getline(char *, int); +void logwtmp(char *, char *, char *); +void lreply(int, const char *, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 2, 3))) +#endif +; +void makedir(char *); +void nack(char *); +void nreply(const char *, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; +void pass(char *); +void passive(void); +void perror_reply(int, char *); +void pwd(void); +void removedir(char *); +void renamecmd(char *, char *); +char *renamefrom(char *); +void reply(int, const char *, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 2, 3))) +#endif +; +void retrieve(char *, char *); +void send_file_list(char *); +void setproctitle(const char *, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; +void statcmd(void); +void statfilecmd(char *); +void do_store(char *, char *, int); +void upper(char *); +void user(char *); +void yyerror(char *); + +void kauth(char *, char*); +void klist(void); + +int find(char *); + +int do_login(int code, char *passwd); +int klogin(char *name, char *password); + +const char *ftp_rooted(const char *path); + +extern struct sockaddr_in ctrl_addr, his_addr; +extern char hostname[]; + +extern struct sockaddr_in data_dest; +extern int logged_in; +extern struct passwd *pw; +extern int guest; +extern int logging; +extern int type; +extern int oobflag; +extern off_t file_size; +extern off_t byte_count; +extern jmp_buf urgcatch; + +extern int form; +extern int debug; +extern int ftpd_timeout; +extern int maxtimeout; +extern int pdata; +extern char hostname[], remotehost[]; +extern char proctitle[]; +extern int usedefault; +extern int transflag; +extern char tmpline[]; + +#endif /* _EXTERN_H_ */ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y new file mode 100644 index 0000000..9368cdb --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y @@ -0,0 +1,1408 @@ +/* $NetBSD: ftpcmd.y,v 1.6 1995/06/03 22:46:45 mycroft Exp $ */ + +/* + * Copyright (c) 1985, 1988, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)ftpcmd.y 8.3 (Berkeley) 4/6/94 + */ + +/* + * Grammar for FTP commands. + * See RFC 959. + */ + +%{ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +RCSID("$Id: ftpcmd.y,v 1.35 1997/05/25 14:38:49 assar Exp $"); + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_FTP_H +#include <arpa/ftp.h> +#endif + +#include <ctype.h> +#include <errno.h> +#include <glob.h> +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif +#include <time.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_BSD_BSD_H +#include <bsd/bsd.h> +#endif + +#include <roken.h> + +#ifdef SOCKS +#include <socks.h> +extern int LIBPREFIX(fclose) __P((FILE *)); +#endif + +#include "extern.h" +#include "auth.h" + +off_t restart_point; + +static int cmd_type; +static int cmd_form; +static int cmd_bytesz; +char cbuf[512]; +char *fromname; + +struct tab { + char *name; + short token; + short state; + short implemented; /* 1 if command is implemented */ + char *help; +}; + +extern struct tab cmdtab[]; +extern struct tab sitetab[]; + +static char *copy (char *); +static void help (struct tab *, char *); +static struct tab * + lookup (struct tab *, char *); +static void sizecmd (char *); +static void toolong (int); +static int yylex (void); + +/* This is for bison */ + +#if !defined(alloca) && !defined(HAVE_ALLOCA) +#define alloca(x) malloc(x) +#endif + +%} + +%union { + int i; + char *s; +} + +%token + A B C E F I + L N P R S T + + SP CRLF COMMA + + USER PASS ACCT REIN QUIT PORT + PASV TYPE STRU MODE RETR STOR + APPE MLFL MAIL MSND MSOM MSAM + MRSQ MRCP ALLO REST RNFR RNTO + ABOR DELE CWD LIST NLST SITE + STAT HELP NOOP MKD RMD PWD + CDUP STOU SMNT SYST SIZE MDTM + + UMASK IDLE CHMOD + + AUTH ADAT PROT PBSZ CCC MIC + CONF ENC + + KAUTH KLIST FIND URL + + LEXERR + +%token <s> STRING +%token <i> NUMBER + +%type <i> check_login check_login_no_guest octal_number byte_size +%type <i> struct_code mode_code type_code form_code +%type <s> pathstring pathname password username + +%start cmd_list + +%% + +cmd_list + : /* empty */ + | cmd_list cmd + { + fromname = (char *) 0; + restart_point = (off_t) 0; + } + | cmd_list rcmd + ; + +cmd + : USER SP username CRLF + { + user($3); + free($3); + } + | AUTH SP STRING CRLF + { + auth($3); + free($3); + } + | ADAT SP STRING CRLF + { + adat($3); + free($3); + } + | PBSZ SP NUMBER CRLF + { + pbsz($3); + } + | PROT SP STRING CRLF + { + prot($3); + } + | CCC CRLF + { + ccc(); + } + | MIC SP STRING CRLF + { + mic($3); + free($3); + } + | CONF SP STRING CRLF + { + conf($3); + free($3); + } + | PASS SP password CRLF + { + pass($3); + memset ($3, 0, strlen($3)); + free($3); + } + | PORT SP host_port CRLF + { + usedefault = 0; + if (pdata >= 0) { + close(pdata); + pdata = -1; + } + reply(200, "PORT command successful."); + } + | PASV CRLF + { + passive(); + } + | TYPE SP type_code CRLF + { + switch (cmd_type) { + + case TYPE_A: + if (cmd_form == FORM_N) { + reply(200, "Type set to A."); + type = cmd_type; + form = cmd_form; + } else + reply(504, "Form must be N."); + break; + + case TYPE_E: + reply(504, "Type E not implemented."); + break; + + case TYPE_I: + reply(200, "Type set to I."); + type = cmd_type; + break; + + case TYPE_L: +#if NBBY == 8 + if (cmd_bytesz == 8) { + reply(200, + "Type set to L (byte size 8)."); + type = cmd_type; + } else + reply(504, "Byte size must be 8."); +#else /* NBBY == 8 */ + UNIMPLEMENTED for NBBY != 8 +#endif /* NBBY == 8 */ + } + } + | STRU SP struct_code CRLF + { + switch ($3) { + + case STRU_F: + reply(200, "STRU F ok."); + break; + + default: + reply(504, "Unimplemented STRU type."); + } + } + | MODE SP mode_code CRLF + { + switch ($3) { + + case MODE_S: + reply(200, "MODE S ok."); + break; + + default: + reply(502, "Unimplemented MODE type."); + } + } + | ALLO SP NUMBER CRLF + { + reply(202, "ALLO command ignored."); + } + | ALLO SP NUMBER SP R SP NUMBER CRLF + { + reply(202, "ALLO command ignored."); + } + | RETR check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + retrieve((char *) 0, $4); + if ($4 != NULL) + free($4); + } + | STOR check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + do_store($4, "w", 0); + if ($4 != NULL) + free($4); + } + | APPE check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + do_store($4, "a", 0); + if ($4 != NULL) + free($4); + } + | NLST check_login CRLF + { + if ($2) + send_file_list("."); + } + | NLST check_login SP STRING CRLF + { + if ($2 && $4 != NULL) + send_file_list($4); + if ($4 != NULL) + free($4); + } + | LIST check_login CRLF + { +#ifdef HAVE_LS_A + char *cmd = "/bin/ls -lA"; +#else + char *cmd = "/bin/ls -la"; +#endif + if ($2) + retrieve(cmd, ""); + + } + | LIST check_login SP pathname CRLF + { +#ifdef HAVE_LS_A + char *cmd = "/bin/ls -lA %s"; +#else + char *cmd = "/bin/ls -la %s"; +#endif + if ($2 && $4 != NULL) + retrieve(cmd, $4); + if ($4 != NULL) + free($4); + } + | STAT check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + statfilecmd($4); + if ($4 != NULL) + free($4); + } + | STAT CRLF + { + if(oobflag){ + if (file_size != (off_t) -1) + reply(213, "Status: %ld of %ld bytes transferred", + byte_count, file_size); + else + reply(213, "Status: %ld bytes transferred", byte_count); + }else + statcmd(); + } + | DELE check_login_no_guest SP pathname CRLF + { + if ($2 && $4 != NULL) + do_delete($4); + if ($4 != NULL) + free($4); + } + | RNTO check_login_no_guest SP pathname CRLF + { + if($2){ + if (fromname) { + renamecmd(fromname, $4); + free(fromname); + fromname = (char *) 0; + } else { + reply(503, "Bad sequence of commands."); + } + } + if ($4 != NULL) + free($4); + } + | ABOR CRLF + { + if(oobflag){ + reply(426, "Transfer aborted. Data connection closed."); + reply(226, "Abort successful"); + oobflag = 0; + longjmp(urgcatch, 1); + }else + reply(225, "ABOR command successful."); + } + | CWD check_login CRLF + { + if ($2) + cwd(pw->pw_dir); + } + | CWD check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + cwd($4); + if ($4 != NULL) + free($4); + } + | HELP CRLF + { + help(cmdtab, (char *) 0); + } + | HELP SP STRING CRLF + { + char *cp = $3; + + if (strncasecmp(cp, "SITE", 4) == 0) { + cp = $3 + 4; + if (*cp == ' ') + cp++; + if (*cp) + help(sitetab, cp); + else + help(sitetab, (char *) 0); + } else + help(cmdtab, $3); + } + | NOOP CRLF + { + reply(200, "NOOP command successful."); + } + | MKD check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + makedir($4); + if ($4 != NULL) + free($4); + } + | RMD check_login_no_guest SP pathname CRLF + { + if ($2 && $4 != NULL) + removedir($4); + if ($4 != NULL) + free($4); + } + | PWD check_login CRLF + { + if ($2) + pwd(); + } + | CDUP check_login CRLF + { + if ($2) + cwd(".."); + } + | SITE SP HELP CRLF + { + help(sitetab, (char *) 0); + } + | SITE SP HELP SP STRING CRLF + { + help(sitetab, $5); + } + | SITE SP UMASK check_login CRLF + { + int oldmask; + + if ($4) { + oldmask = umask(0); + umask(oldmask); + reply(200, "Current UMASK is %03o", oldmask); + } + } + | SITE SP UMASK check_login_no_guest SP octal_number CRLF + { + int oldmask; + + if ($4) { + if (($6 == -1) || ($6 > 0777)) { + reply(501, "Bad UMASK value"); + } else { + oldmask = umask($6); + reply(200, + "UMASK set to %03o (was %03o)", + $6, oldmask); + } + } + } + | SITE SP CHMOD check_login_no_guest SP octal_number SP pathname CRLF + { + if ($4 && $8 != NULL) { + if ($6 > 0777) + reply(501, + "CHMOD: Mode value must be between 0 and 0777"); + else if (chmod($8, $6) < 0) + perror_reply(550, $8); + else + reply(200, "CHMOD command successful."); + } + if ($8 != NULL) + free($8); + } + | SITE SP IDLE CRLF + { + reply(200, + "Current IDLE time limit is %d seconds; max %d", + ftpd_timeout, maxtimeout); + } + | SITE SP IDLE SP NUMBER CRLF + { + if ($5 < 30 || $5 > maxtimeout) { + reply(501, + "Maximum IDLE time must be between 30 and %d seconds", + maxtimeout); + } else { + ftpd_timeout = $5; + alarm((unsigned) ftpd_timeout); + reply(200, + "Maximum IDLE time set to %d seconds", + ftpd_timeout); + } + } + + | SITE SP KAUTH check_login SP STRING CRLF + { + char *p; + + if(guest) + reply(500, "Can't be done as guest."); + else{ + if($4 && $6 != NULL){ + p = strpbrk($6, " \t"); + if(p){ + *p++ = 0; + kauth($6, p + strspn(p, " \t")); + }else + kauth($6, NULL); + } + } + if($6 != NULL) + free($6); + } + | SITE SP KLIST check_login CRLF + { + if($4) + klist(); + } + | SITE SP FIND check_login SP STRING CRLF + { + if($4 && $6 != NULL) + find($6); + if($6 != NULL) + free($6); + } + | SITE SP URL CRLF + { + reply(200, "http://www.pdc.kth.se/kth-krb/"); + } + | STOU check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + do_store($4, "w", 1); + if ($4 != NULL) + free($4); + } + | SYST CRLF + { +#if defined(unix) || defined(__unix__) || defined(__unix) || defined(_AIX) || defined(_CRAY) + reply(215, "UNIX Type: L%d", NBBY); +#else + reply(215, "UNKNOWN Type: L%d", NBBY); +#endif + } + + /* + * SIZE is not in RFC959, but Postel has blessed it and + * it will be in the updated RFC. + * + * Return size of file in a format suitable for + * using with RESTART (we just count bytes). + */ + | SIZE check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + sizecmd($4); + if ($4 != NULL) + free($4); + } + + /* + * MDTM is not in RFC959, but Postel has blessed it and + * it will be in the updated RFC. + * + * Return modification time of file as an ISO 3307 + * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx + * where xxx is the fractional second (of any precision, + * not necessarily 3 digits) + */ + | MDTM check_login SP pathname CRLF + { + if ($2 && $4 != NULL) { + struct stat stbuf; + if (stat($4, &stbuf) < 0) + reply(550, "%s: %s", + $4, strerror(errno)); + else if (!S_ISREG(stbuf.st_mode)) { + reply(550, "%s: not a plain file.", $4); + } else { + struct tm *t; + t = gmtime(&stbuf.st_mtime); + reply(213, + "%04d%02d%02d%02d%02d%02d", + t->tm_year + 1900, + t->tm_mon + 1, + t->tm_mday, + t->tm_hour, + t->tm_min, + t->tm_sec); + } + } + if ($4 != NULL) + free($4); + } + | QUIT CRLF + { + reply(221, "Goodbye."); + dologout(0); + } + | error CRLF + { + yyerrok; + } + ; +rcmd + : RNFR check_login_no_guest SP pathname CRLF + { + restart_point = (off_t) 0; + if ($2 && $4) { + fromname = renamefrom($4); + if (fromname == (char *) 0 && $4) { + free($4); + } + } + } + | REST SP byte_size CRLF + { + fromname = (char *) 0; + restart_point = $3; /* XXX $3 is only "int" */ + reply(350, "Restarting at %ld. %s", + (long)restart_point, + "Send STORE or RETRIEVE to initiate transfer."); + } + | ENC SP STRING CRLF + { + enc($3); + free($3); + } + ; + +username + : STRING + ; + +password + : /* empty */ + { + $$ = (char *)calloc(1, sizeof(char)); + } + | STRING + ; + +byte_size + : NUMBER + ; + +host_port + : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA + NUMBER COMMA NUMBER + { + data_dest.sin_family = AF_INET; + data_dest.sin_port = htons($9 * 256 + $11); + data_dest.sin_addr.s_addr = + htonl(($1 << 24) | ($3 << 16) | ($5 << 8) | $7); + } + ; + +form_code + : N + { + $$ = FORM_N; + } + | T + { + $$ = FORM_T; + } + | C + { + $$ = FORM_C; + } + ; + +type_code + : A + { + cmd_type = TYPE_A; + cmd_form = FORM_N; + } + | A SP form_code + { + cmd_type = TYPE_A; + cmd_form = $3; + } + | E + { + cmd_type = TYPE_E; + cmd_form = FORM_N; + } + | E SP form_code + { + cmd_type = TYPE_E; + cmd_form = $3; + } + | I + { + cmd_type = TYPE_I; + } + | L + { + cmd_type = TYPE_L; + cmd_bytesz = NBBY; + } + | L SP byte_size + { + cmd_type = TYPE_L; + cmd_bytesz = $3; + } + /* this is for a bug in the BBN ftp */ + | L byte_size + { + cmd_type = TYPE_L; + cmd_bytesz = $2; + } + ; + +struct_code + : F + { + $$ = STRU_F; + } + | R + { + $$ = STRU_R; + } + | P + { + $$ = STRU_P; + } + ; + +mode_code + : S + { + $$ = MODE_S; + } + | B + { + $$ = MODE_B; + } + | C + { + $$ = MODE_C; + } + ; + +pathname + : pathstring + { + /* + * Problem: this production is used for all pathname + * processing, but only gives a 550 error reply. + * This is a valid reply in some cases but not in others. + */ + if (logged_in && $1 && *$1 == '~') { + glob_t gl; + int flags = + GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + if (glob($1, flags, NULL, &gl) || + gl.gl_pathc == 0) { + reply(550, "not found"); + $$ = NULL; + } else { + $$ = strdup(gl.gl_pathv[0]); + } + globfree(&gl); + free($1); + } else + $$ = $1; + } + ; + +pathstring + : STRING + ; + +octal_number + : NUMBER + { + int ret, dec, multby, digit; + + /* + * Convert a number that was read as decimal number + * to what it would be if it had been read as octal. + */ + dec = $1; + multby = 1; + ret = 0; + while (dec) { + digit = dec%10; + if (digit > 7) { + ret = -1; + break; + } + ret += digit * multby; + multby *= 8; + dec /= 10; + } + $$ = ret; + } + ; + + +check_login_no_guest : check_login + { + $$ = $1 && !guest; + if($1 && !$$) + reply(550, "Permission denied"); + } + ; + +check_login + : /* empty */ + { + if(auth_complete && prot_level == prot_clear){ + reply(533, "Command protection level denied for paranoid reasons."); + $$ = 0; + }else + if (logged_in) + $$ = 1; + else { + reply(530, "Please login with USER and PASS."); + $$ = 0; + } + } + ; + +%% + +extern jmp_buf errcatch; + +#define CMD 0 /* beginning of command */ +#define ARGS 1 /* expect miscellaneous arguments */ +#define STR1 2 /* expect SP followed by STRING */ +#define STR2 3 /* expect STRING */ +#define OSTR 4 /* optional SP then STRING */ +#define ZSTR1 5 /* SP then optional STRING */ +#define ZSTR2 6 /* optional STRING after SP */ +#define SITECMD 7 /* SITE command */ +#define NSTR 8 /* Number followed by a string */ + +struct tab cmdtab[] = { /* In order defined in RFC 765 */ + { "USER", USER, STR1, 1, "<sp> username" }, + { "PASS", PASS, ZSTR1, 1, "<sp> password" }, + { "ACCT", ACCT, STR1, 0, "(specify account)" }, + { "SMNT", SMNT, ARGS, 0, "(structure mount)" }, + { "REIN", REIN, ARGS, 0, "(reinitialize server state)" }, + { "QUIT", QUIT, ARGS, 1, "(terminate service)", }, + { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" }, + { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, + { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" }, + { "STRU", STRU, ARGS, 1, "(specify file structure)" }, + { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, + { "RETR", RETR, STR1, 1, "<sp> file-name" }, + { "STOR", STOR, STR1, 1, "<sp> file-name" }, + { "APPE", APPE, STR1, 1, "<sp> file-name" }, + { "MLFL", MLFL, OSTR, 0, "(mail file)" }, + { "MAIL", MAIL, OSTR, 0, "(mail to user)" }, + { "MSND", MSND, OSTR, 0, "(mail send to terminal)" }, + { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" }, + { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" }, + { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" }, + { "MRCP", MRCP, STR1, 0, "(mail recipient)" }, + { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" }, + { "REST", REST, ARGS, 1, "<sp> offset (restart command)" }, + { "RNFR", RNFR, STR1, 1, "<sp> file-name" }, + { "RNTO", RNTO, STR1, 1, "<sp> file-name" }, + { "ABOR", ABOR, ARGS, 1, "(abort operation)" }, + { "DELE", DELE, STR1, 1, "<sp> file-name" }, + { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" }, + { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" }, + { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" }, + { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" }, + { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" }, + { "SYST", SYST, ARGS, 1, "(get type of operating system)" }, + { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" }, + { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" }, + { "NOOP", NOOP, ARGS, 1, "" }, + { "MKD", MKD, STR1, 1, "<sp> path-name" }, + { "XMKD", MKD, STR1, 1, "<sp> path-name" }, + { "RMD", RMD, STR1, 1, "<sp> path-name" }, + { "XRMD", RMD, STR1, 1, "<sp> path-name" }, + { "PWD", PWD, ARGS, 1, "(return current directory)" }, + { "XPWD", PWD, ARGS, 1, "(return current directory)" }, + { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "STOU", STOU, STR1, 1, "<sp> file-name" }, + { "SIZE", SIZE, OSTR, 1, "<sp> path-name" }, + { "MDTM", MDTM, OSTR, 1, "<sp> path-name" }, + + /* extensions from draft-ietf-cat-ftpsec-08 */ + { "AUTH", AUTH, STR1, 1, "<sp> auth-type" }, + { "ADAT", ADAT, STR1, 1, "<sp> auth-data" }, + { "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" }, + { "PROT", PROT, STR1, 1, "<sp> prot-level" }, + { "CCC", CCC, ARGS, 1, "" }, + { "MIC", MIC, STR1, 1, "<sp> integrity command" }, + { "CONF", CONF, STR1, 1, "<sp> confidentiality command" }, + { "ENC", ENC, STR1, 1, "<sp> privacy command" }, + + { NULL, 0, 0, 0, 0 } +}; + +struct tab sitetab[] = { + { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" }, + { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" }, + { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" }, + { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" }, + + { "KAUTH", KAUTH, STR1, 1, "<sp> principal [ <sp> ticket ]" }, + { "KLIST", KLIST, ARGS, 1, "(show ticket file)" }, + + { "FIND", FIND, STR1, 1, "<sp> globexpr" }, + + { "URL", URL, ARGS, 1, "?" }, + + { NULL, 0, 0, 0, 0 } +}; + +static struct tab * +lookup(struct tab *p, char *cmd) +{ + + for (; p->name != NULL; p++) + if (strcmp(cmd, p->name) == 0) + return (p); + return (0); +} + +#include <arpa/telnet.h> + +/* + * getline - a hacked up version of fgets to ignore TELNET escape codes. + */ +char * +getline(char *s, int n) +{ + int c; + char *cs; + + cs = s; +/* tmpline may contain saved command from urgent mode interruption */ + if(ftp_command){ + strncpy(s, ftp_command, n); + if (debug) + syslog(LOG_DEBUG, "command: %s", s); +#ifdef XXX + fprintf(stderr, "%s\n", s); +#endif + return s; + } + prot_level = prot_clear; + while ((c = getc(stdin)) != EOF) { + c &= 0377; + if (c == IAC) { + if ((c = getc(stdin)) != EOF) { + c &= 0377; + switch (c) { + case WILL: + case WONT: + c = getc(stdin); + printf("%c%c%c", IAC, DONT, 0377&c); + fflush(stdout); + continue; + case DO: + case DONT: + c = getc(stdin); + printf("%c%c%c", IAC, WONT, 0377&c); + fflush(stdout); + continue; + case IAC: + break; + default: + continue; /* ignore command */ + } + } + } + *cs++ = c; + if (--n <= 0 || c == '\n') + break; + } + if (c == EOF && cs == s) + return (NULL); + *cs++ = '\0'; + if (debug) { + if (!guest && strncasecmp("pass ", s, 5) == 0) { + /* Don't syslog passwords */ + syslog(LOG_DEBUG, "command: %.5s ???", s); + } else { + char *cp; + int len; + + /* Don't syslog trailing CR-LF */ + len = strlen(s); + cp = s + len - 1; + while (cp >= s && (*cp == '\n' || *cp == '\r')) { + --cp; + --len; + } + syslog(LOG_DEBUG, "command: %.*s", len, s); + } + } +#ifdef XXX + fprintf(stderr, "%s\n", s); +#endif + return (s); +} + +static RETSIGTYPE +toolong(int signo) +{ + + reply(421, + "Timeout (%d seconds): closing control connection.", + ftpd_timeout); + if (logging) + syslog(LOG_INFO, "User %s timed out after %d seconds", + (pw ? pw -> pw_name : "unknown"), ftpd_timeout); + dologout(1); + SIGRETURN(0); +} + +static int +yylex(void) +{ + static int cpos, state; + char *cp, *cp2; + struct tab *p; + int n; + char c; + + for (;;) { + switch (state) { + + case CMD: + signal(SIGALRM, toolong); + alarm((unsigned) ftpd_timeout); + if (getline(cbuf, sizeof(cbuf)-1) == NULL) { + reply(221, "You could at least say goodbye."); + dologout(0); + } + alarm(0); +#ifdef HASSETPROCTITLE + if (strncasecmp(cbuf, "PASS", 4) != NULL) + setproctitle("%s: %s", proctitle, cbuf); +#endif /* HASSETPROCTITLE */ + if ((cp = strchr(cbuf, '\r'))) { + *cp++ = '\n'; + *cp = '\0'; + } + if ((cp = strpbrk(cbuf, " \n"))) + cpos = cp - cbuf; + if (cpos == 0) + cpos = 4; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + strupr(cbuf); + p = lookup(cmdtab, cbuf); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + nack(p->name); + longjmp(errcatch,0); + /* NOTREACHED */ + } + state = p->state; + yylval.s = p->name; + return (p->token); + } + break; + + case SITECMD: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + cp = &cbuf[cpos]; + if ((cp2 = strpbrk(cp, " \n"))) + cpos = cp2 - cbuf; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + strupr(cp); + p = lookup(sitetab, cp); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + state = CMD; + nack(p->name); + longjmp(errcatch,0); + /* NOTREACHED */ + } + state = p->state; + yylval.s = p->name; + return (p->token); + } + state = CMD; + break; + + case OSTR: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR1: + case ZSTR1: + dostr1: + if (cbuf[cpos] == ' ') { + cpos++; + state = state == OSTR ? STR2 : ++state; + return (SP); + } + break; + + case ZSTR2: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR2: + cp = &cbuf[cpos]; + n = strlen(cp); + cpos += n - 1; + /* + * Make sure the string is nonempty and \n terminated. + */ + if (n > 1 && cbuf[cpos] == '\n') { + cbuf[cpos] = '\0'; + yylval.s = copy(cp); + cbuf[cpos] = '\n'; + state = ARGS; + return (STRING); + } + break; + + case NSTR: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + if (isdigit(cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit(cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval.i = atoi(cp); + cbuf[cpos] = c; + state = STR1; + return (NUMBER); + } + state = STR1; + goto dostr1; + + case ARGS: + if (isdigit(cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit(cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval.i = atoi(cp); + cbuf[cpos] = c; + return (NUMBER); + } + switch (cbuf[cpos++]) { + + case '\n': + state = CMD; + return (CRLF); + + case ' ': + return (SP); + + case ',': + return (COMMA); + + case 'A': + case 'a': + return (A); + + case 'B': + case 'b': + return (B); + + case 'C': + case 'c': + return (C); + + case 'E': + case 'e': + return (E); + + case 'F': + case 'f': + return (F); + + case 'I': + case 'i': + return (I); + + case 'L': + case 'l': + return (L); + + case 'N': + case 'n': + return (N); + + case 'P': + case 'p': + return (P); + + case 'R': + case 'r': + return (R); + + case 'S': + case 's': + return (S); + + case 'T': + case 't': + return (T); + + } + break; + + default: + fatal("Unknown state in scanner."); + } + yyerror((char *) 0); + state = CMD; + longjmp(errcatch,0); + } +} + +static char * +copy(char *s) +{ + char *p; + + p = strdup(s); + if (p == NULL) + fatal("Ran out of memory."); + return p; +} + +static void +help(struct tab *ctab, char *s) +{ + struct tab *c; + int width, NCMDS; + char *type; + char buf[1024]; + + if (ctab == sitetab) + type = "SITE "; + else + type = ""; + width = 0, NCMDS = 0; + for (c = ctab; c->name != NULL; c++) { + int len = strlen(c->name); + + if (len > width) + width = len; + NCMDS++; + } + width = (width + 8) &~ 7; + if (s == 0) { + int i, j, w; + int columns, lines; + + lreply(214, "The following %scommands are recognized %s.", + type, "(* =>'s unimplemented)"); + columns = 76 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + strcpy (buf, " "); + for (j = 0; j < columns; j++) { + c = ctab + j * lines + i; + snprintf (buf + strlen(buf), sizeof(buf) - strlen(buf), + "%s%c", c->name, c->implemented ? ' ' : '*'); + if (c + lines >= &ctab[NCMDS]) + break; + w = strlen(c->name) + 1; + while (w < width) { + strcat(buf, " "); + w++; + } + } + lreply(214, buf); + } + reply(214, "Direct comments to kth-krb-bugs@pdc.kth.se"); + return; + } + strupr(s); + c = lookup(ctab, s); + if (c == (struct tab *)0) { + reply(502, "Unknown command %s.", s); + return; + } + if (c->implemented) + reply(214, "Syntax: %s%s %s", type, c->name, c->help); + else + reply(214, "%s%-*s\t%s; unimplemented.", type, width, + c->name, c->help); +} + +static void +sizecmd(char *filename) +{ + switch (type) { + case TYPE_L: + case TYPE_I: { + struct stat stbuf; + if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) + reply(550, "%s: not a plain file.", filename); + else + reply(213, "%lu", (unsigned long)stbuf.st_size); + break; } + case TYPE_A: { + FILE *fin; + int c; + off_t count; + struct stat stbuf; + fin = fopen(filename, "r"); + if (fin == NULL) { + perror_reply(550, filename); + return; + } + if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) { + reply(550, "%s: not a plain file.", filename); + fclose(fin); + return; + } + + count = 0; + while((c=getc(fin)) != EOF) { + if (c == '\n') /* will get expanded to \r\n */ + count++; + count++; + } + fclose(fin); + + reply(213, "%ld", count); + break; } + default: + reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); + } +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c new file mode 100644 index 0000000..17cd3b9 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c @@ -0,0 +1,2076 @@ +/* + * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +RCSID("$Id: ftpd.c,v 1.88 1997/06/01 03:13:48 assar Exp $"); +#endif + +/* + * FTP server. + */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4 +#include <sys/ioctl.h> +#endif +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif + +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +#define FTP_NAMES +#include <arpa/ftp.h> +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_TELNET_H +#include <arpa/telnet.h> +#endif + +#include <ctype.h> +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif +#include <errno.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <glob.h> +#include <limits.h> +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif +#include <time.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_GRP_H +#include <grp.h> +#endif + +#include <err.h> + +#include "pathnames.h" +#include "extern.h" +#include "common.h" + +#include "auth.h" + +#include <krb.h> + +#include <kafs.h> +#include "roken.h" + +#include <otp.h> + +#ifdef SOCKS +#include <socks.h> +extern int LIBPREFIX(fclose) __P((FILE *)); +#endif + +void yyparse(); + +#ifndef LOG_FTP +#define LOG_FTP LOG_DAEMON +#endif + +static char version[] = "Version 6.00"; + +extern off_t restart_point; +extern char cbuf[]; + +struct sockaddr_in ctrl_addr; +struct sockaddr_in data_source; +struct sockaddr_in data_dest; +struct sockaddr_in his_addr; +struct sockaddr_in pasv_addr; + +int data; +jmp_buf errcatch, urgcatch; +int oobflag; +int logged_in; +struct passwd *pw; +int debug; +int ftpd_timeout = 900; /* timeout after 15 minutes of inactivity */ +int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ +int logging; +int guest; +int dochroot; +int type; +int form; +int stru; /* avoid C keyword */ +int mode; +int usedefault = 1; /* for data transfers */ +int pdata = -1; /* for passive mode */ +int transflag; +off_t file_size; +off_t byte_count; +#if !defined(CMASK) || CMASK == 0 +#undef CMASK +#define CMASK 027 +#endif +int defumask = CMASK; /* default umask value */ +int guest_umask = 0777; /* Paranoia for anonymous users */ +char tmpline[10240]; +char hostname[MaxHostNameLen]; +char remotehost[MaxHostNameLen]; +static char ttyline[20]; + +#define AUTH_PLAIN (1 << 0) /* allow sending passwords */ +#define AUTH_OTP (1 << 1) /* passwords are one-time */ +#define AUTH_FTP (1 << 2) /* allow anonymous login */ + +static int auth_level = 0; /* Only allow kerberos login by default */ + +/* + * Timeout intervals for retrying connections + * to hosts that don't accept PORT cmds. This + * is a kludge, but given the problems with TCP... + */ +#define SWAITMAX 90 /* wait at most 90 seconds */ +#define SWAITINT 5 /* interval between retries */ + +int swaitmax = SWAITMAX; +int swaitint = SWAITINT; + +#ifdef HAVE_SETPROCTITLE +char proctitle[BUFSIZ]; /* initial part of title */ +#endif /* HAVE_SETPROCTITLE */ + +#define LOGCMD(cmd, file) \ + if (logging > 1) \ + syslog(LOG_INFO,"%s %s%s", cmd, \ + *(file) == '/' ? "" : curdir(), file); +#define LOGCMD2(cmd, file1, file2) \ + if (logging > 1) \ + syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ + *(file1) == '/' ? "" : curdir(), file1, \ + *(file2) == '/' ? "" : curdir(), file2); +#define LOGBYTES(cmd, file, cnt) \ + if (logging > 1) { \ + if (cnt == (off_t)-1) \ + syslog(LOG_INFO,"%s %s%s", cmd, \ + *(file) == '/' ? "" : curdir(), file); \ + else \ + syslog(LOG_INFO, "%s %s%s = %ld bytes", \ + cmd, (*(file) == '/') ? "" : curdir(), file, (long)cnt); \ + } + +static void ack (char *); +static void myoob (int); +static int checkuser (char *, char *); +static int checkaccess (char *); +static FILE *dataconn (char *, off_t, char *); +static void dolog (struct sockaddr_in *); +static void end_login (void); +static FILE *getdatasock (char *); +static char *gunique (char *); +static RETSIGTYPE lostconn (int); +static int receive_data (FILE *, FILE *); +static void send_data (FILE *, FILE *); +static struct passwd * sgetpwnam (char *); +static void usage(void); + +static char * +curdir(void) +{ + static char path[MaxPathLen+1+1]; /* path + '/' + '\0' */ + + if (getcwd(path, sizeof(path)-2) == NULL) + return (""); + if (path[1] != '\0') /* special case for root dir. */ + strcat(path, "/"); + /* For guest account, skip / since it's chrooted */ + return (guest ? path+1 : path); +} + +#ifndef LINE_MAX +#define LINE_MAX 1024 +#endif + +static int +parse_auth_level(char *str) +{ + char *p; + int ret = 0; + char *foo = NULL; + + for(p = strtok_r(str, ",", &foo); + p; + p = strtok_r(NULL, ",", &foo)) { + if(strcmp(p, "user") == 0) + ; + else if(strcmp(p, "otp") == 0) + ret |= AUTH_PLAIN|AUTH_OTP; + else if(strcmp(p, "ftp") == 0 || + strcmp(p, "safe") == 0) + ret |= AUTH_FTP; + else if(strcmp(p, "plain") == 0) + ret |= AUTH_PLAIN; + else if(strcmp(p, "none") == 0) + ret |= AUTH_PLAIN|AUTH_FTP; + else + warnx("bad value for -a: `%s'", p); + } + return ret; +} + +/* + * Print usage and die. + */ + +static void +usage (void) +{ + fprintf (stderr, + "Usage: %s [-d] [-i] [-g guest_umask] [-l] [-p port]" + " [-t timeout] [-T max_timeout] [-u umask] [-v]" + " [-a auth_level] \n", + __progname); + exit (1); +} + +int +main(int argc, char **argv) +{ + int addrlen, ch, on = 1, tos; + char *cp, line[LINE_MAX]; + FILE *fd; + int not_inetd = 0; + int port; + struct servent *sp; + char tkfile[1024]; + + set_progname (argv[0]); + + /* detach from any tickets and tokens */ + + snprintf(tkfile, sizeof(tkfile), + "/tmp/ftp_%u", (unsigned)getpid()); + krb_set_tkt_string(tkfile); + if(k_hasafs()) + k_setpag(); + + sp = getservbyname("ftp", "tcp"); + if(sp) + port = sp->s_port; + else + port = htons(21); + + while ((ch = getopt(argc, argv, "a:dg:ilp:t:T:u:v")) != EOF) { + switch (ch) { + case 'a': + auth_level = parse_auth_level(optarg); + break; + case 'd': + debug = 1; + break; + + case 'i': + not_inetd = 1; + break; + case 'g': + { + long val = 0; + + val = strtol(optarg, &optarg, 8); + if (*optarg != '\0' || val < 0) + warnx("bad value for -g"); + else + guest_umask = val; + break; + } + case 'l': + logging++; /* > 1 == extra logging */ + break; + + case 'p': + sp = getservbyname(optarg, "tcp"); + if(sp) + port = sp->s_port; + else + if(isdigit(optarg[0])) + port = htons(atoi(optarg)); + else + warnx("bad value for -p"); + break; + + case 't': + ftpd_timeout = atoi(optarg); + if (maxtimeout < ftpd_timeout) + maxtimeout = ftpd_timeout; + break; + + case 'T': + maxtimeout = atoi(optarg); + if (ftpd_timeout > maxtimeout) + ftpd_timeout = maxtimeout; + break; + + case 'u': + { + long val = 0; + + val = strtol(optarg, &optarg, 8); + if (*optarg != '\0' || val < 0) + warnx("bad value for -u"); + else + defumask = val; + break; + } + + case 'v': + debug = 1; + break; + + default: + usage (); + } + } + + if(not_inetd) + mini_inetd (port); + + /* + * LOG_NDELAY sets up the logging connection immediately, + * necessary for anonymous ftp's that chroot and can't do it later. + */ + openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); + addrlen = sizeof(his_addr); + if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); + exit(1); + } + addrlen = sizeof(ctrl_addr); + if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); + exit(1); + } +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + tos = IPTOS_LOWDELAY; + if (setsockopt(0, IPPROTO_IP, IP_TOS, (void *)&tos, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); +#endif + data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); + debug = 0; + + /* set this here so it can be put in wtmp */ + snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid()); + + + /* freopen(_PATH_DEVNULL, "w", stderr); */ + signal(SIGPIPE, lostconn); + signal(SIGCHLD, SIG_IGN); +#ifdef SIGURG + if (signal(SIGURG, myoob) == SIG_ERR) + syslog(LOG_ERR, "signal: %m"); +#endif + + auth_init(); + + /* Try to handle urgent data inline */ +#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) + if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on, + sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt: %m"); +#endif + +#ifdef F_SETOWN + if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) + syslog(LOG_ERR, "fcntl F_SETOWN: %m"); +#endif + dolog(&his_addr); + /* + * Set up default state + */ + data = -1; + type = TYPE_A; + form = FORM_N; + stru = STRU_F; + mode = MODE_S; + tmpline[0] = '\0'; + + /* If logins are disabled, print out the message. */ + if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(530, "%s", line); + } + fflush(stdout); + fclose(fd); + reply(530, "System not available."); + exit(0); + } + if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(220, "%s", line); + } + fflush(stdout); + fclose(fd); + /* reply(220,) must follow */ + } + k_gethostname(hostname, sizeof(hostname)); + reply(220, "%s FTP server (%s+%s) ready.", hostname, + version, krb4_version); + setjmp(errcatch); + for (;;) + yyparse(); + /* NOTREACHED */ +} + +static RETSIGTYPE +lostconn(int signo) +{ + + if (debug) + syslog(LOG_DEBUG, "lost connection"); + dologout(-1); +} + +/* + * Helper function for sgetpwnam(). + */ +static char * +sgetsave(char *s) +{ + char *new = strdup(s); + + if (new == NULL) { + perror_reply(421, "Local resource failure: malloc"); + dologout(1); + /* NOTREACHED */ + } + return new; +} + +/* + * Save the result of a getpwnam. Used for USER command, since + * the data returned must not be clobbered by any other command + * (e.g., globbing). + */ +static struct passwd * +sgetpwnam(char *name) +{ + static struct passwd save; + struct passwd *p; + + if ((p = k_getpwnam(name)) == NULL) + return (p); + if (save.pw_name) { + free(save.pw_name); + free(save.pw_passwd); + free(save.pw_gecos); + free(save.pw_dir); + free(save.pw_shell); + } + save = *p; + save.pw_name = sgetsave(p->pw_name); + save.pw_passwd = sgetsave(p->pw_passwd); + save.pw_gecos = sgetsave(p->pw_gecos); + save.pw_dir = sgetsave(p->pw_dir); + save.pw_shell = sgetsave(p->pw_shell); + return (&save); +} + +static int login_attempts; /* number of failed login attempts */ +static int askpasswd; /* had user command, ask for passwd */ +static char curname[10]; /* current USER name */ +OtpContext otp_ctx; + +/* + * USER command. + * Sets global passwd pointer pw if named account exists and is acceptable; + * sets askpasswd if a PASS command is expected. If logged in previously, + * need to reset state. If name is "ftp" or "anonymous", the name is not in + * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. + * If account doesn't exist, ask for passwd anyway. Otherwise, check user + * requesting login privileges. Disallow anyone who does not have a standard + * shell as returned by getusershell(). Disallow anyone mentioned in the file + * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. + */ +void +user(char *name) +{ + char *cp, *shell; + + if(auth_level == 0 && !auth_complete){ + reply(530, "No login allowed without authorization."); + return; + } + + if (logged_in) { + if (guest) { + reply(530, "Can't change user from guest login."); + return; + } else if (dochroot) { + reply(530, "Can't change user from chroot user."); + return; + } + end_login(); + } + + guest = 0; + if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { + if ((auth_level & AUTH_FTP) == 0 || + checkaccess("ftp") || + checkaccess("anonymous")) + reply(530, "User %s access denied.", name); + else if ((pw = sgetpwnam("ftp")) != NULL) { + guest = 1; + defumask = guest_umask; /* paranoia for incoming */ + askpasswd = 1; + reply(331, "Guest login ok, type your name as password."); + } else + reply(530, "User %s unknown.", name); + if (!askpasswd && logging) + syslog(LOG_NOTICE, + "ANONYMOUS FTP LOGIN REFUSED FROM %s(%s)", + remotehost, inet_ntoa(his_addr.sin_addr)); + return; + } + if((auth_level & AUTH_PLAIN) == 0 && !auth_complete){ + reply(530, "Only authorized and anonymous login allowed."); + return; + } + if ((pw = sgetpwnam(name))) { + if ((shell = pw->pw_shell) == NULL || *shell == 0) + shell = _PATH_BSHELL; + while ((cp = getusershell()) != NULL) + if (strcmp(cp, shell) == 0) + break; + endusershell(); + + if (cp == NULL || checkaccess(name)) { + reply(530, "User %s access denied.", name); + if (logging) + syslog(LOG_NOTICE, + "FTP LOGIN REFUSED FROM %s(%s), %s", + remotehost, + inet_ntoa(his_addr.sin_addr), + name); + pw = (struct passwd *) NULL; + return; + } + } + if (logging) + strncpy(curname, name, sizeof(curname)-1); + if(auth_ok()) + ct->userok(name); + else { + char ss[256]; + + if (otp_challenge(&otp_ctx, name, ss, sizeof(ss)) == 0) { + reply(331, "Password %s for %s required.", + ss, name); + askpasswd = 1; + } else if ((auth_level & AUTH_OTP) == 0) { + reply(331, "Password required for %s.", name); + askpasswd = 1; + } else { + char *s; + + if (s = otp_error (&otp_ctx)) + lreply(530, "OTP: %s", s); + reply(530, + "Only authorized, anonymous and OTP " + "login allowed."); + } + + } + /* + * Delay before reading passwd after first failed + * attempt to slow down passwd-guessing programs. + */ + if (login_attempts) + sleep(login_attempts); +} + +/* + * Check if a user is in the file "fname" + */ +static int +checkuser(char *fname, char *name) +{ + FILE *fd; + int found = 0; + char *p, line[BUFSIZ]; + + if ((fd = fopen(fname, "r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) + if ((p = strchr(line, '\n')) != NULL) { + *p = '\0'; + if (line[0] == '#') + continue; + if (strcmp(line, name) == 0) { + found = 1; + break; + } + } + fclose(fd); + } + return (found); +} + + +/* + * Determine whether a user has access, based on information in + * _PATH_FTPUSERS. The users are listed one per line, with `allow' + * or `deny' after the username. If anything other than `allow', or + * just nothing, is given after the username, `deny' is assumed. + * + * If the user is not found in the file, but the pseudo-user `*' is, + * the permission is taken from that line. + * + * This preserves the old semantics where if a user was listed in the + * file he was denied, otherwise he was allowed. + * + * Return 1 if the user is denied, or 0 if he is allowed. */ + +static int +match(const char *pattern, const char *string) +{ +#ifdef HAVE_FNMATCH + return fnmatch(pattern, string, FNM_NOESCAPE); +#else + return strcmp(pattern, "*") != 0 && strcmp(pattern, string) != 0; +#endif +} + +static int +checkaccess(char *name) +{ +#define ALLOWED 0 +#define NOT_ALLOWED 1 + FILE *fd; + int allowed = ALLOWED; + char *user, *perm, line[BUFSIZ]; + char *foo; + + fd = fopen(_PATH_FTPUSERS, "r"); + + if(fd == NULL) + return allowed; + + while (fgets(line, sizeof(line), fd) != NULL) { + foo = NULL; + user = strtok_r(line, " \t\n", &foo); + if (user == NULL || user[0] == '#') + continue; + perm = strtok_r(NULL, " \t\n", &foo); + if (match(user, name) == 0){ + if(perm && strcmp(perm, "allow") == 0) + allowed = ALLOWED; + else + allowed = NOT_ALLOWED; + break; + } + } + fclose(fd); + return allowed; +} +#undef ALLOWED +#undef NOT_ALLOWED + +int do_login(int code, char *passwd) +{ + FILE *fd; + login_attempts = 0; /* this time successful */ + if (setegid((gid_t)pw->pw_gid) < 0) { + reply(550, "Can't set gid."); + return -1; + } + initgroups(pw->pw_name, pw->pw_gid); + + /* open wtmp before chroot */ + logwtmp(ttyline, pw->pw_name, remotehost); + logged_in = 1; + + dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name); + if (guest) { + /* + * We MUST do a chdir() after the chroot. Otherwise + * the old current directory will be accessible as "." + * outside the new root! + */ + if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + reply(550, "Can't set guest privileges."); + return -1; + } + } else if (dochroot) { + if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + reply(550, "Can't change root."); + return -1; + } + } else if (chdir(pw->pw_dir) < 0) { + if (chdir("/") < 0) { + reply(530, "User %s: can't change directory to %s.", + pw->pw_name, pw->pw_dir); + return -1; + } else + lreply(code, "No directory! Logging in with home=/"); + } + if (seteuid((uid_t)pw->pw_uid) < 0) { + reply(550, "Can't set uid."); + return -1; + } + /* + * Display a login message, if it exists. + * N.B. reply(code,) must follow the message. + */ + if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { + char *cp, line[LINE_MAX]; + + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(code, "%s", line); + } + } + if (guest) { + reply(code, "Guest login ok, access restrictions apply."); +#ifdef HAVE_SETPROCTITLE + snprintf (proctitle, sizeof(proctitle), + "%s: anonymous/%s", + remotehost, + passwd); +#endif /* HAVE_SETPROCTITLE */ + if (logging) + syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s(%s), %s", + remotehost, + inet_ntoa(his_addr.sin_addr), + passwd); + } else { + reply(code, "User %s logged in.", pw->pw_name); +#ifdef HAVE_SETPROCTITLE + snprintf(proctitle, sizeof(proctitle), "%s: %s", remotehost, pw->pw_name); + setproctitle(proctitle); +#endif /* HAVE_SETPROCTITLE */ + if (logging) + syslog(LOG_INFO, "FTP LOGIN FROM %s(%s) as %s", + remotehost, + inet_ntoa(his_addr.sin_addr), + pw->pw_name); + } + umask(defumask); + return 0; +} + +/* + * Terminate login as previous user, if any, resetting state; + * used when USER command is given or login fails. + */ +static void +end_login(void) +{ + + seteuid((uid_t)0); + if (logged_in) + logwtmp(ttyline, "", ""); + pw = NULL; + logged_in = 0; + guest = 0; + dochroot = 0; +} + +void +pass(char *passwd) +{ + int rval; + + /* some clients insists on sending a password */ + if (logged_in && askpasswd == 0){ + reply(230, "Dumpucko!"); + return; + } + + if (logged_in || askpasswd == 0) { + reply(503, "Login with USER first."); + return; + } + askpasswd = 0; + rval = 1; + if (!guest) { /* "ftp" is only account allowed no password */ + if (pw == NULL) + rval = 1; /* failure below */ + else if (otp_verify_user (&otp_ctx, passwd) == 0) { + rval = 0; + } else if((auth_level & AUTH_OTP) == 0) { + char realm[REALM_SZ]; + if((rval = krb_get_lrealm(realm, 1)) == KSUCCESS) + rval = krb_verify_user(pw->pw_name, "", realm, + passwd, 1, NULL); + if (rval == KSUCCESS ){ + if(k_hasafs()) + k_afsklog(0, 0); + }else + rval = unix_verify_user(pw->pw_name, passwd); + } else { + char *s; + + if (s = otp_error(&otp_ctx)) + lreply(530, "OTP: %s", s); + } + memset (passwd, 0, strlen(passwd)); + + /* + * If rval == 1, the user failed the authentication + * check above. If rval == 0, either Kerberos or + * local authentication succeeded. + */ + if (rval) { + reply(530, "Login incorrect."); + if (logging) + syslog(LOG_NOTICE, + "FTP LOGIN FAILED FROM %s(%s), %s", + remotehost, + inet_ntoa(his_addr.sin_addr), + curname); + pw = NULL; + if (login_attempts++ >= 5) { + syslog(LOG_NOTICE, + "repeated login failures from %s(%s)", + remotehost, + inet_ntoa(his_addr.sin_addr)); + exit(0); + } + return; + } + } + if(!do_login(230, passwd)) + return; + + /* Forget all about it... */ + end_login(); +} + +void +retrieve(char *cmd, char *name) +{ + FILE *fin = NULL, *dout; + struct stat st; + int (*closefunc) (FILE *); + char line[BUFSIZ]; + + + if (cmd == 0) { + fin = fopen(name, "r"); + closefunc = fclose; + st.st_size = 0; + if(fin == NULL){ + struct cmds { + char *ext; + char *cmd; + } cmds[] = { + {".tar", "/bin/gtar cPf - %s"}, + {".tar.gz", "/bin/gtar zcPf - %s"}, + {".tar.Z", "/bin/gtar ZcPf - %s"}, + {".gz", "/bin/gzip -c %s"}, + {".Z", "/bin/compress -c %s"}, + {NULL, NULL} + }; + struct cmds *p; + for(p = cmds; p->ext; p++){ + char *tail = name + strlen(name) - strlen(p->ext); + char c = *tail; + + if(strcmp(tail, p->ext) == 0 && + (*tail = 0) == 0 && + access(name, R_OK) == 0){ + snprintf (line, sizeof(line), p->cmd, name); + *tail = c; + break; + } + *tail = c; + } + if(p->ext){ + fin = ftpd_popen(line, "r", 0, 0); + closefunc = ftpd_pclose; + st.st_size = -1; + cmd = line; + } + } + } else { + snprintf(line, sizeof(line), cmd, name); + name = line; + fin = ftpd_popen(line, "r", 1, 0); + closefunc = ftpd_pclose; + st.st_size = -1; + } + if (fin == NULL) { + if (errno != 0) { + perror_reply(550, name); + if (cmd == 0) { + LOGCMD("get", name); + } + } + return; + } + byte_count = -1; + if (cmd == 0){ + if(fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) { + reply(550, "%s: not a plain file.", name); + goto done; + } + } + if (restart_point) { + if (type == TYPE_A) { + off_t i, n; + int c; + + n = restart_point; + i = 0; + while (i++ < n) { + if ((c=getc(fin)) == EOF) { + perror_reply(550, name); + goto done; + } + if (c == '\n') + i++; + } + } else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) { + perror_reply(550, name); + goto done; + } + } + dout = dataconn(name, st.st_size, "w"); + if (dout == NULL) + goto done; + set_buffer_size(fileno(dout), 0); + send_data(fin, dout); + fclose(dout); + data = -1; + pdata = -1; +done: + if (cmd == 0) + LOGBYTES("get", name, byte_count); + (*closefunc)(fin); +} + +/* filename sanity check */ + +int +filename_check(char *filename) +{ + static const char good_chars[] = "+-=_,."; + char *p; + + p = strrchr(filename, '/'); + if(p) + filename = p + 1; + + p = filename; + + if(isalnum(*p)){ + p++; + while(*p && (isalnum(*p) || strchr(good_chars, *p))) + p++; + if(*p == '\0') + return 0; + } + lreply(553, "\"%s\" is an illegal filename.", filename); + lreply(553, "The filename must start with an alphanumeric " + "character and must only"); + reply(553, "consist of alphanumeric characters or any of the following: %s", + good_chars); + return 1; +} + +void +do_store(char *name, char *mode, int unique) +{ + FILE *fout, *din; + struct stat st; + int (*closefunc) (FILE *); + + if(guest && filename_check(name)) + return; + if (unique && stat(name, &st) == 0 && + (name = gunique(name)) == NULL) { + LOGCMD(*mode == 'w' ? "put" : "append", name); + return; + } + + if (restart_point) + mode = "r+"; + fout = fopen(name, mode); + closefunc = fclose; + if (fout == NULL) { + perror_reply(553, name); + LOGCMD(*mode == 'w' ? "put" : "append", name); + return; + } + byte_count = -1; + if (restart_point) { + if (type == TYPE_A) { + off_t i, n; + int c; + + n = restart_point; + i = 0; + while (i++ < n) { + if ((c=getc(fout)) == EOF) { + perror_reply(550, name); + goto done; + } + if (c == '\n') + i++; + } + /* + * We must do this seek to "current" position + * because we are changing from reading to + * writing. + */ + if (fseek(fout, 0L, SEEK_CUR) < 0) { + perror_reply(550, name); + goto done; + } + } else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) { + perror_reply(550, name); + goto done; + } + } + din = dataconn(name, (off_t)-1, "r"); + if (din == NULL) + goto done; + set_buffer_size(fileno(din), 1); + if (receive_data(din, fout) == 0) { + if (unique) + reply(226, "Transfer complete (unique file name:%s).", + name); + else + reply(226, "Transfer complete."); + } + fclose(din); + data = -1; + pdata = -1; +done: + LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count); + (*closefunc)(fout); +} + +static FILE * +getdatasock(char *mode) +{ + int on = 1, s, t, tries; + + if (data >= 0) + return (fdopen(data, mode)); + seteuid((uid_t)0); + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + goto bad; +#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (void *) &on, sizeof(on)) < 0) + goto bad; +#endif + /* anchor socket to avoid multi-homing problems */ + data_source.sin_family = AF_INET; + data_source.sin_addr = ctrl_addr.sin_addr; + for (tries = 1; ; tries++) { + if (bind(s, (struct sockaddr *)&data_source, + sizeof(data_source)) >= 0) + break; + if (errno != EADDRINUSE || tries > 10) + goto bad; + sleep(tries); + } + seteuid((uid_t)pw->pw_uid); +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + on = IPTOS_THROUGHPUT; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); +#endif + return (fdopen(s, mode)); +bad: + /* Return the real value of errno (close may change it) */ + t = errno; + seteuid((uid_t)pw->pw_uid); + close(s); + errno = t; + return (NULL); +} + +static FILE * +dataconn(char *name, off_t size, char *mode) +{ + char sizebuf[32]; + FILE *file; + int retry = 0, tos; + + file_size = size; + byte_count = 0; + if (size != (off_t) -1) + snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", size); + else + strcpy(sizebuf, ""); + if (pdata >= 0) { + struct sockaddr_in from; + int s, fromlen = sizeof(from); + + s = accept(pdata, (struct sockaddr *)&from, &fromlen); + if (s < 0) { + reply(425, "Can't open data connection."); + close(pdata); + pdata = -1; + return (NULL); + } + close(pdata); + pdata = s; +#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) + tos = IPTOS_THROUGHPUT; + setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos, + sizeof(int)); +#endif + reply(150, "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + return (fdopen(pdata, mode)); + } + if (data >= 0) { + reply(125, "Using existing data connection for '%s'%s.", + name, sizebuf); + usedefault = 1; + return (fdopen(data, mode)); + } + if (usedefault) + data_dest = his_addr; + usedefault = 1; + file = getdatasock(mode); + if (file == NULL) { + reply(425, "Can't create data socket (%s,%d): %s.", + inet_ntoa(data_source.sin_addr), + ntohs(data_source.sin_port), strerror(errno)); + return (NULL); + } + data = fileno(file); + while (connect(data, (struct sockaddr *)&data_dest, + sizeof(data_dest)) < 0) { + if (errno == EADDRINUSE && retry < swaitmax) { + sleep((unsigned) swaitint); + retry += swaitint; + continue; + } + perror_reply(425, "Can't build data connection"); + fclose(file); + data = -1; + return (NULL); + } + reply(150, "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + return (file); +} + +/* + * Tranfer the contents of "instr" to "outstr" peer using the appropriate + * encapsulation of the data subject * to Mode, Structure, and Type. + * + * NB: Form isn't handled. + */ +static void +send_data(FILE *instr, FILE *outstr) +{ + int c, cnt, filefd, netfd; + static char *buf; + static size_t bufsize; + int i = 0; + char s[1024]; + + transflag++; + if (setjmp(urgcatch)) { + transflag = 0; + return; + } + switch (type) { + + case TYPE_A: + while ((c = getc(instr)) != EOF) { + byte_count++; + if(i > 1022){ + auth_write(fileno(outstr), s, i); + i = 0; + } + if(c == '\n') + s[i++] = '\r'; + s[i++] = c; + } + if(i) + auth_write(fileno(outstr), s, i); + auth_write(fileno(outstr), s, 0); + fflush(outstr); + transflag = 0; + if (ferror(instr)) + goto file_err; + if (ferror(outstr)) + goto data_err; + reply(226, "Transfer complete."); + return; + + case TYPE_I: + case TYPE_L: +#ifdef HAVE_MMAP +#ifndef MAP_FAILED +#define MAP_FAILED (-1) +#endif + { + struct stat st; + char *chunk; + int in = fileno(instr); + if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)) { + chunk = mmap(0, st.st_size, PROT_READ, MAP_SHARED, in, 0); + if(chunk != (void *)MAP_FAILED) { + cnt = st.st_size - restart_point; + auth_write(fileno(outstr), + chunk + restart_point, + cnt); + munmap(chunk, st.st_size); + auth_write(fileno(outstr), NULL, 0); + byte_count = cnt; + transflag = 0; + } + } + } + +#endif + if(transflag){ + struct stat st; + + netfd = fileno(outstr); + filefd = fileno(instr); + buf = alloc_buffer (buf, &bufsize, + fstat(filefd, &st) >= 0 ? &st : NULL); + if (buf == NULL) { + transflag = 0; + perror_reply(451, "Local resource failure: malloc"); + return; + } + while ((cnt = read(filefd, buf, bufsize)) > 0 && + auth_write(netfd, buf, cnt) == cnt) + byte_count += cnt; + auth_write(netfd, buf, 0); /* to end an encrypted stream */ + transflag = 0; + if (cnt != 0) { + if (cnt < 0) + goto file_err; + goto data_err; + } + } + reply(226, "Transfer complete."); + return; + default: + transflag = 0; + reply(550, "Unimplemented TYPE %d in send_data", type); + return; + } + +data_err: + transflag = 0; + perror_reply(426, "Data connection"); + return; + +file_err: + transflag = 0; + perror_reply(551, "Error on input file"); +} + +/* + * Transfer data from peer to "outstr" using the appropriate encapulation of + * the data subject to Mode, Structure, and Type. + * + * N.B.: Form isn't handled. + */ +static int +receive_data(FILE *instr, FILE *outstr) +{ + int cnt, bare_lfs = 0; + static char *buf; + static size_t bufsize; + struct stat st; + + transflag++; + if (setjmp(urgcatch)) { + transflag = 0; + return (-1); + } + + buf = alloc_buffer (buf, &bufsize, + fstat(fileno(outstr), &st) >= 0 ? &st : NULL); + if (buf == NULL) { + transflag = 0; + perror_reply(451, "Local resource failure: malloc"); + return -1; + } + + switch (type) { + + case TYPE_I: + case TYPE_L: + while ((cnt = auth_read(fileno(instr), buf, bufsize)) > 0) { + if (write(fileno(outstr), buf, cnt) != cnt) + goto file_err; + byte_count += cnt; + } + if (cnt < 0) + goto data_err; + transflag = 0; + return (0); + + case TYPE_E: + reply(553, "TYPE E not implemented."); + transflag = 0; + return (-1); + + case TYPE_A: + { + char *p, *q; + int cr_flag = 0; + while ((cnt = auth_read(fileno(instr), + buf + cr_flag, + bufsize - cr_flag)) > 0){ + byte_count += cnt; + cnt += cr_flag; + cr_flag = 0; + for(p = buf, q = buf; p < buf + cnt;) { + if(*p == '\n') + bare_lfs++; + if(*p == '\r') + if(p == buf + cnt - 1){ + cr_flag = 1; + p++; + continue; + }else if(p[1] == '\n'){ + *q++ = '\n'; + p += 2; + continue; + } + *q++ = *p++; + } + fwrite(buf, q - buf, 1, outstr); + if(cr_flag) + buf[0] = '\r'; + } + if(cr_flag) + putc('\r', outstr); + fflush(outstr); + if (ferror(instr)) + goto data_err; + if (ferror(outstr)) + goto file_err; + transflag = 0; + if (bare_lfs) { + lreply(226, "WARNING! %d bare linefeeds received in ASCII mode\r\n" + " File may not have transferred correctly.\r\n", + bare_lfs); + } + return (0); + } + default: + reply(550, "Unimplemented TYPE %d in receive_data", type); + transflag = 0; + return (-1); + } + +data_err: + transflag = 0; + perror_reply(426, "Data Connection"); + return (-1); + +file_err: + transflag = 0; + perror_reply(452, "Error writing file"); + return (-1); +} + +void +statfilecmd(char *filename) +{ + FILE *fin; + int c; + char line[LINE_MAX]; + + snprintf(line, sizeof(line), "/bin/ls -la %s", filename); + fin = ftpd_popen(line, "r", 1, 0); + lreply(211, "status of %s:", filename); + while ((c = getc(fin)) != EOF) { + if (c == '\n') { + if (ferror(stdout)){ + perror_reply(421, "control connection"); + ftpd_pclose(fin); + dologout(1); + /* NOTREACHED */ + } + if (ferror(fin)) { + perror_reply(551, filename); + ftpd_pclose(fin); + return; + } + putc('\r', stdout); + } + putc(c, stdout); + } + ftpd_pclose(fin); + reply(211, "End of Status"); +} + +void +statcmd(void) +{ +#if 0 + struct sockaddr_in *sin; + u_char *a, *p; + + lreply(211, "%s FTP server status:", hostname, version); + printf(" %s\r\n", version); + printf(" Connected to %s", remotehost); + if (!isdigit(remotehost[0])) + printf(" (%s)", inet_ntoa(his_addr.sin_addr)); + printf("\r\n"); + if (logged_in) { + if (guest) + printf(" Logged in anonymously\r\n"); + else + printf(" Logged in as %s\r\n", pw->pw_name); + } else if (askpasswd) + printf(" Waiting for password\r\n"); + else + printf(" Waiting for user name\r\n"); + printf(" TYPE: %s", typenames[type]); + if (type == TYPE_A || type == TYPE_E) + printf(", FORM: %s", formnames[form]); + if (type == TYPE_L) +#if NBBY == 8 + printf(" %d", NBBY); +#else + printf(" %d", bytesize); /* need definition! */ +#endif + printf("; STRUcture: %s; transfer MODE: %s\r\n", + strunames[stru], modenames[mode]); + if (data != -1) + printf(" Data connection open\r\n"); + else if (pdata != -1) { + printf(" in Passive mode"); + sin = &pasv_addr; + goto printaddr; + } else if (usedefault == 0) { + printf(" PORT"); + sin = &data_dest; +printaddr: + a = (u_char *) &sin->sin_addr; + p = (u_char *) &sin->sin_port; +#define UC(b) (((int) b) & 0xff) + printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), + UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); +#undef UC + } else + printf(" No data connection\r\n"); +#endif + reply(211, "End of status"); +} + +void +fatal(char *s) +{ + + reply(451, "Error in server: %s\n", s); + reply(221, "Closing connection due to server error."); + dologout(0); + /* NOTREACHED */ +} + +static void +int_reply(int, char *, const char *, va_list) +#ifdef __GNUC__ +__attribute__ ((format (printf, 3, 0))) +#endif +; + +static void +int_reply(int n, char *c, const char *fmt, va_list ap) +{ + char buf[10240]; + char *p; + p=buf; + if(n){ + snprintf(p, sizeof(buf), "%d%s", n, c); + p+=strlen(p); + } + vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap); + p+=strlen(p); + snprintf(p, sizeof(buf) - strlen(p), "\r\n"); + p+=strlen(p); + auth_printf("%s", buf); + fflush(stdout); + if (debug) + syslog(LOG_DEBUG, "<--- %s- ", buf); +} + +void +reply(int n, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int_reply(n, " ", fmt, ap); + delete_ftp_command(); + va_end(ap); +} + +void +lreply(int n, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int_reply(n, "-", fmt, ap); + va_end(ap); +} + +void +nreply(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int_reply(0, NULL, fmt, ap); + va_end(ap); +} + +static void +ack(char *s) +{ + + reply(250, "%s command successful.", s); +} + +void +nack(char *s) +{ + + reply(502, "%s command not implemented.", s); +} + +/* ARGSUSED */ +void +yyerror(char *s) +{ + char *cp; + + if ((cp = strchr(cbuf,'\n'))) + *cp = '\0'; + reply(500, "'%s': command not understood.", cbuf); +} + +void +do_delete(char *name) +{ + struct stat st; + + LOGCMD("delete", name); + if (stat(name, &st) < 0) { + perror_reply(550, name); + return; + } + if ((st.st_mode&S_IFMT) == S_IFDIR) { + if (rmdir(name) < 0) { + perror_reply(550, name); + return; + } + goto done; + } + if (unlink(name) < 0) { + perror_reply(550, name); + return; + } +done: + ack("DELE"); +} + +void +cwd(char *path) +{ + + if (chdir(path) < 0) + perror_reply(550, path); + else + ack("CWD"); +} + +void +makedir(char *name) +{ + + LOGCMD("mkdir", name); + if(guest && filename_check(name)) + return; + if (mkdir(name, 0777) < 0) + perror_reply(550, name); + else{ + if(guest) + chmod(name, 0700); /* guest has umask 777 */ + reply(257, "MKD command successful."); + } +} + +void +removedir(char *name) +{ + + LOGCMD("rmdir", name); + if (rmdir(name) < 0) + perror_reply(550, name); + else + ack("RMD"); +} + +void +pwd(void) +{ + char path[MaxPathLen + 1]; + char *ret; + + /* SunOS has a broken getcwd that does popen(pwd) (!!!), this + * failes miserably when running chroot + */ + ret = getcwd(path, sizeof(path)); + if (ret == NULL) + reply(550, "%s.", strerror(errno)); + else + reply(257, "\"%s\" is current directory.", path); +} + +char * +renamefrom(char *name) +{ + struct stat st; + + if (stat(name, &st) < 0) { + perror_reply(550, name); + return NULL; + } + reply(350, "File exists, ready for destination name"); + return (name); +} + +void +renamecmd(char *from, char *to) +{ + + LOGCMD2("rename", from, to); + if(guest && filename_check(to)) + return; + if (rename(from, to) < 0) + perror_reply(550, "rename"); + else + ack("RNTO"); +} + +static void +dolog(struct sockaddr_in *sin) +{ + inaddr2str (sin->sin_addr, remotehost, sizeof(remotehost)); +#ifdef HAVE_SETPROCTITLE + snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost); + setproctitle(proctitle); +#endif /* HAVE_SETPROCTITLE */ + + if (logging) + syslog(LOG_INFO, "connection from %s(%s)", + remotehost, + inet_ntoa(his_addr.sin_addr)); +} + +/* + * Record logout in wtmp file + * and exit with supplied status. + */ +void +dologout(int status) +{ + transflag = 0; + if (logged_in) { + seteuid((uid_t)0); + logwtmp(ttyline, "", ""); + dest_tkt(); + if(k_hasafs()) + k_unlog(); + } + /* beware of flushing buffers after a SIGPIPE */ +#ifdef XXX + exit(status); +#else + _exit(status); +#endif +} + +void abor(void) +{ +} + +static void +myoob(int signo) +{ +#if 0 + char *cp; +#endif + + /* only process if transfer occurring */ + if (!transflag) + return; + + /* This is all XXX */ + oobflag = 1; + /* if the command resulted in a new command, + parse that as well */ + do{ + yyparse(); + } while(ftp_command); + oobflag = 0; + +#if 0 + cp = tmpline; + if (getline(cp, 7) == NULL) { + reply(221, "You could at least say goodbye."); + dologout(0); + } + upper(cp); + if (strcmp(cp, "ABOR\r\n") == 0) { + tmpline[0] = '\0'; + reply(426, "Transfer aborted. Data connection closed."); + reply(226, "Abort successful"); + longjmp(urgcatch, 1); + } + if (strcmp(cp, "STAT\r\n") == 0) { + if (file_size != (off_t) -1) + reply(213, "Status: %ld of %ld bytes transferred", + (long)byte_count, + (long)file_size); + else + reply(213, "Status: %ld bytes transferred" + (long)byte_count); + } +#endif +} + +/* + * Note: a response of 425 is not mentioned as a possible response to + * the PASV command in RFC959. However, it has been blessed as + * a legitimate response by Jon Postel in a telephone conversation + * with Rick Adams on 25 Jan 89. + */ +void +passive(void) +{ + int len; + char *p, *a; + + pdata = socket(AF_INET, SOCK_STREAM, 0); + if (pdata < 0) { + perror_reply(425, "Can't open passive connection"); + return; + } + pasv_addr = ctrl_addr; + pasv_addr.sin_port = 0; + seteuid((uid_t)0); + if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) { + seteuid((uid_t)pw->pw_uid); + goto pasv_error; + } + seteuid((uid_t)pw->pw_uid); + len = sizeof(pasv_addr); + if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) + goto pasv_error; + if (listen(pdata, 1) < 0) + goto pasv_error; + a = (char *) &pasv_addr.sin_addr; + p = (char *) &pasv_addr.sin_port; + +#define UC(b) (((int) b) & 0xff) + + reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), + UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); + return; + +pasv_error: + close(pdata); + pdata = -1; + perror_reply(425, "Can't open passive connection"); + return; +} + +/* + * Generate unique name for file with basename "local". + * The file named "local" is already known to exist. + * Generates failure reply on error. + */ +static char * +gunique(char *local) +{ + static char new[MaxPathLen]; + struct stat st; + int count; + char *cp; + + cp = strrchr(local, '/'); + if (cp) + *cp = '\0'; + if (stat(cp ? local : ".", &st) < 0) { + perror_reply(553, cp ? local : "."); + return NULL; + } + if (cp) + *cp = '/'; + for (count = 1; count < 100; count++) { + snprintf (new, sizeof(new), "%s.%d", local, count); + if (stat(new, &st) < 0) + return (new); + } + reply(452, "Unique file name cannot be created."); + return (NULL); +} + +/* + * Format and send reply containing system error number. + */ +void +perror_reply(int code, char *string) +{ + reply(code, "%s: %s.", string, strerror(errno)); +} + +static char *onefile[] = { + "", + 0 +}; + +void +send_file_list(char *whichf) +{ + struct stat st; + DIR *dirp = NULL; + struct dirent *dir; + FILE *dout = NULL; + char **dirlist, *dirname; + int simple = 0; + int freeglob = 0; + glob_t gl; + char buf[MaxPathLen]; + + if (strpbrk(whichf, "~{[*?") != NULL) { + int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + freeglob = 1; + if (glob(whichf, flags, 0, &gl)) { + reply(550, "not found"); + goto out; + } else if (gl.gl_pathc == 0) { + errno = ENOENT; + perror_reply(550, whichf); + goto out; + } + dirlist = gl.gl_pathv; + } else { + onefile[0] = whichf; + dirlist = onefile; + simple = 1; + } + + if (setjmp(urgcatch)) { + transflag = 0; + goto out; + } + while ((dirname = *dirlist++)) { + if (stat(dirname, &st) < 0) { + /* + * If user typed "ls -l", etc, and the client + * used NLST, do what the user meant. + */ + if (dirname[0] == '-' && *dirlist == NULL && + transflag == 0) { + retrieve("/bin/ls %s", dirname); + goto out; + } + perror_reply(550, whichf); + if (dout != NULL) { + fclose(dout); + transflag = 0; + data = -1; + pdata = -1; + } + goto out; + } + + if (S_ISREG(st.st_mode)) { + if (dout == NULL) { + dout = dataconn("file list", (off_t)-1, "w"); + if (dout == NULL) + goto out; + transflag++; + } + snprintf(buf, sizeof(buf), "%s%s\n", dirname, + type == TYPE_A ? "\r" : ""); + auth_write(fileno(dout), buf, strlen(buf)); + byte_count += strlen(dirname) + 1; + continue; + } else if (!S_ISDIR(st.st_mode)) + continue; + + if ((dirp = opendir(dirname)) == NULL) + continue; + + while ((dir = readdir(dirp)) != NULL) { + char nbuf[MaxPathLen]; + + if (!strcmp(dir->d_name, ".")) + continue; + if (!strcmp(dir->d_name, "..")) + continue; + + snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname, dir->d_name); + + /* + * We have to do a stat to insure it's + * not a directory or special file. + */ + if (simple || (stat(nbuf, &st) == 0 && + S_ISREG(st.st_mode))) { + if (dout == NULL) { + dout = dataconn("file list", (off_t)-1, "w"); + if (dout == NULL) + goto out; + transflag++; + } + if(strncmp(nbuf, "./", 2) == 0) + snprintf(buf, sizeof(buf), "%s%s\n", nbuf +2, + type == TYPE_A ? "\r" : ""); + else + snprintf(buf, sizeof(buf), "%s%s\n", nbuf, + type == TYPE_A ? "\r" : ""); + auth_write(fileno(dout), buf, strlen(buf)); + byte_count += strlen(nbuf) + 1; + } + } + closedir(dirp); + } + if (dout == NULL) + reply(550, "No files found."); + else if (ferror(dout) != 0) + perror_reply(550, "Data connection"); + else + reply(226, "Transfer complete."); + + transflag = 0; + if (dout != NULL){ + auth_write(fileno(dout), buf, 0); /* XXX flush */ + + fclose(dout); + } + data = -1; + pdata = -1; +out: + if (freeglob) { + freeglob = 0; + globfree(&gl); + } +} + + +int +find(char *pattern) +{ + char line[1024]; + FILE *f; + + snprintf(line, sizeof(line), + "/bin/locate -d %s %s", + ftp_rooted("/etc/locatedb"), + pattern); + f = ftpd_popen(line, "r", 1, 1); + if(f == NULL){ + perror_reply(550, "/bin/locate"); + return 1; + } + lreply(200, "Output from find."); + while(fgets(line, sizeof(line), f)){ + if(line[strlen(line)-1] == '\n') + line[strlen(line)-1] = 0; + nreply("%s", line); + } + reply(200, "Done"); + ftpd_pclose(f); + return 0; +} + diff --git a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c new file mode 100644 index 0000000..02d23d6 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +RCSID("$Id: kauth.c,v 1.14 1997/05/07 02:21:30 assar Exp $"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <time.h> +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#include <roken.h> + +#include <des.h> +#include <krb.h> +#include <kafs.h> + +#include "extern.h" +#include "krb4.h" +#include "auth.h" +#include "base64.h" + +static KTEXT_ST cip; +static unsigned int lifetime; +static time_t local_time; + +static krb_principal pr; + +static int +save_tkt(char *user, char *instance, char *realm, void *arg, + int (*key_proc)(char*, char*, char*, void*, des_cblock*), KTEXT *cipp) +{ + local_time = time(0); + memmove(&cip, *cipp, sizeof(cip)); + return -1; +} + +static int +store_ticket(KTEXT cip) +{ + char *ptr; + des_cblock session; + krb_principal sp; + unsigned char kvno; + KTEXT_ST tkt; + int left = cip->length; + + int kerror; + + time_t kdc_time; + + ptr = (char *) cip->dat; + + /* extract session key */ + memmove(session, ptr, 8); + ptr += 8; + left -= 8; + + if (strnlen(ptr, left) == left) + return(INTK_BADPW); + + /* extract server's name */ + strcpy(sp.name, ptr); + ptr += strlen(sp.name) + 1; + left -= strlen(sp.name) + 1; + + if (strnlen(ptr, left) == left) + return(INTK_BADPW); + + /* extract server's instance */ + strcpy(sp.instance, ptr); + ptr += strlen(sp.instance) + 1; + left -= strlen(sp.instance) + 1; + + if (strnlen(ptr, left) == left) + return(INTK_BADPW); + + /* extract server's realm */ + strcpy(sp.realm,ptr); + ptr += strlen(sp.realm) + 1; + left -= strlen(sp.realm) + 1; + + if(left < 3) + return INTK_BADPW; + /* extract ticket lifetime, server key version, ticket length */ + /* be sure to avoid sign extension on lifetime! */ + lifetime = (unsigned char) ptr[0]; + kvno = (unsigned char) ptr[1]; + tkt.length = (unsigned char) ptr[2]; + ptr += 3; + left -= 3; + + if (tkt.length > left) + return(INTK_BADPW); + + /* extract ticket itself */ + memmove(tkt.dat, ptr, tkt.length); + ptr += tkt.length; + left -= tkt.length; + + /* Here is where the time should be verified against the KDC. + * Unfortunately everything is sent in host byte order (receiver + * makes wrong) , and at this stage there is no way for us to know + * which byteorder the KDC has. So we simply ignore the time, + * there are no security risks with this, the only thing that can + * happen is that we might receive a replayed ticket, which could + * at most be useless. + */ + +#if 0 + /* check KDC time stamp */ + memmove(&kdc_time, ptr, sizeof(kdc_time)); + if (swap_bytes) swap_u_long(kdc_time); + + ptr += 4; + + if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) { + return(RD_AP_TIME); /* XXX should probably be better + code */ + } +#endif + + /* initialize ticket cache */ + + if (tf_create(TKT_FILE) != KSUCCESS) + return(INTK_ERR); + + if (tf_put_pname(pr.name) != KSUCCESS || + tf_put_pinst(pr.instance) != KSUCCESS) { + tf_close(); + return(INTK_ERR); + } + + + kerror = tf_save_cred(sp.name, sp.instance, sp.realm, session, + lifetime, kvno, &tkt, local_time); + tf_close(); + + return(kerror); +} + +void kauth(char *principal, char *ticket) +{ + char *p; + int ret; + + ret = krb_parse_name(principal, &pr); + if(ret){ + reply(500, "Bad principal: %s.", krb_get_err_text(ret)); + return; + } + if(pr.realm[0] == 0) + krb_get_lrealm(pr.realm, 1); + + if(ticket){ + cip.length = base64_decode(ticket, &cip.dat); + if(cip.length == -1){ + reply(500, "Failed to decode data."); + return; + } + ret = store_ticket(&cip); + if(ret){ + reply(500, "Kerberos error: %s.", krb_get_err_text(ret)); + memset(&cip, 0, sizeof(cip)); + return; + } + if(k_hasafs()) + k_afsklog(0, 0); + reply(200, "Tickets will be destroyed on exit."); + return; + } + + ret = krb_get_in_tkt (pr.name, + pr.instance, + pr.realm, + KRB_TICKET_GRANTING_TICKET, + pr.realm, + DEFAULT_TKT_LIFE, + NULL, save_tkt, NULL); + if(ret != INTK_BADPW){ + reply(500, "Kerberos error: %s.", krb_get_err_text(ret)); + return; + } + base64_encode(cip.dat, cip.length, &p); + reply(300, "P=%s T=%s", krb_unparse_name(&pr), p); + free(p); + memset(&cip, 0, sizeof(cip)); +} + + +static char * +short_date(int32_t dp) +{ + char *cp; + time_t t = (time_t)dp; + + if (t == (time_t)(-1L)) return "*** Never *** "; + cp = ctime(&t) + 4; + cp[15] = '\0'; + return (cp); +} + +void klist(void) +{ + int err; + + char *file = tkt_string(); + + krb_principal pr; + + char buf1[128], buf2[128]; + int header = 1; + CREDENTIALS c; + + + + err = tf_init(file, R_TKT_FIL); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + tf_close(); + + /* + * We must find the realm of the ticket file here before calling + * tf_init because since the realm of the ticket file is not + * really stored in the principal section of the file, the + * routine we use must itself call tf_init and tf_close. + */ + err = krb_get_tf_realm(file, pr.realm); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + + err = tf_init(file, R_TKT_FIL); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + + err = tf_get_pname(pr.name); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + err = tf_get_pinst(pr.instance); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + + /* + * You may think that this is the obvious place to get the + * realm of the ticket file, but it can't be done here as the + * routine to do this must open the ticket file. This is why + * it was done before tf_init. + */ + + lreply(200, "Principal: %s", krb_unparse_name(&pr)); + while ((err = tf_get_cred(&c)) == KSUCCESS) { + if (header) { + lreply(200, "%-15s %-15s %s", + " Issued", " Expires", " Principal (kvno)"); + header = 0; + } + strcpy(buf1, short_date(c.issue_date)); + c.issue_date = krb_life_to_time(c.issue_date, c.lifetime); + if (time(0) < (unsigned long) c.issue_date) + strcpy(buf2, short_date(c.issue_date)); + else + strcpy(buf2, ">>> Expired <<< "); + lreply(200, "%s %s %s (%d)", buf1, buf2, + krb_unparse_name_long(c.service, c.instance, c.realm), c.kvno); + } + if (header && err == EOF) { + lreply(200, "No tickets in file."); + } + reply(200, ""); +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/krb4.c b/crypto/kerberosIV/appl/ftp/ftpd/krb4.c new file mode 100644 index 0000000..2457c61 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/krb4.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +RCSID("$Id: krb4.c,v 1.19 1997/05/11 09:00:07 assar Exp $"); +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_NETINET_IN_h +#include <netinet/in.h> +#endif + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <krb.h> + +#include "base64.h" +#include "extern.h" +#include "auth.h" +#include "krb4.h" + +#include <roken.h> + +static AUTH_DAT auth_dat; +static des_key_schedule schedule; + +int krb4_auth(char *auth) +{ + auth_complete = 0; + reply(334, "Using authentication type %s; ADAT must follow", auth); + return 0; +} + +int krb4_adat(char *auth) +{ + KTEXT_ST tkt; + char *p; + int kerror; + u_int32_t cs; + char msg[35]; /* size of encrypted block */ + int len; + + char inst[INST_SZ]; + + memset(&tkt, 0, sizeof(tkt)); + len = base64_decode(auth, tkt.dat); + + if(len < 0){ + reply(501, "Failed to decode base64 data."); + return -1; + } + tkt.length = len; + + k_getsockinst(0, inst, sizeof(inst)); + kerror = krb_rd_req(&tkt, "ftp", inst, 0, &auth_dat, ""); + if(kerror == RD_AP_UNDEC){ + k_getsockinst(0, inst, sizeof(inst)); + kerror = krb_rd_req(&tkt, "rcmd", inst, 0, &auth_dat, ""); + } + + if(kerror){ + reply(535, "Error reading request: %s.", krb_get_err_text(kerror)); + return -1; + } + + des_set_key(&auth_dat.session, schedule); + + cs = auth_dat.checksum + 1; + { + unsigned char tmp[4]; + tmp[0] = (cs >> 24) & 0xff; + tmp[1] = (cs >> 16) & 0xff; + tmp[2] = (cs >> 8) & 0xff; + tmp[3] = cs & 0xff; + len = krb_mk_safe(tmp, msg, 4, &auth_dat.session, + &ctrl_addr, &his_addr); + } + if(len < 0){ + reply(535, "Error creating reply: %s.", strerror(errno)); + return -1; + } + base64_encode(msg, len, &p); + reply(235, "ADAT=%s", p); + auth_complete = 1; + free(p); + return 0; +} + +int krb4_pbsz(int size) +{ + if(size > 1048576) /* XXX arbitrary number */ + size = 1048576; + buffer_size = size; + reply(200, "OK PBSZ=%d", buffer_size); + return 0; +} + +int krb4_prot(int level) +{ + if(level == prot_confidential) + return -1; + return 0; +} + +int krb4_ccc(void) +{ + reply(534, "Don't event think about it."); + return -1; +} + +int krb4_mic(char *msg) +{ + int len; + int kerror; + MSG_DAT m_data; + char *tmp, *cmd; + + cmd = strdup(msg); + + len = base64_decode(msg, cmd); + if(len < 0){ + reply(501, "Failed to decode base 64 data."); + free(cmd); + return -1; + } + kerror = krb_rd_safe(cmd, len, &auth_dat.session, + &his_addr, &ctrl_addr, &m_data); + + if(kerror){ + reply(535, "Error reading request: %s.", krb_get_err_text(kerror)); + free(cmd); + return -1; + } + + tmp = malloc(strlen(msg) + 1); + snprintf(tmp, strlen(msg) + 1, "%.*s", (int)m_data.app_length, m_data.app_data); + if(!strstr(tmp, "\r\n")) + strcat(tmp, "\r\n"); + new_ftp_command(tmp); + free(cmd); + return 0; +} + +int krb4_conf(char *msg) +{ + prot_level = prot_safe; + + reply(537, "Protection level not supported."); + return -1; +} + +int krb4_enc(char *msg) +{ + int len; + int kerror; + MSG_DAT m_data; + char *tmp, *cmd; + + cmd = strdup(msg); + + len = base64_decode(msg, cmd); + if(len < 0){ + reply(501, "Failed to decode base 64 data."); + free(cmd); + return -1; + } + kerror = krb_rd_priv(cmd, len, schedule, &auth_dat.session, + &his_addr, &ctrl_addr, &m_data); + + if(kerror){ + reply(535, "Error reading request: %s.", krb_get_err_text(kerror)); + free(cmd); + return -1; + } + + tmp = strdup(msg); + snprintf(tmp, strlen(msg) + 1, "%.*s", (int)m_data.app_length, m_data.app_data); + if(!strstr(tmp, "\r\n")) + strcat(tmp, "\r\n"); + new_ftp_command(tmp); + free(cmd); + return 0; +} + +int krb4_read(int fd, void *data, int length) +{ + static int left; + static char *extra; + static int eof; + int len, bytes, tx = 0; + + MSG_DAT m_data; + int kerror; + + if(eof){ /* if we haven't reported an end-of-file, do so */ + eof = 0; + return 0; + } + + if(left){ + if(length > left) + bytes = left; + else + bytes = length; + memmove(data, extra, bytes); + left -= bytes; + if(left) + memmove(extra, extra + bytes, left); + else + free(extra); + length -= bytes; + tx += bytes; + } + + while(length){ + unsigned char tmp[4]; + if(krb_net_read(fd, tmp, 4) < 4){ + reply(400, "Unexpected end of file.\n"); + return -1; + } + len = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3]; + krb_net_read(fd, data_buffer, len); + if(data_protection == prot_safe) + kerror = krb_rd_safe(data_buffer, len, &auth_dat.session, + &his_addr, &ctrl_addr, &m_data); + else + kerror = krb_rd_priv(data_buffer, len, schedule, &auth_dat.session, + &his_addr, &ctrl_addr, &m_data); + + if(kerror){ + reply(400, "Failed to read data: %s.", krb_get_err_text(kerror)); + return -1; + } + + bytes = m_data.app_length; + if(bytes == 0){ + if(tx) eof = 1; + return tx; + } + if(bytes > length){ + left = bytes - length; + bytes = length; + extra = malloc(left); + memmove(extra, m_data.app_data + bytes, left); + } + memmove((unsigned char*)data + tx, m_data.app_data, bytes); + tx += bytes; + length -= bytes; + } + return tx; +} + +int krb4_write(int fd, void *data, int length) +{ + int len, bytes, tx = 0; + + len = buffer_size; + if(data_protection == prot_safe) + len -= 31; /* always 31 bytes overhead */ + else + len -= 26; /* at most 26 bytes */ + + do{ + if(length < len) + len = length; + if(data_protection == prot_safe) + bytes = krb_mk_safe(data, data_buffer+4, len, &auth_dat.session, + &ctrl_addr, &his_addr); + else + bytes = krb_mk_priv(data, data_buffer+4, len, schedule, + &auth_dat.session, + &ctrl_addr, &his_addr); + if(bytes == -1){ + reply(535, "Failed to make packet: %s.", strerror(errno)); + return -1; + } + data_buffer[0] = (bytes >> 24) & 0xff; + data_buffer[1] = (bytes >> 16) & 0xff; + data_buffer[2] = (bytes >> 8) & 0xff; + data_buffer[3] = bytes & 0xff; + if(krb_net_write(fd, data_buffer, bytes+4) < 0) + return -1; + length -= len; + data = (unsigned char*)data + len; + tx += len; + }while(length); + return tx; +} + +int krb4_userok(char *name) +{ + if(!kuserok(&auth_dat, name)){ + do_login(232, name); + }else{ + reply(530, "User %s access denied.", name); + } + return 0; +} + + +int +krb4_vprintf(const char *fmt, va_list ap) +{ + char buf[10240]; + char *p; + char *enc; + int code; + int len; + + vsnprintf (buf, sizeof(buf), fmt, ap); + enc = malloc(strlen(buf) + 31); + if(prot_level == prot_safe){ + len = krb_mk_safe((u_char*)buf, (u_char*)enc, strlen(buf), &auth_dat.session, + &ctrl_addr, &his_addr); + code = 631; + }else if(prot_level == prot_private){ + len = krb_mk_priv((u_char*)buf, (u_char*)enc, strlen(buf), schedule, + &auth_dat.session, &ctrl_addr, &his_addr); + code = 632; + }else{ + len = 0; /* XXX */ + code = 631; + } + base64_encode(enc, len, &p); + fprintf(stdout, "%d %s\r\n", code, p); + free(enc); + free(p); + return 0; +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/krb4.h b/crypto/kerberosIV/appl/ftp/ftpd/krb4.h new file mode 100644 index 0000000..f777dbd --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/krb4.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: krb4.h,v 1.6 1997/04/01 08:17:29 joda Exp $ */ + +#ifndef __KRB4_H__ +#define __KRB4_H__ + +#include <stdarg.h> + +int krb4_auth(char *auth); +int krb4_adat(char *auth); +int krb4_pbsz(int size); +int krb4_prot(int level); +int krb4_ccc(void); +int krb4_mic(char *msg); +int krb4_conf(char *msg); +int krb4_enc(char *msg); + +int krb4_read(int fd, void *data, int length); +int krb4_write(int fd, void *data, int length); + +int krb4_userok(char *name); +int krb4_vprintf(const char *fmt, va_list ap); + +#endif /* __KRB4_H__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c new file mode 100644 index 0000000..95ab216 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +RCSID("$Id: logwtmp.c,v 1.10 1997/05/25 15:17:56 assar Exp $"); +#endif + +#include <stdio.h> +#include <string.h> +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_UTMP_H +#include <utmp.h> +#endif +#ifdef HAVE_UTMPX_H +#include <utmpx.h> +#endif +#include "extern.h" + +#ifndef WTMP_FILE +#ifdef _PATH_WTMP +#define WTMP_FILE _PATH_WTMP +#else +#define WTMP_FILE "/var/adm/wtmp" +#endif +#endif + +void +logwtmp(char *line, char *name, char *host) +{ + static int init = 0; + static int fd, fdx; + struct timeval tv; + struct utmp ut; +#ifdef WTMPX_FILE + struct utmpx utx; +#endif + + memset(&ut, 0, sizeof(struct utmp)); +#ifdef HAVE_UT_TYPE + if(name[0]) + ut.ut_type = USER_PROCESS; + else + ut.ut_type = DEAD_PROCESS; +#endif + strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + strncpy(ut.ut_name, name, sizeof(ut.ut_name)); +#ifdef HAVE_UT_PID + ut.ut_pid = getpid(); +#endif +#ifdef HAVE_UT_HOST + strncpy(ut.ut_host, host, sizeof(ut.ut_host)); +#endif + ut.ut_time = time(NULL); + +#ifdef WTMPX_FILE + strncpy(utx.ut_line, line, sizeof(utx.ut_line)); + strncpy(utx.ut_user, name, sizeof(utx.ut_user)); + strncpy(utx.ut_host, host, sizeof(utx.ut_host)); +#ifdef HAVE_UT_SYSLEN + utx.ut_syslen = strlen(host) + 1; + if (utx.ut_syslen > sizeof(utx.ut_host)) + utx.ut_syslen = sizeof(utx.ut_host); +#endif + gettimeofday (&tv, 0); + utx.ut_tv.tv_sec = tv.tv_sec; + utx.ut_tv.tv_usec = tv.tv_usec; + + if(name[0]) + utx.ut_type = USER_PROCESS; + else + utx.ut_type = DEAD_PROCESS; +#endif + + if(!init){ + fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0); +#ifdef WTMPX_FILE + fdx = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0); +#endif + init = 1; + } + if(fd >= 0) { + write(fd, &ut, sizeof(struct utmp)); /* XXX */ +#ifdef WTMPX_FILE + write(fdx, &utx, sizeof(struct utmpx)); +#endif + } +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/pathnames.h b/crypto/kerberosIV/appl/ftp/ftpd/pathnames.h new file mode 100644 index 0000000..1bd2be1 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/pathnames.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + */ + +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif + +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif + +#ifndef _PATH_NOLOGIN +#define _PATH_NOLOGIN "/etc/nologin" +#endif + +#ifndef _PATH_BSHELL +#define _PATH_BSHELL "/bin/sh" +#endif + +#define _PATH_FTPUSERS "/etc/ftpusers" +#define _PATH_FTPCHROOT "/etc/ftpchroot" +#define _PATH_FTPWELCOME "/etc/ftpwelcome" +#define _PATH_FTPLOGINMESG "/etc/motd" diff --git a/crypto/kerberosIV/appl/ftp/ftpd/popen.c b/crypto/kerberosIV/appl/ftp/ftpd/popen.c new file mode 100644 index 0000000..58c4985 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/popen.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software written by Ken Arnold and + * published in UNIX Review, Vol. 6, No. 8. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +RCSID("$Id: popen.c,v 1.16 1997/06/01 03:14:06 assar Exp $"); +#endif + +#include <sys/types.h> +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <sys/wait.h> + +#include <errno.h> +#include <glob.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "extern.h" + +#include <roken.h> + +/* + * Special version of popen which avoids call to shell. This ensures + * no one may create a pipe to a hidden program as a side effect of a + * list or dir command. + */ +static int *pids; +static int fds; + +extern int dochroot; + +/* return path prepended with ~ftp if that file exists, otherwise + * return path unchanged + */ + +const char * +ftp_rooted(const char *path) +{ + static char home[MaxPathLen] = ""; + static char newpath[MaxPathLen]; + struct passwd *pwd; + + if(!home[0]) + if((pwd = k_getpwnam("ftp"))) + strcpy(home, pwd->pw_dir); + snprintf(newpath, sizeof(newpath), "%s/%s", home, path); + if(access(newpath, X_OK)) + strcpy(newpath, path); + return newpath; +} + + +FILE * +ftpd_popen(char *program, char *type, int do_stderr, int no_glob) +{ + char *cp; + FILE *iop; + int argc, gargc, pdes[2], pid; + char **pop, *argv[100], *gargv[1000]; + char *foo; + + if (strcmp(type, "r") && strcmp(type, "w")) + return (NULL); + + if (!pids) { + + /* This function is ugly and should be rewritten, in + * modern unices there is no such thing as a maximum + * filedescriptor. + */ + + fds = getdtablesize(); + pids = (int*)calloc(fds, sizeof(int)); + if(!pids) + return NULL; + } + if (pipe(pdes) < 0) + return (NULL); + + /* break up string into pieces */ + for (argc = 0, cp = program;; cp = NULL) { + foo = NULL; + if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo))) + break; + } + + gargv[0] = (char*)ftp_rooted(argv[0]); + /* glob each piece */ + for (gargc = argc = 1; argv[argc]; argc++) { + glob_t gl; + int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + if (no_glob || glob(argv[argc], flags, NULL, &gl)) + gargv[gargc++] = strdup(argv[argc]); + else + for (pop = gl.gl_pathv; *pop; pop++) + gargv[gargc++] = strdup(*pop); + globfree(&gl); + } + gargv[gargc] = NULL; + + iop = NULL; + switch(pid = fork()) { + case -1: /* error */ + close(pdes[0]); + close(pdes[1]); + goto pfree; + /* NOTREACHED */ + case 0: /* child */ + if (*type == 'r') { + if (pdes[1] != STDOUT_FILENO) { + dup2(pdes[1], STDOUT_FILENO); + close(pdes[1]); + } + if(do_stderr) + dup2(STDOUT_FILENO, STDERR_FILENO); + close(pdes[0]); + } else { + if (pdes[0] != STDIN_FILENO) { + dup2(pdes[0], STDIN_FILENO); + close(pdes[0]); + } + close(pdes[1]); + } + execv(gargv[0], gargv); + gargv[0] = argv[0]; + execv(gargv[0], gargv); + _exit(1); + } + /* parent; assume fdopen can't fail... */ + if (*type == 'r') { + iop = fdopen(pdes[0], type); + close(pdes[1]); + } else { + iop = fdopen(pdes[1], type); + close(pdes[0]); + } + pids[fileno(iop)] = pid; + +pfree: + for (argc = 1; gargv[argc] != NULL; argc++) + free(gargv[argc]); + + + return (iop); +} + +int +ftpd_pclose(FILE *iop) +{ + int fdes, status; + pid_t pid; + sigset_t sigset, osigset; + + /* + * pclose returns -1 if stream is not associated with a + * `popened' command, or, if already `pclosed'. + */ + if (pids == 0 || pids[fdes = fileno(iop)] == 0) + return (-1); + fclose(iop); + sigemptyset(&sigset); + sigaddset(&sigset, SIGINT); + sigaddset(&sigset, SIGQUIT); + sigaddset(&sigset, SIGHUP); + sigprocmask(SIG_BLOCK, &sigset, &osigset); + while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR) + continue; + sigprocmask(SIG_SETMASK, &osigset, NULL); + pids[fdes] = 0; + if (pid < 0) + return (pid); + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + return (1); +} diff --git a/crypto/kerberosIV/appl/kauth/Makefile.in b/crypto/kerberosIV/appl/kauth/Makefile.in new file mode 100644 index 0000000..97bfdb4 --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/Makefile.in @@ -0,0 +1,112 @@ +# $Id: Makefile.in,v 1.33 1997/04/05 21:24:35 assar Exp $ + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +topdir = ../.. + +CC = @CC@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ -DBINDIR='"$(bindir)"' +CFLAGS = @CFLAGS@ +LD_FLAGS = @LD_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LIBS = @LIBS@ +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +bindir = @bindir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +PROG_BIN = kauth$(EXECSUFFIX) ksrvtgt +PROG_LIBEXEC = kauthd$(EXECSUFFIX) +PROGS = $(PROG_BIN) $(PROG_LIBEXEC) + +SOURCES_KAUTH = kauth.c rkinit.c +SOURCES_KAUTHD = kauthd.c +SOURCES_COMMON = encdata.c marshall.c + +OBJECTS_KAUTH = kauth.o rkinit.o +OBJECTS_KAUTHD = kauthd.o +OBJECTS_COMMON = marshall.o encdata.o + +OBJECTS = $(OBJECTS_KAUTH) $(OBJECTS_KAUTHD) +SOURCES = $(SOURCES_KAUTH) $(SOURCES_KAUTHD) $(SOURCES_COMMON) + +KRB_KAFS_LIB = @KRB_KAFS_LIB@ + +all: $(PROGS) + +Wall: + make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $< + +install: all + $(MKINSTALLDIRS) $(bindir) $(libexecdir) + for x in $(PROG_BIN); do \ + $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x| sed '$(transform)'`; \ + done + if test -f $(bindir)/zrefresh -o -r $(bindir)/zrefresh; then \ + true; \ + else \ + $(INSTALL_PROGRAM) $(srcdir)/zrefresh $(bindir)/`echo zrefresh | sed '$(transform)'`; \ + fi + for x in $(PROG_LIBEXEC); do \ + $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROG_BIN); do \ + rm -f $(bindir)/`echo $$x| sed '$(transform)'`; \ + done + for x in $(PROG_LIBEXEC); do \ + rm -f $(libexecdir)/`echo $$x| sed '$(transform)'`; \ + done + +TAGS: $(SOURCES) + etags $(SOURCES) + +check: + +clean: + rm -f *.a *.o $(PROGS) + +mostlyclean: clean + +distclean: clean + rm -f Makefile *.tab.c *~ + +realclean: distclean + rm -f TAGS + +dist: $(DISTFILES) + for file in $(DISTFILES); do \ + ln $$file ../`cat ../.fname`/lib \ + || cp -p $$file ../`cat ../.fname`/lib; \ + done + +KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes +LIBROKEN=-L../../lib/roken -lroken + +kauth$(EXECSUFFIX): $(OBJECTS_KAUTH) $(OBJECTS_COMMON) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTH) $(OBJECTS_COMMON) $(KRB_KAFS_LIB) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +kauthd$(EXECSUFFIX): $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KAUTHD) $(OBJECTS_COMMON) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +ksrvtgt: ksrvtgt.in + sed -e "s!%bindir%!$(bindir)!" $(srcdir)/ksrvtgt.in > $@ + chmod +x $@ + + +$(OBJECTS): ../../include/config.h diff --git a/crypto/kerberosIV/appl/kauth/encdata.c b/crypto/kerberosIV/appl/kauth/encdata.c new file mode 100644 index 0000000..800326a --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/encdata.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "kauth.h" + +RCSID("$Id: encdata.c,v 1.9 1997/04/01 08:17:30 joda Exp $"); + +int +write_encrypted (int fd, void *buf, size_t len, des_key_schedule schedule, + des_cblock *session, struct sockaddr_in *me, + struct sockaddr_in *him) +{ + void *outbuf; + int32_t outlen, l; + int i; + unsigned char tmp[4]; + + outbuf = malloc(len + 30); + if (outbuf == NULL) + return -1; + outlen = krb_mk_priv (buf, outbuf, len, schedule, session, me, him); + if (outlen < 0) { + free(outbuf); + return -1; + } + l = outlen; + for(i = 3; i >= 0; i--, l = l >> 8) + tmp[i] = l & 0xff; + if (krb_net_write (fd, tmp, 4) != 4 || + krb_net_write (fd, outbuf, outlen) != outlen) { + free(outbuf); + return -1; + } + + free(outbuf); + return 0; +} + + +int +read_encrypted (int fd, void *buf, size_t len, void **ret, + des_key_schedule schedule, des_cblock *session, + struct sockaddr_in *him, struct sockaddr_in *me) +{ + int status; + int32_t l; + MSG_DAT msg; + unsigned char tmp[4]; + + l = krb_net_read (fd, tmp, 4); + if (l != 4) + return l; + l = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3]; + if (l > len) + return -1; + if (krb_net_read (fd, buf, l) != l) + return -1; + status = krb_rd_priv (buf, l, schedule, session, him, me, &msg); + if (status != RD_AP_OK) { + fprintf (stderr, "read_encrypted: %s\n", + krb_get_err_text(status)); + return -1; + } + *ret = msg.app_data; + return msg.app_length; +} diff --git a/crypto/kerberosIV/appl/kauth/kauth.c b/crypto/kerberosIV/appl/kauth/kauth.c new file mode 100644 index 0000000..84614b0 --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/kauth.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* + * Little program that reads an srvtab or password and + * creates a suitable ticketfile and associated AFS tokens. + * + * If an optional command is given the command is executed in a + * new PAG and when the command exits the tickets are destroyed. + */ + +#include "kauth.h" + +RCSID("$Id: kauth.c,v 1.75 1997/05/02 15:09:24 assar Exp $"); + +krb_principal princ; +static char srvtab[MaxPathLen + 1]; +static int lifetime = DEFAULT_TKT_LIFE; +static char remote_tktfile[MaxPathLen + 1]; +static char remoteuser[100]; +static char *cell = 0; + +static void +usage(void) +{ + fprintf(stderr, + "Usage: %s [-n <name>] [-r remoteuser] [-t remote ticketfile]" + "[-l lifetime (in minutes) ] [-h hosts... ]" + "[-f srvtab ] [-c AFS cell name ] [command ... ]\n", + __progname); + fprintf(stderr, "\nA fully qualified name can be given user[.instance][@realm]\nRealm is converted to uppercase!\n"); + exit(1); +} + +static void +doexec(int argc, char **argv) +{ + int status; + pid_t ret; + + switch (fork()) { + case -1: + err (1, "fork"); + break; + case 0: + /* in child */ + execvp(argv[0], argv); + err (1, "Can't exec program ``%s''", argv[0]); + break; + default: + /* in parent */ + do { + ret = wait(&status); + } while ((ret > 0 && !WIFEXITED(status)) || (ret < 0 && errno == EINTR)); + if (ret < 0) + perror("wait"); + dest_tkt(); + if (k_hasafs()) + k_unlog(); + break; + } +} + +static RETSIGTYPE +renew(int sig) +{ + int code; + + signal(SIGALRM, renew); + + code = krb_get_svc_in_tkt(princ.name, princ.instance, princ.realm, + KRB_TICKET_GRANTING_TICKET, + princ.realm, lifetime, srvtab); + if (code) + warnx ("%s", krb_get_err_text(code)); + else if (k_hasafs()) + { + if ((code = k_afsklog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) { + warnx ("%s", krb_get_err_text(code)); + } + } + + alarm(krb_life_to_time(0, lifetime)/2 - 60); + SIGRETURN(0); +} + +static int +zrefresh(void) +{ + switch (fork()) { + case -1: + err (1, "Warning: Failed to fork zrefresh"); + return -1; + case 0: + /* Child */ + execlp("zrefresh", "zrefresh", 0); + execl(BINDIR "/zrefresh", "zrefresh", 0); + exit(1); + default: + /* Parent */ + break; + } + return 0; +} + +static int +key_to_key(char *user, char *instance, char *realm, void *arg, + des_cblock *key) +{ + memcpy(key, arg, sizeof(des_cblock)); + return 0; +} + +int +main(int argc, char **argv) +{ + int code, more_args; + int ret; + int c; + char *file; + int pflag = 0; + char passwd[100]; + des_cblock key; + char **host; + int nhost; + char tf[MaxPathLen]; + + set_progname (argv[0]); + + if ((file = getenv("KRBTKFILE")) == 0) + file = TKT_FILE; + + memset(&princ, 0, sizeof(princ)); + memset(srvtab, 0, sizeof(srvtab)); + *remoteuser = '\0'; + nhost = 0; + + while ((c = getopt(argc, argv, "r:t:f:hl:n:c:")) != EOF) + switch (c) { + case 'f': + strncpy(srvtab, optarg, sizeof(srvtab)); + break; + case 't': + strncpy(remote_tktfile, optarg, sizeof(remote_tktfile)); + break; + case 'r': + strncpy(remoteuser, optarg, sizeof(remoteuser)); + break; + case 'l': + lifetime = atoi(optarg); + if (lifetime == -1) + lifetime = 255; + else if (lifetime < 5) + lifetime = 1; + else + lifetime = krb_time_to_life(0, lifetime*60); + if (lifetime > 255) + lifetime = 255; + break; + case 'n': + if ((code = krb_parse_name(optarg, &princ)) != 0) { + warnx ("%s", krb_get_err_text(code)); + usage(); + } + strupr(princ.realm); + pflag = 1; + break; + case 'c': + cell = optarg; + break; + case 'h': + host = argv + optind; + for(nhost = 0; optind < argc && *argv[optind] != '-'; ++optind) + ++nhost; + break; + case '?': + default: + usage(); + break; + } + + /* Look for kerberos name */ + if (!pflag && optind < argc && krb_parse_name(argv[optind], &princ) == 0) { + ++optind; + strupr(princ.realm); + } + + if (princ.name[0] == '\0' && krb_get_default_principal (princ.name, + princ.instance, + princ.realm) < 0) + errx (1, "Could not get default principal"); + + if (*remoteuser == '\0') + strcpy (remoteuser, princ.name); + + more_args = argc - optind; + + if (princ.realm[0] == '\0') + if (krb_get_lrealm(princ.realm, 1) != KSUCCESS) + strcpy(princ.realm, KRB_REALM); + + if (more_args) { + int f; + + do{ + snprintf(tf, sizeof(tf), + TKT_ROOT "%u_%u", + (unsigned)getuid(), + (unsigned)(getpid()*time(0))); + f = open(tf, O_CREAT|O_EXCL|O_RDWR); + }while(f < 0); + close(f); + unlink(tf); + setenv("KRBTKFILE", tf, 1); + krb_set_tkt_string (tf); + } + + if (srvtab[0]) + { + signal(SIGALRM, renew); + + code = read_service_key (princ.name, princ.instance, princ.realm, 0, + srvtab, (char *)&key); + if (code == KSUCCESS) + code = krb_get_in_tkt(princ.name, princ.instance, princ.realm, + KRB_TICKET_GRANTING_TICKET, + princ.realm, lifetime, + key_to_key, NULL, key); + alarm(krb_life_to_time(0, lifetime)/2 - 60); + } + else { + char prompt[128]; + + snprintf(prompt, sizeof(prompt), "%s's Password: ", krb_unparse_name(&princ)); + if (des_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ + memset(passwd, 0, sizeof(passwd)); + exit(1); + } + des_string_to_key (passwd, &key); + code = krb_get_in_tkt (princ.name, princ.instance, princ.realm, + KRB_TICKET_GRANTING_TICKET, + princ.realm, lifetime, + key_to_key, NULL, key); + if(code == INTK_BADPW) { + afs_string_to_key (passwd, princ.realm, &key); + code = krb_get_in_tkt (princ.name, princ.instance, princ.realm, + KRB_TICKET_GRANTING_TICKET, + princ.realm, lifetime, + key_to_key, NULL, key); + } + memset(passwd, 0, sizeof(passwd)); + } + if (code) { + memset (key, 0, sizeof(key)); + errx (1, "%s", krb_get_err_text(code)); + } + + if (k_hasafs()) { + if (more_args) + k_setpag(); + if ((code = k_afsklog(cell, NULL)) != 0 && code != KDC_PR_UNKNOWN) + warnx ("%s", krb_get_err_text(code)); + } + + for(ret = 0; nhost-- > 0; host++) + ret += rkinit(&princ, lifetime, remoteuser, remote_tktfile, &key, *host); + + if (ret) + return ret; + + if (more_args) + doexec(more_args, &argv[optind]); + else + zrefresh(); + + return 0; +} diff --git a/crypto/kerberosIV/appl/kauth/kauth.h b/crypto/kerberosIV/appl/kauth/kauth.h new file mode 100644 index 0000000..2c48fcc --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/kauth.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: kauth.h,v 1.18 1997/05/20 18:40:31 bg Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <signal.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#ifdef HAVE_GRP_H +#include <grp.h> +#endif + +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif /* HAVE_SYS_RESOURCE_H */ +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef SOCKS +#include <socks.h> +#endif + +#include <err.h> + +#include <krb.h> +#include <kafs.h> + +#include <roken.h> + +#define KAUTH_PORT 2120 + +#define KAUTH_VERSION "RKINIT.0" + +int rkinit (krb_principal*, int, char*, char*, des_cblock*, char*); + +int write_encrypted (int, void*, size_t, des_key_schedule, + des_cblock*, struct sockaddr_in*, struct sockaddr_in*); + +int read_encrypted (int, void*, size_t, void **, des_key_schedule, + des_cblock*, struct sockaddr_in*, struct sockaddr_in*); + +unsigned pack_args (char *, krb_principal*, int, char*, char*); + +int unpack_args (char*, krb_principal*, int*, char*, char*); diff --git a/crypto/kerberosIV/appl/kauth/kauthd.c b/crypto/kerberosIV/appl/kauth/kauthd.c new file mode 100644 index 0000000..b6a40cf --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/kauthd.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "kauth.h" + +RCSID("$Id: kauthd.c,v 1.22 1997/05/18 20:37:55 assar Exp $"); + +krb_principal princ; +static char locuser[SNAME_SZ + 1]; +static int lifetime; +static char tktfile[MaxPathLen + 1]; + +struct remote_args { + int sock; + des_key_schedule *schedule; + des_cblock *session; + struct sockaddr_in *me, *her; +}; + +static int +decrypt_remote_tkt (char *user, char *inst, char *realm, void *varg, + key_proc_t key_proc, KTEXT *cipp) +{ + char buf[BUFSIZ]; + void *ptr; + int len; + KTEXT cip = *cipp; + struct remote_args *args = (struct remote_args *)varg; + + write_encrypted (args->sock, cip->dat, cip->length, + *args->schedule, args->session, args->me, + args->her); + len = read_encrypted (args->sock, buf, sizeof(buf), &ptr, *args->schedule, + args->session, args->her, args->me); + memcpy(cip->dat, ptr, cip->length); + + return 0; +} + +static int +doit(int sock) +{ + int status; + KTEXT_ST ticket; + AUTH_DAT auth; + char instance[INST_SZ + 1]; + des_key_schedule schedule; + struct sockaddr_in thisaddr, thataddr; + int addrlen; + int len; + char buf[BUFSIZ]; + void *data; + struct passwd *passwd; + char version[KRB_SENDAUTH_VLEN + 1]; + char remotehost[MaxHostNameLen]; + + addrlen = sizeof(thisaddr); + if (getsockname (sock, (struct sockaddr *)&thisaddr, &addrlen) < 0 || + addrlen != sizeof(thisaddr)) { + return 1; + } + addrlen = sizeof(thataddr); + if (getpeername (sock, (struct sockaddr *)&thataddr, &addrlen) < 0 || + addrlen != sizeof(thataddr)) { + return 1; + } + + inaddr2str (thataddr.sin_addr, remotehost, sizeof(remotehost)); + + k_getsockinst (sock, instance, sizeof(instance)); + status = krb_recvauth (KOPT_DO_MUTUAL, sock, &ticket, "rcmd", instance, + &thataddr, &thisaddr, &auth, "", schedule, + version); + if (status != KSUCCESS || + strncmp(version, KAUTH_VERSION, KRB_SENDAUTH_VLEN) != 0) { + return 1; + } + len = read_encrypted (sock, buf, sizeof(buf), &data, schedule, + &auth.session, &thataddr, &thisaddr); + if (len < 0) { + write_encrypted (sock, "read_enc failed", + sizeof("read_enc failed") - 1, schedule, + &auth.session, &thisaddr, &thataddr); + return 1; + } + if (unpack_args(data, &princ, &lifetime, locuser, + tktfile)) { + write_encrypted (sock, "unpack_args failed", + sizeof("unpack_args failed") - 1, schedule, + &auth.session, &thisaddr, &thataddr); + return 1; + } + + if( kuserok(&auth, locuser) != 0) { + snprintf(buf, sizeof(buf), "%s cannot get tickets for %s", + locuser, krb_unparse_name(&princ)); + syslog (LOG_ERR, buf); + write_encrypted (sock, buf, strlen(buf), schedule, + &auth.session, &thisaddr, &thataddr); + return 1; + } + passwd = k_getpwnam (locuser); + if (passwd == NULL) { + snprintf (buf, sizeof(buf), "No user '%s'", locuser); + syslog (LOG_ERR, buf); + write_encrypted (sock, buf, strlen(buf), schedule, + &auth.session, &thisaddr, &thataddr); + return 1; + } + if (setgid (passwd->pw_gid) || + initgroups(passwd->pw_name, passwd->pw_gid) || + setuid(passwd->pw_uid)) { + snprintf (buf, sizeof(buf), "Could not change user"); + syslog (LOG_ERR, buf); + write_encrypted (sock, buf, strlen(buf), schedule, + &auth.session, &thisaddr, &thataddr); + return 1; + } + write_encrypted (sock, "ok", sizeof("ok") - 1, schedule, + &auth.session, &thisaddr, &thataddr); + + if (*tktfile == 0) + snprintf(tktfile, sizeof(tktfile), "%s%u", TKT_ROOT, (unsigned)getuid()); + krb_set_tkt_string (tktfile); + + { + struct remote_args arg; + + arg.sock = sock; + arg.schedule = &schedule; + arg.session = &auth.session; + arg.me = &thisaddr; + arg.her = &thataddr; + + status = krb_get_in_tkt (princ.name, princ.instance, princ.realm, + KRB_TICKET_GRANTING_TICKET, + princ.realm, + lifetime, NULL, decrypt_remote_tkt, &arg); + } + if (status == KSUCCESS) { + syslog (LOG_INFO, "from %s(%s): %s -> %s", + remotehost, + inet_ntoa(thataddr.sin_addr), + locuser, + krb_unparse_name (&princ)); + write_encrypted (sock, "ok", sizeof("ok") - 1, schedule, + &auth.session, &thisaddr, &thataddr); + return 0; + } else { + snprintf (buf, sizeof(buf), "TGT failed: %s", krb_get_err_text(status)); + syslog (LOG_NOTICE, buf); + write_encrypted (sock, buf, strlen(buf), schedule, + &auth.session, &thisaddr, &thataddr); + return 1; + } +} + +int +main (int argc, char **argv) +{ + openlog ("kauthd", LOG_ODELAY, LOG_AUTH); + + if(argc > 1 && strcmp(argv[1], "-i") == 0) + mini_inetd (k_getportbyname("kauth", "tcp", htons(KAUTH_PORT))); + return doit(STDIN_FILENO); +} diff --git a/crypto/kerberosIV/appl/kauth/ksrvtgt.in b/crypto/kerberosIV/appl/kauth/ksrvtgt.in new file mode 100644 index 0000000..30d9e15 --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/ksrvtgt.in @@ -0,0 +1,14 @@ +#! /bin/sh +# $Id: ksrvtgt.in,v 1.2 1997/04/05 21:29:17 assar Exp $ + +usage="Usage: `basename $0` name instance [[realm] srvtab]" + +if [ $# -lt 2 -o $# -gt 4 ]; then + echo "$usage" + exit 1 +fi + +srvtab="${4-${3-/etc/srvtab}}" +realm="${4+@$3}" + +%bindir%/kauth -n "$1.$2$realm" -l 5 -f "$srvtab " diff --git a/crypto/kerberosIV/appl/kauth/marshall.c b/crypto/kerberosIV/appl/kauth/marshall.c new file mode 100644 index 0000000..4f1bfeb --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/marshall.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "kauth.h" + +RCSID("$Id: marshall.c,v 1.7 1997/04/01 08:17:32 joda Exp $"); + +unsigned +pack_args (char *buf, krb_principal *pr, int lifetime, + char *locuser, char *tktfile) +{ + char *p; + + p = buf; + strcpy (p, pr->name); + p += strlen (pr->name) + 1; + strcpy (p, pr->instance); + p += strlen (pr->instance) + 1; + strcpy (p, pr->realm); + p += strlen (pr->realm) + 1; + *p++ = (unsigned char)lifetime; + strcpy(p, locuser); + p += strlen (locuser) + 1; + strcpy(p, tktfile); + p += strlen(tktfile) + 1; + return p - buf; +} + +int +unpack_args (char *buf, krb_principal *pr, int *lifetime, + char *locuser, char *tktfile) +{ + int len; + + len = strlen(buf); + if (len > SNAME_SZ) + return -1; + strncpy(pr->name, buf, len + 1); + buf += len + 1; + len = strlen (buf); + if (len > INST_SZ) + return -1; + strncpy (pr->instance, buf, len + 1); + buf += len + 1; + len = strlen (buf); + if (len > REALM_SZ) + return -1; + strncpy (pr->realm, buf, len + 1); + buf += len + 1; + *lifetime = (unsigned char)*buf++; + len = strlen(buf); + if (len > SNAME_SZ) + return -1; + strncpy (locuser, buf, len + 1); + buf += len + 1; + len = strlen(buf); + if (len > MaxPathLen) + return -1; + strncpy (tktfile, buf, len + 1); + buf += len + 1; + return 0; +} diff --git a/crypto/kerberosIV/appl/kauth/rkinit.c b/crypto/kerberosIV/appl/kauth/rkinit.c new file mode 100644 index 0000000..ec75d46 --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/rkinit.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "kauth.h" + +RCSID("$Id: rkinit.c,v 1.19 1997/04/01 08:17:33 joda Exp $"); + +static struct in_addr * +getalladdrs (char *hostname, unsigned *count) +{ + struct hostent *hostent; + struct in_addr **h; + struct in_addr *addr; + unsigned naddr; + unsigned maxaddr; + + hostent = gethostbyname (hostname); + if (hostent == NULL) { + warnx ("gethostbyname '%s' failed: %s\n", + hostname, +#ifdef HAVE_H_ERRNO + hstrerror(h_errno) +#else + "unknown error" +#endif + ); + return NULL; + } + maxaddr = 1; + naddr = 0; + addr = malloc(sizeof(*addr) * maxaddr); + if (addr == NULL) { + warnx ("out of memory"); + return NULL; + } + for (h = (struct in_addr **)(hostent->h_addr_list); + *h != NULL; + h++) { + if (naddr >= maxaddr) { + maxaddr *= 2; + addr = realloc (addr, sizeof(*addr) * maxaddr); + if (addr == NULL) { + warnx ("out of memory"); + return NULL; + } + } + addr[naddr++] = **h; + } + addr = realloc (addr, sizeof(*addr) * naddr); + if (addr == NULL) { + warnx ("out of memory"); + return NULL; + } + *count = naddr; + return addr; +} + +static int +doit_host (krb_principal *princ, int lifetime, char *locuser, + char *tktfile, des_cblock *key, int s, char *hostname) +{ + char buf[BUFSIZ]; + int inlen; + KTEXT_ST text; + CREDENTIALS cred; + MSG_DAT msg; + int status; + des_key_schedule schedule; + struct sockaddr_in thisaddr, thataddr; + int addrlen; + void *ret; + + addrlen = sizeof(thisaddr); + if (getsockname (s, (struct sockaddr *)&thisaddr, &addrlen) < 0 || + addrlen != sizeof(thisaddr)) { + warn ("getsockname(%s)", hostname); + return 1; + } + addrlen = sizeof(thataddr); + if (getpeername (s, (struct sockaddr *)&thataddr, &addrlen) < 0 || + addrlen != sizeof(thataddr)) { + warn ("getpeername(%s)", hostname); + return 1; + } + + status = krb_sendauth (KOPT_DO_MUTUAL, s, &text, "rcmd", + hostname, krb_realmofhost (hostname), + getpid(), &msg, &cred, schedule, + &thisaddr, &thataddr, KAUTH_VERSION); + if (status != KSUCCESS) { + warnx ("%s: %s\n", hostname, krb_get_err_text(status)); + return 1; + } + inlen = pack_args (buf, princ, lifetime, locuser, tktfile); + + if (write_encrypted(s, buf, inlen, schedule, &cred.session, + &thisaddr, &thataddr) < 0) { + warn ("write to %s", hostname); + return 1; + } + + inlen = read_encrypted (s, buf, sizeof(buf), &ret, schedule, + &cred.session, &thataddr, &thisaddr); + if (inlen < 0) { + warn ("read from %s failed", hostname); + return 1; + } + + if (strncmp(ret, "ok", inlen) != 0) { + warnx ("error from %s: %.*s\n", + hostname, inlen, (char *)ret); + return 1; + } + + inlen = read_encrypted (s, buf, sizeof(buf), &ret, schedule, + &cred.session, &thataddr, &thisaddr); + if (inlen < 0) { + warn ("read from %s", hostname); + return 1; + } + + { + des_key_schedule key_s; + + des_key_sched(key, key_s); + des_pcbc_encrypt(ret, ret, inlen, key_s, key, DES_DECRYPT); + memset(key_s, 0, sizeof(key_s)); + } + write_encrypted (s, ret, inlen, schedule, &cred.session, + &thisaddr, &thataddr); + + inlen = read_encrypted (s, buf, sizeof(buf), &ret, schedule, + &cred.session, &thataddr, &thisaddr); + if (inlen < 0) { + warn ("read from %s", hostname); + return 1; + } + + if (strncmp(ret, "ok", inlen) != 0) { + warnx ("error from %s: %.*s\n", + hostname, inlen, (char *)ret); + return 1; + } + return 0; +} + +int +rkinit (krb_principal *princ, int lifetime, char *locuser, + char *tktfile, des_cblock *key, char *hostname) +{ + struct in_addr *addr; + unsigned naddr; + unsigned i; + int port; + int success; + + addr = getalladdrs (hostname, &naddr); + if (addr == NULL) + return 1; + port = k_getportbyname ("kauth", "tcp", htons(KAUTH_PORT)); + success = 0; + for (i = 0; !success && i < naddr; ++i) { + struct sockaddr_in a; + int s; + + memset(&a, 0, sizeof(a)); + a.sin_family = AF_INET; + a.sin_port = port; + a.sin_addr = addr[i]; + + s = socket (AF_INET, SOCK_STREAM, 0); + if (s < 0) { + warn("socket"); + return 1; + } + if (connect(s, (struct sockaddr *)&a, sizeof(a)) < 0) { + warn("connect(%s)", hostname); + continue; + } + + success = success || !doit_host (princ, lifetime, + locuser, tktfile, key, + s, hostname); + close (s); + } + return !success; +} diff --git a/crypto/kerberosIV/appl/kauth/zrefresh b/crypto/kerberosIV/appl/kauth/zrefresh new file mode 100644 index 0000000..8347a1b --- /dev/null +++ b/crypto/kerberosIV/appl/kauth/zrefresh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# @(#) $Id: zrefresh,v 1.3 1996/06/09 19:21:59 joda Exp $ +# +# Substitute this script with a real zrefresh if running Zephyr. For +# instance: +# +# if [ -f "$WGFILE" ] ; then +# zctl load +# fi + +exit 0 diff --git a/crypto/kerberosIV/appl/kip/Makefile.in b/crypto/kerberosIV/appl/kip/Makefile.in new file mode 100644 index 0000000..690a661 --- /dev/null +++ b/crypto/kerberosIV/appl/kip/Makefile.in @@ -0,0 +1,96 @@ +# $Id: Makefile.in,v 1.12 1997/03/23 13:04:03 assar Exp $ + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +AR = ar +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +LD_FLAGS = @LD_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LIBS = @LIBS@ +MKINSTALLDIRS = @top_srcdir@/mkinstalldirs + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libexecdir = @libexecdir@ +libdir = @libdir@ +bindir = @bindir@ +transform=@program_transform_name@ +EXECSUFFIX=@EXECSUFFIX@ + +PROG_BIN = kip$(EXECSUFFIX) +PROG_LIBEXEC = kipd$(EXECSUFFIX) +PROGS = $(PROG_BIN) $(PROG_LIBEXEC) + +SOURCES_KIP = kip.c +SOURCES_KIPD = kipd.c +SOURCES_COMMON = common.c + +OBJECTS_KIP = kip.o common.o +OBJECTS_KIPD = kipd.o common.o + +OBJECTS = $(OBJECTS_KIP) $(OBJECTS_KIPD) +SOURCES = $(SOURCES_KIP) $(SOURCES_KIPD) $(SOURCES_COMMON) + +all: $(PROGS) + +Wall: + make CFLAGS="-g -Wall -Wno-comment -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) -I../../include -I$(srcdir) $(CFLAGS) $< + +install: all + $(MKINSTALLDIRS) $(bindir) $(libexecdir) + for x in $(PROG_BIN); do \ + $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \ + done + for x in $(PROG_LIBEXEC); do \ + $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + +uninstall: + for x in $(PROG_BIN); do \ + rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \ + done + for x in $(PROG_LIBEXEC); do \ + rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + done + +TAGS: $(SOURCES) + etags $(SOURCES) + +check: + +clean: + rm -f *.a *.o $(PROGS) + +mostlyclean: clean + +distclean: clean + rm -f Makefile *.tab.c *~ + +realclean: distclean + rm -f TAGS + +dist: $(DISTFILES) + for file in $(DISTFILES); do \ + ln $$file ../`cat ../.fname`/lib \ + || cp -p $$file ../`cat ../.fname`/lib; \ + done + +KLIB=-L../../lib/krb -lkrb -L../../lib/des -ldes +LIBROKEN=-L../../lib/roken -lroken + +kip$(EXECSUFFIX): $(OBJECTS_KIP) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIP) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +kipd$(EXECSUFFIX): $(OBJECTS_KIPD) + $(CC) $(LD_FLAGS) $(LDFLAGS) -o $@ $(OBJECTS_KIPD) $(KLIB) $(LIBROKEN) $(LIBS) $(LIBROKEN) + +$(OBJECTS): ../../include/config.h diff --git a/crypto/kerberosIV/appl/kip/common.c b/crypto/kerberosIV/appl/kip/common.c new file mode 100644 index 0000000..b21d03d --- /dev/null +++ b/crypto/kerberosIV/appl/kip/common.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "kip.h" + +RCSID("$Id: common.c,v 1.12 1997/05/02 14:28:06 assar Exp $"); + +/* + * Copy packets from `tundev' to `netdev' or vice versa. + * Mode is used when reading from `tundev' + */ + +int +copy_packets (int tundev, int netdev, int mtu, des_cblock *iv, + des_key_schedule schedule) +{ + des_cblock iv1, iv2; + int num1 = 0, num2 = 0; + u_char *buf; + + buf = malloc (mtu + 2); + if (buf == NULL) { + warnx("malloc(%d) failed", mtu); + return 1; + } + + memcpy (&iv1, iv, sizeof(iv1)); + memcpy (&iv2, iv, sizeof(iv2)); + for (;;) { + fd_set fdset; + int ret, len; + + FD_ZERO(&fdset); + FD_SET(tundev, &fdset); + FD_SET(netdev, &fdset); + + ret = select (max(tundev, netdev)+1, &fdset, NULL, NULL, NULL); + if (ret < 0 && errno != EINTR) { + warn ("select"); + return 1; + } + if (FD_ISSET(tundev, &fdset)) { + ret = read (tundev, buf + 2, mtu); + if (ret == 0) + return 0; + if (ret < 0) { + if (errno == EINTR) + continue; + else { + warn("read"); + return ret; + } + } + buf[0] = ret >> 8; + buf[1] = ret & 0xFF; + ret += 2; + des_cfb64_encrypt (buf, buf, ret, schedule, + &iv1, &num1, DES_ENCRYPT); + ret = krb_net_write (netdev, buf, ret); + if (ret < 0) { + warn("write"); + return ret; + } + } + if (FD_ISSET(netdev, &fdset)) { + ret = read (netdev, buf, 2); + if (ret == 0) + return 0; + if (ret < 0) { + if (errno == EINTR) + continue; + else { + warn("read"); + return ret; + } + } + des_cfb64_encrypt (buf, buf, 2, schedule, + &iv2, &num2, DES_DECRYPT); + len = (buf[0] << 8 ) | buf[1]; + ret = krb_net_read (netdev, buf + 2, len); + if (ret == 0) + return 0; + if (ret < 0) { + if (errno == EINTR) + continue; + else { + warn("read"); + return ret; + } + } + des_cfb64_encrypt (buf + 2, buf + 2, len, schedule, + &iv2, &num2, DES_DECRYPT); + ret = krb_net_write (tundev, buf + 2, len); + if (ret < 0) { + warn("write"); + return ret; + } + } + } +} + +/* + * Signal handler that justs waits for the children when they die. + */ + +RETSIGTYPE +childhandler (int sig) +{ + pid_t pid; + int status; + + do { + pid = waitpid (-1, &status, WNOHANG|WUNTRACED); + } while(pid > 0); + signal (SIGCHLD, childhandler); + SIGRETURN(0); +} + +/* + * Find a free tunnel device and open it. + */ + +int +tunnel_open (void) +{ + int fd; + int i; + char name[64]; + + for (i = 0; i < 256; ++i) { + snprintf (name, sizeof(name), "%s%s%d", _PATH_DEV, TUNDEV, i); + fd = open (name, O_RDWR, 0); + if (fd >= 0) + break; + if (errno == ENOENT || errno == ENODEV) { + warn("open %s", name); + return fd; + } + } + if (fd < 0) + warn("open %s" ,name); + return fd; +} diff --git a/crypto/kerberosIV/appl/kip/kip.c b/crypto/kerberosIV/appl/kip/kip.c new file mode 100644 index 0000000..e324a28 --- /dev/null +++ b/crypto/kerberosIV/appl/kip/kip.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "kip.h" + +RCSID("$Id: kip.c,v 1.15 1997/05/11 10:54:51 assar Exp $"); + +static void +usage() +{ + fprintf (stderr, "Usage: %s host\n", + __progname); + exit (1); +} + +/* + * Establish authenticated connection + */ + +static int +connect_host (char *host, des_cblock *key, des_key_schedule schedule) +{ + CREDENTIALS cred; + KTEXT_ST text; + MSG_DAT msg; + int status; + struct sockaddr_in thisaddr, thataddr; + int addrlen; + struct hostent *hostent; + int s; + u_char b; + char **p; + + hostent = gethostbyname (host); + if (hostent == NULL) { + warnx ("gethostbyname '%s': %s", host, +#ifdef HAVE_H_ERRNO + hstrerror(h_errno) +#else + "unknown error" +#endif + ); + return -1; + } + + memset (&thataddr, 0, sizeof(thataddr)); + thataddr.sin_family = AF_INET; + thataddr.sin_port = k_getportbyname ("kip", "tcp", htons(KIPPORT)); + + for(p = hostent->h_addr_list; *p; ++p) { + int one = 1; + + memcpy (&thataddr.sin_addr, *p, sizeof(thataddr.sin_addr)); + + s = socket (AF_INET, SOCK_STREAM, 0); + if (s < 0) { + warn ("socket"); + return -1; + } + +#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) + setsockopt (s, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one)); +#endif + + if (connect (s, (struct sockaddr *)&thataddr, sizeof(thataddr)) < 0) { + warn ("connect(%s)", host); + close (s); + continue; + } else { + break; + } + } + if (*p == NULL) + return -1; + + addrlen = sizeof(thisaddr); + if (getsockname (s, (struct sockaddr *)&thisaddr, &addrlen) < 0 || + addrlen != sizeof(thisaddr)) { + warn ("getsockname(%s)", host); + return -1; + } + status = krb_sendauth (KOPT_DO_MUTUAL, s, &text, "rcmd", + host, krb_realmofhost (host), + getpid(), &msg, &cred, schedule, + &thisaddr, &thataddr, KIP_VERSION); + if (status != KSUCCESS) { + warnx("%s: %s", host, + krb_get_err_text(status)); + return -1; + } + if (read (s, &b, sizeof(b)) != sizeof(b)) { + warn ("read"); + return -1; + } + if (b) { + char buf[BUFSIZ]; + + read (s, buf, sizeof(buf)); + buf[BUFSIZ - 1] = '\0'; + + warnx ("%s: %s", host, buf); + return -1; + } + + memcpy(key, &cred.session, sizeof(des_cblock)); + return s; +} + +/* + * Connect to the given host. + */ + +static int +doit (char *host) +{ + des_key_schedule schedule; + des_cblock iv; + int other, this; + struct ifreq ifreq; + int sock; + + other = connect_host (host, &iv, schedule); + if (other < 0) + return 1; + this = tunnel_open (); + if (this < 0) + return 1; + return copy_packets (this, other, TUNMTU, &iv, schedule); +} + +/* + * kip - forward IP packets over a kerberos-encrypted channel. + * + */ + +int +main(int argc, char **argv) +{ + set_progname (argv[0]); + + if (argc != 2) + usage (); + return doit (argv[1]); +} diff --git a/crypto/kerberosIV/appl/kip/kip.h b/crypto/kerberosIV/appl/kip/kip.h new file mode 100644 index 0000000..94e30a5 --- /dev/null +++ b/crypto/kerberosIV/appl/kip/kip.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +/* $Id: kip.h,v 1.16 1997/05/20 18:40:31 bg Exp $ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <pwd.h> +#include <signal.h> +#include <paths.h> +#include <fcntl.h> +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#endif +#include <sys/types.h> +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#else +#include <time.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/sockio.h> +#include <net/if.h> +#ifdef HAVE_NET_IF_VAR_H +#include <net/if_var.h> +#endif +#include <net/if_tun.h> +#include <err.h> + +#ifdef SOCKS +#include <socks.h> +#endif + +#include <krb.h> + +#include <roken.h> + +#define TUNDEV "tun" + +#define KIPPORT 2112 + +#define KIP_VERSION "KIPSRV.0" + +int +copy_packets (int tundev, int netdev, int mtu, des_cblock *iv, + des_key_schedule schedule); + +RETSIGTYPE childhandler (int); + +int +tunnel_open (void); diff --git a/crypto/kerberosIV/appl/kip/kipd.c b/crypto/kerberosIV/appl/kip/kipd.c new file mode 100644 index 0000000..6d9d334 --- /dev/null +++ b/crypto/kerberosIV/appl/kip/kipd.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1995, 1996, 1997 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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 "kip.h" + +RCSID("$Id: kipd.c,v 1.13 1997/05/18 20:38:01 assar Exp $"); + +static int +fatal (int fd, char *s) +{ + u_char err = 1; + + write (fd, &err, sizeof(err)); + write (fd, s, strlen(s)+1); + syslog(LOG_ERR, s); + return err; +} + +static int +recv_conn (int sock, des_cblock *key, des_key_schedule schedule, + struct sockaddr_in *retaddr) +{ + int status; + KTEXT_ST ticket; + AUTH_DAT auth; + char instance[INST_SZ + 1]; + struct sockaddr_in thisaddr, thataddr; + int addrlen; + char version[KRB_SENDAUTH_VLEN + 1]; + u_char ok = 0; + struct passwd *passwd; + + addrlen = sizeof(thisaddr); + if (getsockname (sock, (struct sockaddr *)&thisaddr, &addrlen) < 0 || + addrlen != sizeof(thisaddr)) { + return 1; + } + addrlen = sizeof(thataddr); + if (getpeername (sock, (struct sockaddr *)&thataddr, &addrlen) < 0 || + addrlen != sizeof(thataddr)) { + return 1; + } + + k_getsockinst (sock, instance, sizeof(instance)); + status = krb_recvauth (KOPT_DO_MUTUAL, sock, &ticket, "rcmd", instance, + &thataddr, &thisaddr, &auth, "", schedule, + version); + if (status != KSUCCESS || + strncmp(version, KIP_VERSION, KRB_SENDAUTH_VLEN) != 0) { + return 1; + } + passwd = k_getpwnam ("root"); + if (passwd == NULL) + return fatal (sock, "Cannot find root"); + if (kuserok(&auth, "root") != 0) + return fatal (sock, "Permission denied"); + if (write (sock, &ok, sizeof(ok)) != sizeof(ok)) + return 1; + + memcpy(key, &auth.session, sizeof(des_cblock)); + *retaddr = thataddr; + return 0; +} + +static int +doit(int sock) +{ + struct sockaddr_in thataddr; + des_key_schedule schedule; + des_cblock key; + int this; + + if (recv_conn (sock, &key, schedule, &thataddr)) + return 1; + this = tunnel_open (); + if (this < 0) + fatal (sock, "Cannot open " _PATH_DEV TUNDEV); + return copy_packets (this, sock, TUNMTU, &key, schedule); +} + +/* + * kipd - receive forwarded IP + */ + +int +main (int argc, char **argv) +{ + set_progname (argv[0]); + + openlog(__progname, LOG_PID|LOG_CONS, LOG_DAEMON); + signal (SIGCHLD, childhandler); + return doit(0); +} |