diff options
Diffstat (limited to 'crypto/kerberosIV/appl/ftp')
30 files changed, 3581 insertions, 1845 deletions
diff --git a/crypto/kerberosIV/appl/ftp/ChangeLog b/crypto/kerberosIV/appl/ftp/ChangeLog new file mode 100644 index 0000000..422f4a5 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ChangeLog @@ -0,0 +1,196 @@ +1999-08-18 Assar Westerlund <assar@sics.se> + + * ftp/cmds.c (getit): be more suspicious when parsing the result + of MDTM. Do the comparison of timestamps correctly. + +1999-06-15 Assar Westerlund <assar@sics.se> + + * ftp/krb4.c (krb4_auth): type correctness + +1999-06-02 Johan Danielsson <joda@pdc.kth.se> + + * ftp/ftp.c (sendrequest): lmode != rmode + +1999-05-21 Assar Westerlund <assar@sics.se> + + * ftp/extern.h (sendrequest): update prototype + + * ftp/cmds.c: update calls to sendrequest and recvrequest to send + "b" when appropriate + + * ftp/ftp.c (sendrequest): add argument for mode to open file in. + +1999-05-08 Assar Westerlund <assar@sics.se> + + * ftpd/ftpcmd.y: rename getline -> ftpd_getline + + * ftp/main.c (makeargv): fill in unused slots with NULL + +Thu Apr 8 15:06:40 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/ftpd.c: remove definition of KRB_VERIFY_USER (moved to + config.h) + +Wed Apr 7 16:15:21 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftp/gssapi.c (gss_auth): call gss_display_status to get a sane + error message; return AUTH_{CONTINUE,ERROR}, where appropriate + + * ftp/krb4.c: return AUTH_{CONTINUE,ERROR}, where appropriate + + * ftp/security.c (sec_login): if mechanism returns AUTH_CONTINUE, + just continue with the next mechanism, this fixes the case of + having GSSAPI fail because of non-existant of expired tickets + + * ftp/security.h: add AUTH_{OK,CONTINUE,ERROR} + +Thu Apr 1 16:59:04 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/Makefile.am: don't run check-local + + * ftp/Makefile.am: don't run check-local + +Mon Mar 22 22:15:18 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd.c (pass): fall-back for KRB_VERIFY_SECURE + + * ftpd/ftpd.c (pass): 1 -> KRB_VERIFY_SECURE + +Thu Mar 18 12:07:09 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/Makefile.am: clean ftpcmd.c + + * ftpd/ftpd_locl.h: remove krb5.h (breaks in ftpcmd.y) + + * ftpd/ftpd.c: move include of krb5.h here + + * ftpd/Makefile.am: include Makefile.am.common + + * Makefile.am: include Makefile.am.common + + * ftp/Makefile.am: include Makefile.am.common + + * common/Makefile.am: include Makefile.am.common + +Tue Mar 16 22:28:37 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd_locl.h: add krb5.h to get heimdal_version + + * ftpd/ftpd.c: krb_verify_user_multiple -> krb_verify_user + +Thu Mar 11 14:54:59 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftp/Makefile.in: WFLAGS + + * ftp/ruserpass.c: add some if-braces + +Wed Mar 10 20:02:55 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/ftpd_locl.h: remove ifdef HAVE_FNMATCH + +Mon Mar 8 21:29:24 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/ftpd.c: re-add version in greeting message + +Mon Mar 1 10:49:38 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/logwtmp.c: HAVE_UT_* -> HAVE_STRUCT_UTMP*_UT_* + +Mon Feb 22 19:20:51 1999 Johan Danielsson <joda@hella.pdc.kth.se> + + * common/Makefile.in: remove glob + +Sat Feb 13 17:19:35 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd.c (match): remove #ifdef HAVE_FNMATCH. We have a + fnmatch implementation in roken and therefore always have it. + + * ftp/ftp.c (copy_stream): initialize `werr' + +Wed Jan 13 23:52:57 1999 Assar Westerlund <assar@sics.se> + + * ftpd/ftpcmd.y: moved all check_login and check_login_no_guest to + the end of the rules to ensure we don't generate several + (independent) error messages. once again, having a yacc-grammar + for FTP with embedded actions doesn't strike me as the most + optimal way of doing it. + +Tue Dec 1 14:44:29 1998 Johan Danielsson <joda@hella.pdc.kth.se> + + * ftpd/Makefile.am: link with extra libs for aix + +Sun Nov 22 10:28:20 1998 Assar Westerlund <assar@sics.se> + + * ftpd/ftpd.c (retrying): support on-the-fly decompression + + * ftpd/Makefile.in (WFLAGS): set + + * ftp/ruserpass.c (guess_domain): new function + (ruserpass): use it + + * common/Makefile.in (WFLAGS): set + + * Makefile.in (WFLAGS): set + +Sat Nov 21 23:13:03 1998 Assar Westerlund <assar@sics.se> + + * ftp/security.c: some more type correctness. + + * ftp/gssapi.c (gss_adat): more braces to shut up warnings + +Wed Nov 18 21:47:55 1998 Assar Westerlund <assar@sics.se> + + * ftp/main.c (main): new option `-p' for enable passive mode. + +Mon Nov 2 01:57:49 1998 Assar Westerlund <assar@sics.se> + + * ftp/ftp.c (getreply): remove extra `break' + + * ftp/gssapi.c (gss_auth): fixo typo(copyo?) + + * ftp/security.c (sec_login): fix loop and return value + +Tue Sep 1 16:56:42 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/cmds.c (quote1): fix % quoting bug + +Fri Aug 14 17:10:06 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/krb4.c: krb_put_int -> KRB_PUT_INT + +Tue Jun 30 18:07:15 1998 Assar Westerlund <assar@sics.se> + + * ftp/security.c (auth): free `app_data' + (sec_end): only destroy if it was initialized + +Tue Jun 9 21:01:59 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/krb4.c: pass client address to krb_rd_req + +Sat May 16 00:02:07 1998 Assar Westerlund <assar@sics.se> + + * ftpd/Makefile.am: link with DBLIB + +Tue May 12 14:15:32 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/gssapi.c: Save client name for userok(). + + * ftpd/gss_userok.c: Userok for gssapi. + +Fri May 1 07:15:01 1998 Assar Westerlund <assar@sics.se> + + * ftp/ftp.c: unifdef -DHAVE_H_ERRNO + +Fri Mar 27 00:46:07 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * Make compile w/o krb4. + +Thu Mar 26 03:49:12 1998 Johan Danielsson <joda@emma.pdc.kth.se> + + * ftp/*, ftpd/*: Changes for new framework. + + * ftp/gssapi.c: GSS-API backend for the new security framework. + + * ftp/krb4.c: Updated for new framework. + + * ftp/security.{c,h}: New unified security framework. diff --git a/crypto/kerberosIV/appl/ftp/Makefile.am b/crypto/kerberosIV/appl/ftp/Makefile.am new file mode 100644 index 0000000..f8831a3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/Makefile.am @@ -0,0 +1,5 @@ +# $Id: Makefile.am,v 1.5 1999/03/20 13:58:14 joda Exp $ + +include $(top_srcdir)/Makefile.am.common + +SUBDIRS = common ftp ftpd diff --git a/crypto/kerberosIV/appl/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/Makefile.in index 6d0c420..68546ab 100644 --- a/crypto/kerberosIV/appl/ftp/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.9 1997/03/23 13:03:54 assar Exp $ +# $Id: Makefile.in,v 1.12 1999/03/10 19:01:11 joda Exp $ srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -11,7 +11,8 @@ SHELL = /bin/sh CC = @CC@ RANLIB = @RANLIB@ DEFS = @DEFS@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ INSTALL = @INSTALL@ @@ -39,3 +40,5 @@ distclean: for i in $(SUBDIRS); \ do (cd $$i && $(MAKE) $(MFLAGS) distclean); done rm -f Makefile *~ + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/common/Makefile.am b/crypto/kerberosIV/appl/ftp/common/Makefile.am new file mode 100644 index 0000000..2ab5801 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/common/Makefile.am @@ -0,0 +1,12 @@ +# $Id: Makefile.am,v 1.7 1999/03/20 13:58:14 joda Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += $(INCLUDE_krb4) + +noinst_LIBRARIES = libcommon.a + +libcommon_a_SOURCES = \ + sockbuf.c \ + buffer.c \ + common.h diff --git a/crypto/kerberosIV/appl/ftp/common/Makefile.in b/crypto/kerberosIV/appl/ftp/common/Makefile.in index 9ce1aa5..b00bd0a 100644 --- a/crypto/kerberosIV/appl/ftp/common/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/common/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.17 1997/05/18 20:00:06 assar Exp $ +# $Id: Makefile.in,v 1.23 1999/03/10 19:01:11 joda Exp $ SHELL = /bin/sh @@ -10,16 +10,17 @@ CC = @CC@ AR = ar RANLIB = @RANLIB@ DEFS = @DEFS@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ INSTALL = @INSTALL@ prefix = @prefix@ -SOURCES = base64.c glob.c sockbuf.c buffer.c +SOURCES = sockbuf.c buffer.c OBJECTS = $(libcommon_OBJS) -libcommon_OBJS = base64.o glob.o sockbuf.o buffer.o +libcommon_OBJS = sockbuf.o buffer.o LIBNAME = $(LIBPREFIX)common LIBEXT = a @@ -29,7 +30,7 @@ LIB = $(LIBNAME).$(LIBEXT) all: $(LIB) .c.o: - $(CC) -c $(CFLAGS) -I$(srcdir) -I../../../include $(DEFS) $< + $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $< $(LIB): $(libcommon_OBJS) rm -f $@ @@ -50,3 +51,5 @@ distclean: rm -f Makefile $(OBJECTS): ../../../include/config.h + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/common/buffer.c b/crypto/kerberosIV/appl/ftp/common/buffer.c index 5b7829a..97e2815 100644 --- a/crypto/kerberosIV/appl/ftp/common/buffer.c +++ b/crypto/kerberosIV/appl/ftp/common/buffer.c @@ -38,9 +38,10 @@ #include "common.h" #include <stdio.h> +#include <err.h> #include "roken.h" -RCSID("$Id: buffer.c,v 1.1 1997/05/18 19:59:24 assar Exp $"); +RCSID("$Id: buffer.c,v 1.2 1997/12/14 23:51:45 assar Exp $"); /* * Allocate a buffer enough to handle st->st_blksize, if diff --git a/crypto/kerberosIV/appl/ftp/ftp/Makefile.am b/crypto/kerberosIV/appl/ftp/ftp/Makefile.am new file mode 100644 index 0000000..081465a --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.am @@ -0,0 +1,44 @@ +# $Id: Makefile.am,v 1.12 1999/04/09 18:22:08 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += -I$(srcdir)/../common $(INCLUDE_readline) $(INCLUDE_krb4) + +bin_PROGRAMS = ftp + +CHECK_LOCAL = + +if KRB4 +krb4_sources = krb4.c kauth.c +endif +if KRB5 +krb5_sources = gssapi.c +endif + +ftp_SOURCES = \ + cmds.c \ + cmdtab.c \ + extern.h \ + ftp.c \ + ftp_locl.h \ + ftp_var.h \ + main.c \ + pathnames.h \ + ruserpass.c \ + domacro.c \ + globals.c \ + security.c \ + security.h \ + $(krb4_sources) \ + $(krb5_sources) + +EXTRA_ftp_SOURCES = krb4.c kauth.c gssapi.c + +LDADD = \ + ../common/libcommon.a \ + $(LIB_gssapi) \ + $(LIB_krb5) \ + $(LIB_krb4) \ + $(top_builddir)/lib/des/libdes.la \ + $(LIB_roken) \ + $(LIB_readline) diff --git a/crypto/kerberosIV/appl/ftp/ftp/Makefile.in b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in index 62bde3b..637d553 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/ftp/Makefile.in @@ -1,5 +1,5 @@ # -# $Id: Makefile.in,v 1.24 1997/03/23 13:03:55 assar Exp $ +# $Id: Makefile.in,v 1.32 1999/03/11 13:58:09 joda Exp $ # SHELL = /bin/sh @@ -8,13 +8,14 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -topdir = ../../.. +top_builddir = ../../.. 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@ +CFLAGS = @CFLAGS@ $(WFLAGS) +WFLAGS = @WFLAGS@ +CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir)/../common @INCLUDE_readline@ LD_FLAGS = @LD_FLAGS@ LIB_tgetent = @LIB_tgetent@ LIBS = @LIBS@ @LIB_readline@ @@ -30,17 +31,35 @@ libdir = @libdir@ transform=@program_transform_name@ EXECSUFFIX=@EXECSUFFIX@ -INCTOP = $(topdir)/include +INCTOP = $(top_builddir)/include -LIBTOP = $(topdir)/lib +LIBTOP = $(top_builddir)/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 +ftp_SOURCES = \ + cmds.c \ + cmdtab.c \ + domacro.c \ + ftp.c \ + globals.c \ + kauth.c \ + krb4.c \ + main.c \ + ruserpass.c \ + security.c + +ftp_OBJS = \ + cmds.o \ + cmdtab.o \ + domacro.o \ + ftp.o \ + globals.o \ + kauth.o \ + krb4.o \ + main.o \ + ruserpass.o \ + security.o OBJECTS = $(ftp_OBJS) SOURCES = $(ftp_SOURCES) @@ -48,29 +67,36 @@ SOURCES = $(ftp_SOURCES) all: $(PROGS) .c.o: - $(CC) -c $(CFLAGS) $(CPPFLAGS) $(DEFS) $< + $(CC) -c -I$(srcdir) -I../../../include $(DEFS) $(CFLAGS) $(CPPFLAGS) $< install: all - $(MKINSTALLDIRS) $(bindir) + $(MKINSTALLDIRS) $(DESTDIR)$(bindir) for x in $(PROGS); do \ - $(INSTALL_PROGRAM) $$x $(bindir)/`echo $$x | sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done uninstall: for x in $(PROGS); do \ - rm -f $(bindir)/`echo $$x | sed '$(transform)'`; \ + rm -f $(DESTDIR)$(bindir)/`echo $$x | sed '$(transform)'`; \ done -ftp$(EXECSUFFIX): $(ftp_OBJS) # ../common/libcommon.a +ftp$(EXECSUFFIX): $(ftp_OBJS) $(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) +TAGS: $(SOURCES) etags $(SOURCES) -clean cleandir: - rm -f *~ *.o core ftp \#* +clean: + rm -f *~ *.o core ftp$(EXECSUFFIX) \#* + +mostlyclean: clean -distclean: +distclean: clean rm -f Makefile +realclean: distclean + rm -f TAGS + $(OBJECTS): ../../../include/config.h + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/ftp/cmds.c b/crypto/kerberosIV/appl/ftp/ftp/cmds.c index 5e1980b..1571fc8 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/cmds.c +++ b/crypto/kerberosIV/appl/ftp/ftp/cmds.c @@ -36,7 +36,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: cmds.c,v 1.23 1997/06/01 22:52:37 assar Exp $"); +RCSID("$Id: cmds.c,v 1.34.2.1 1999/08/18 18:19:44 assar Exp $"); typedef void (*sighand)(int); @@ -119,12 +119,17 @@ setpeer(int argc, char **argv) /* * Set up defaults for FTP. */ - strcpy(typename, "ascii"), type = TYPE_A; + strcpy_truncate(typename, "ascii", sizeof(typename)); + 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; + strcpy_truncate(formname, "non-print", sizeof(formname)); + form = FORM_N; + strcpy_truncate(modename, "stream", sizeof(modename)); + mode = MODE_S; + strcpy_truncate(structname, "file", sizeof(structname)); + stru = STRU_F; + strcpy_truncate(bytename, "8", sizeof(bytename)); + bytesize = 8; if (autologin) login(argv[1]); @@ -165,7 +170,7 @@ setpeer(int argc, char **argv) * for text files unless changed by the user. */ type = 0; - strcpy(typename, "binary"); + strcpy_truncate(typename, "binary", sizeof(typename)); if (overbose) printf("Using %s mode to transfer files.\n", typename); @@ -238,7 +243,7 @@ settype(int argc, char **argv) else comret = command("TYPE %s", p->t_mode); if (comret == COMPLETE) { - strcpy(typename, p->t_name); + strcpy_truncate(typename, p->t_name, sizeof(typename)); curtype = type = p->t_type; } } @@ -398,7 +403,8 @@ usage: argv[2] = domap(argv[2]); } sendrequest(cmd, argv[1], argv[2], - argv[1] != oldargv1 || argv[2] != oldargv2); + curtype == TYPE_I ? "rb" : "r", + argv[1] != oldargv1 || argv[2] != oldargv2); } /* ARGSUSED */ @@ -428,133 +434,150 @@ mabort(int signo) void mput(int argc, char **argv) { - int i; - RETSIGTYPE (*oldintr)(); - int ointer; - char *tp; + 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]; + 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); + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == 0) { 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; + } + 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++; } - continue; + } + tp = tmpbuf; } - - 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; + if (ntflag) { + tp = dotrans(tp); } - 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; - } - } + if (mapflag) { + tp = domap(tp); } - globfree(&gl); + sendrequest((sunique) ? "STOU" : "STOR", + cp, tp, + curtype == TYPE_I ? "rb" : "r", + 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], + curtype == TYPE_I ? "rb" : "r", + 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, + curtype == TYPE_I ? "rb" : "r", + *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"); + getit(argc, argv, 1, curtype == TYPE_I ? "r+wb" : "r+w"); } void get(int argc, char **argv) { + char *mode; - getit(argc, argv, 0, restart_point ? "r+w" : "w" ); + if (restart_point) + if (curtype == TYPE_I) + mode = "r+wb"; + else + mode = "r+w"; + else + if (curtype == TYPE_I) + mode = "wb"; + else + mode = "w"; + + getit(argc, argv, 0, mode); } /* @@ -564,17 +587,17 @@ int getit(int argc, char **argv, int restartit, char *mode) { int loc = 0; + int local_given = 1; char *oldargv1, *oldargv2; if (argc == 2) { argc++; + local_given = 0; argv[2] = argv[1]; loc++; } - if (argc < 2 && !another(&argc, &argv, "remote-file")) - goto usage; - if (argc < 3 && !another(&argc, &argv, "local-file")) { -usage: + if ((argc < 2 && !another(&argc, &argv, "remote-file")) || + (argc < 3 && !another(&argc, &argv, "local-file"))) { printf("usage: %s remote-file [ local-file ]\n", argv[0]); code = -1; return (0); @@ -619,50 +642,60 @@ usage: 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); - } + } else if (ret == 0) { + int overbose; + int cmdret; + int yy, mo, day, hour, min, sec; + struct tm *tm; + + overbose = verbose; + if (debug == 0) + verbose = -1; + cmdret = command("MDTM %s", argv[1]); + verbose = overbose; + if (cmdret != COMPLETE) { + printf("%s\n", reply_string); + return (0); + } + if (sscanf(reply_string, + "%*s %04d%02d%02d%02d%02d%02d", + &yy, &mo, &day, &hour, &min, &sec) + != 6) { + printf ("bad MDTM result\n"); + return (0); } + + tm = gmtime(&stbuf.st_mtime); + tm->tm_mon++; + tm->tm_year += 1900; + + if ((tm->tm_year > yy) || + (tm->tm_year == yy && + 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); } } recvrequest("RETR", argv[2], argv[1], mode, - argv[1] != oldargv1 || argv[2] != oldargv2); + argv[1] != oldargv1 || argv[2] != oldargv2, local_given); restart_point = 0; return (0); } +static int +suspicious_filename(const char *fn) +{ + return strstr(fn, "../") != NULL || *fn == '/'; +} + /* * Get multiple files. */ @@ -687,6 +720,8 @@ mget(int argc, char **argv) mflag = 0; continue; } + if (mflag && suspicious_filename(cp)) + printf("*** Suspicious filename: %s\n", cp); if (mflag && confirm(argv[0], cp)) { tp = cp; if (mcase) { @@ -701,8 +736,9 @@ mget(int argc, char **argv) if (mapflag) { tp = domap(tp); } - recvrequest("RETR", tp, cp, "w", - tp != cp || !interactive); + recvrequest("RETR", tp, cp, + curtype == TYPE_I ? "wb" : "w", + tp != cp || !interactive, 0); if (!mflag && fromatty) { ointer = interactive; interactive = 1; @@ -720,61 +756,71 @@ mget(int argc, char **argv) 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; + 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 (!mflag) { if (!doglob) { - if (args == NULL) - args = argv; - if ((cp = *++args) == NULL) - args = NULL; - return (cp); + args = NULL; } - 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) { + else { + if (ftemp) { fclose(ftemp); ftemp = NULL; - return (NULL); + } } + return (NULL); + } + if (!doglob) { + if (args == NULL) + args = argv; + if ((cp = *++args) == NULL) + args = NULL; + return (cp); + } + if (ftemp == NULL) { + int fd; + strcpy_truncate(temp, _PATH_TMP_XXX, sizeof(temp)); + fd = mkstemp(temp); + if(fd < 0){ + warn("unable to create temporary file %s", temp); + return NULL; + } + close(fd); + 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, 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); + } + } + while(fgets(buf, sizeof (buf), ftemp)) { if ((cp = strchr(buf, '\n')) != NULL) - *cp = '\0'; - return (buf); + *cp = '\0'; + if(!interactive && suspicious_filename(buf)){ + printf("Ignoring remote globbed file `%s'\n", buf); + continue; + } + return buf; + } + fclose(ftemp); + ftemp = NULL; + return (NULL); } char * @@ -1036,38 +1082,38 @@ delete(int argc, char **argv) void mdelete(int argc, char **argv) { - sighand oldintr; - int ointer; - char *cp; + 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; - } + 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; + } + signal(SIGINT, oldintr); + mflag = 0; } /* @@ -1113,11 +1159,12 @@ ls(int argc, char **argv) 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); + if (!globulize(&argv[2]) || !confirm("output to local-file:", + argv[2])) { + code = -1; + return; + } + recvrequest(cmd, argv[2], argv[1], "w", 0, 1); } /* @@ -1154,7 +1201,7 @@ usage: setjmp(jabort); for (i = 1; mflag && i < argc-1; ++i) { *mode = (i == 1) ? 'w' : 'a'; - recvrequest(cmd, dest, argv[i], mode, 0); + recvrequest(cmd, dest, argv[i], mode, 0, 1); if (!mflag && fromatty) { ointer = interactive; interactive = 1; @@ -1193,8 +1240,8 @@ shell(int argc, char **argv) namep = strrchr(shell,'/'); if (namep == NULL) namep = shell; - strcpy(shellnam,"-"); - strcat(shellnam, ++namep); + snprintf (shellnam, sizeof(shellnam), + "-%s", ++namep); if (strcmp(namep, "sh") != 0) shellnam[0] = '+'; if (debug) { @@ -1369,22 +1416,19 @@ site(int argc, char **argv) void quote1(char *initial, int argc, char **argv) { - int i, len; - char buf[BUFSIZ]; /* must be >= sizeof(line) */ + int i; + 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; - } + strcpy_truncate(buf, initial, sizeof(buf)); + for(i = 1; i < argc; i++) { + if(i > 1) + strcat_truncate(buf, " ", sizeof(buf)); + strcat_truncate(buf, argv[i], sizeof(buf)); + } + if (command("%s", buf) == PRELIM) { + while (getreply(0) == PRELIM) + continue; + } } void @@ -1467,7 +1511,7 @@ disconnect(int argc, char **argv) } cout = NULL; connected = 0; - krb4_quit(); + sec_end(); data = -1; if (!proxy) { macnum = 0; @@ -1485,7 +1529,7 @@ confirm(char *cmd, char *file) fflush(stdout); if (fgets(line, sizeof line, stdin) == NULL) return (0); - return (*line != 'n' && *line != 'N'); + return (*line == 'y' || *line == 'Y'); } void @@ -1531,12 +1575,11 @@ account(int argc, char **argv) if (argc > 1) { ++argv; --argc; - strncpy(acct,*argv,49); - acct[49] = '\0'; + strcpy_truncate (acct, *argv, sizeof(acct)); while (argc > 1) { --argc; ++argv; - strncat(acct,*argv, 49-strlen(acct)); + strcat_truncate(acct, *argv, sizeof(acct)); } } else { @@ -1648,14 +1691,12 @@ setntrans(int argc, char **argv) } ntflag++; code = ntflag; - strncpy(ntin, argv[1], 16); - ntin[16] = '\0'; + strcpy_truncate (ntin, argv[1], 17); if (argc == 2) { ntout[0] = '\0'; return; } - strncpy(ntout, argv[2], 16); - ntout[16] = '\0'; + strcpy_truncate (ntout, argv[2], 17); } char * @@ -1712,10 +1753,10 @@ setnmap(int argc, char **argv) cp = strchr(altarg, ' '); } *cp = '\0'; - strncpy(mapin, altarg, MaxPathLen - 1); + strcpy_truncate(mapin, altarg, MaxPathLen); while (*++cp == ' ') continue; - strncpy(mapout, cp, MaxPathLen - 1); + strcpy_truncate(mapout, cp, MaxPathLen); } char * @@ -1967,7 +2008,9 @@ macdef(int argc, char **argv) if (interactive) { printf("Enter macro line by line, terminating it with a null line\n"); } - strncpy(macros[macnum].mac_name, argv[1], 8); + strcpy_truncate(macros[macnum].mac_name, + argv[1], + sizeof(macros[macnum].mac_name)); if (macnum == 0) { macros[macnum].mac_start = macbuf; } @@ -2067,7 +2110,7 @@ void newer(int argc, char **argv) { - if (getit(argc, argv, -1, "w")) + if (getit(argc, argv, -1, curtype == TYPE_I ? "wb" : "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 index 9567e3c..5dc96ef 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c +++ b/crypto/kerberosIV/appl/ftp/ftp/cmdtab.c @@ -105,9 +105,13 @@ char userhelp[] = "send new user information"; char verbosehelp[] = "toggle verbose mode"; char prothelp[] = "set protection level"; +#ifdef KRB4 char kauthhelp[] = "get remote tokens"; char klisthelp[] = "show remote tickets"; -char aklog[] = "obtain remote AFS tokens"; +char kdestroyhelp[] = "destroy remote tickets"; +char krbtkfilehelp[] = "set filename of remote tickets"; +char afsloghelp[] = "obtain remote AFS tokens"; +#endif struct cmd cmdtab[] = { { "!", shellhelp, 0, 0, 0, shell }, @@ -184,8 +188,13 @@ struct cmd cmdtab[] = { { "?", helphelp, 0, 0, 1, help }, { "prot", prothelp, 0, 1, 0, sec_prot }, +#ifdef KRB4 { "kauth", kauthhelp, 0, 1, 0, kauth }, { "klist", klisthelp, 0, 1, 0, klist }, + { "kdestroy", kdestroyhelp, 0, 1, 0, kdestroy }, + { "krbtkfile", krbtkfilehelp, 0, 1, 0, krbtkfile }, + { "afslog", afsloghelp, 0, 1, 0, afslog }, +#endif { 0 }, }; diff --git a/crypto/kerberosIV/appl/ftp/ftp/domacro.c b/crypto/kerberosIV/appl/ftp/ftp/domacro.c index f5a89b9..432e3e5 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/domacro.c +++ b/crypto/kerberosIV/appl/ftp/ftp/domacro.c @@ -32,7 +32,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: domacro.c,v 1.5 1996/11/17 20:23:10 assar Exp $"); +RCSID("$Id: domacro.c,v 1.6 1998/06/09 19:24:21 joda Exp $"); void domacro(int argc, char **argv) @@ -56,7 +56,7 @@ domacro(int argc, char **argv) code = -1; return; } - strcpy(line2, line); + strcpy_truncate(line2, line, sizeof(line2)); TOP: cp1 = macros[i].mac_start; while (cp1 != macros[i].mac_end) { diff --git a/crypto/kerberosIV/appl/ftp/ftp/extern.h b/crypto/kerberosIV/appl/ftp/ftp/extern.h index b830999..5efe918 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/extern.h +++ b/crypto/kerberosIV/appl/ftp/ftp/extern.h @@ -33,7 +33,7 @@ * @(#)extern.h 8.3 (Berkeley) 10/9/94 */ -/* $Id: extern.h,v 1.13 1997/04/20 05:46:48 assar Exp $ */ +/* $Id: extern.h,v 1.16 1999/05/21 09:21:51 assar Exp $ */ #include <setjmp.h> #include <stdlib.h> @@ -107,7 +107,7 @@ 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 recvrequest (char *, char *, char *, char *, int, int); void reget (int, char **); char *remglob (char **, int); void removedir (int, char **); @@ -117,7 +117,7 @@ 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 sendrequest (char *, char *, char *, char *, int); void setascii (int, char **); void setbell (int, char **); void setbinary (int, char **); @@ -165,3 +165,9 @@ extern int NCMDS; extern char username[32]; extern char myhostname[]; extern char *mydomain; + +void afslog (int, char **); +void kauth (int, char **); +void kdestroy (int, char **); +void klist (int, char **); +void krbtkfile (int, char **); diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp.c b/crypto/kerberosIV/appl/ftp/ftp/ftp.c index cfabda6..3021a19 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/ftp.c +++ b/crypto/kerberosIV/appl/ftp/ftp/ftp.c @@ -32,42 +32,38 @@ */ #include "ftp_locl.h" -RCSID("$Id: ftp.c,v 1.44 1997/05/18 20:00:31 assar Exp $"); +RCSID ("$Id: ftp.c,v 1.55 1999/06/02 20:12:22 joda 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; +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; +FILE *cin, *cout; -typedef void (*sighand)(int); +typedef void (*sighand) (int); char * -hookup(char *host, int port) +hookup (char *host, int port) { struct hostent *hp = 0; - int s, len, tos; - static char hostnamebuf[80]; + int s, len; + static char hostnamebuf[MaxHostNameLen]; - memset(&hisctladdr, 0, sizeof (hisctladdr)); - if(inet_aton(host, &hisctladdr.sin_addr)){ + memset (&hisctladdr, 0, sizeof (hisctladdr)); + if (inet_aton (host, &hisctladdr.sin_addr)) { hisctladdr.sin_family = AF_INET; - strncpy(hostnamebuf, host, sizeof(hostnamebuf)); + strcpy_truncate (hostnamebuf, host, sizeof (hostnamebuf)); } else { - hp = gethostbyname(host); + 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; } @@ -75,73 +71,75 @@ hookup(char *host, int port) 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'; + strcpy_truncate (hostnamebuf, hp->h_name, sizeof (hostnamebuf)); } hostname = hostnamebuf; - s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + s = socket (hisctladdr.sin_family, SOCK_STREAM, 0); if (s < 0) { - warn("socket"); + warn ("socket"); code = -1; return (0); } hisctladdr.sin_port = port; - while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { + 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); + ia = inet_ntoa (hisctladdr.sin_addr); errno = oerrno; - warn("connect to address %s", ia); + 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); + 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"); + warn ("socket"); code = -1; return (0); } continue; } - warn("connect"); + warn ("connect"); code = -1; goto bad; } len = sizeof (myctladdr); - if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { - warn("getsockname"); + if (getsockname (s, (struct sockaddr *) & myctladdr, &len) < 0) { + warn ("getsockname"); code = -1; goto bad; } #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) - tos = IPTOS_LOWDELAY; + { + int 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"); + cin = fdopen (s, "r"); + cout = fdopen (s, "w"); if (cin == NULL || cout == NULL) { - warnx("fdopen failed."); + warnx ("fdopen failed."); if (cin) - fclose(cin); + fclose (cin); if (cout) - fclose(cout); + fclose (cout); code = -1; goto bad; } if (verbose) - printf("Connected to %s.\n", hostname); - if (getreply(0) > 2) { /* read startup message from server */ + printf ("Connected to %s.\n", hostname); + if (getreply (0) > 2) { /* read startup message from server */ if (cin) - fclose(cin); + fclose (cin); if (cout) - fclose(cout); + fclose (cout); code = -1; goto bad; } @@ -149,21 +147,21 @@ hookup(char *host, int port) { int on = 1; - if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) + if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on)) < 0 && debug) { - warn("setsockopt"); + warn ("setsockopt"); } } -#endif /* SO_OOBINLINE */ +#endif /* SO_OOBINLINE */ return (hostname); bad: - close(s); + close (s); return NULL; } int -login(char *host) +login (char *host) { char tmp[80]; char defaultpass[128]; @@ -172,94 +170,97 @@ login(char *host) char *myname = NULL; struct passwd *pw = k_getpwuid(getuid()); + if (pw != NULL) myname = pw->pw_name; user = pass = acct = 0; - if(do_klogin(host)) + if(sec_login(host)) printf("\n*** Using plaintext user and password ***\n\n"); else{ - printf("Kerberos authentication successful.\n\n"); + printf("Authentication successful.\n\n"); } - if (ruserpass(host, &user, &pass, &acct) < 0) { + if (ruserpass (host, &user, &pass, &acct) < 0) { code = -1; return (0); } while (user == NULL) { if (myname) - printf("Name (%s:%s): ", host, myname); + printf ("Name (%s:%s): ", host, myname); else - printf("Name (%s): ", host); - fgets(tmp, sizeof(tmp) - 1, stdin); - tmp[strlen(tmp) - 1] = '\0'; + 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); + strcpy_truncate(username, user, sizeof(username)); n = command("USER %s", user); if (n == CONTINUE) { - if(auth_complete) + if(sec_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); + snprintf(defaultpass, sizeof(defaultpass), + "%s@%s", myname, mydomain); + snprintf(prompt, sizeof(prompt), + "Password (%s): ", defaultpass); }else{ - strcpy(defaultpass, ""); + *defaultpass = '\0'; snprintf(prompt, sizeof(prompt), "Password: "); } pass = defaultpass; - des_read_pw_string (tmp, sizeof(tmp), prompt, 0); - if(tmp[0]) + des_read_pw_string (tmp, sizeof (tmp), prompt, 0); + if (tmp[0]) pass = tmp; } - n = command("PASS %s", pass); + n = command ("PASS %s", pass); } if (n == CONTINUE) { aflag++; acct = tmp; - des_read_pw_string(acct, 128, "Account:", 0); - n = command("ACCT %s", acct); + des_read_pw_string (acct, 128, "Account:", 0); + n = command ("ACCT %s", acct); } if (n != COMPLETE) { - warnx("Login failed."); + warnx ("Login failed."); return (0); } if (!aflag && acct != NULL) - command("ACCT %s", acct); + command ("ACCT %s", acct); if (proxy) return (1); for (n = 0; n < macnum; ++n) { if (!strcmp("init", macros[n].mac_name)) { - strcpy(line, "$init"); + strcpy_truncate (line, "$init", sizeof (line)); makeargv(); domacro(margc, margv); break; } } - sec_set_protection_level(); + sec_set_protection_level (); return (1); } void -cmdabort(int sig) +cmdabort (int sig) { - printf("\n"); - fflush(stdout); + printf ("\n"); + fflush (stdout); abrtflag++; if (ptflag) - longjmp(ptabort,1); + longjmp (ptabort, 1); } int -command(char *fmt, ...) +command (char *fmt,...) { va_list ap; int r; @@ -267,7 +268,7 @@ command(char *fmt, ...) abrtflag = 0; if (cout == NULL) { - warn("No control connection for command"); + warn ("No control connection for command"); code = -1; return (0); } @@ -281,29 +282,26 @@ command(char *fmt, ...) vfprintf(stdout, fmt, ap); va_start(ap, fmt); } - if(auth_complete) - krb4_write_enc(cout, fmt, ap); - else - vfprintf(cout, fmt, ap); + sec_vfprintf(cout, fmt, ap); va_end(ap); if(debug){ printf("\n"); fflush(stdout); } - fprintf(cout, "\r\n"); - fflush(cout); + fprintf (cout, "\r\n"); + fflush (cout); cpend = 1; - r = getreply(!strcmp(fmt, "QUIT")); + r = getreply (!strcmp (fmt, "QUIT")); if (abrtflag && oldintr != SIG_IGN) - (*oldintr)(SIGINT); - signal(SIGINT, oldintr); + (*oldintr) (SIGINT); + signal (SIGINT, oldintr); return (r); } -char reply_string[BUFSIZ]; /* last line of previous reply */ +char reply_string[BUFSIZ]; /* last line of previous reply */ int -getreply(int expecteof) +getreply (int expecteof) { char *p; char *lead_string; @@ -311,80 +309,82 @@ getreply(int expecteof) struct sigaction sa, osa; char buf[1024]; - sigemptyset(&sa.sa_mask); + sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = cmdabort; - sigaction(SIGINT, &sa, &osa); - + sigaction (SIGINT, &sa, &osa); + p = buf; - while(1){ - c = getc(cin); - switch(c){ + while (1) { + c = getc (cin); + switch (c) { case EOF: if (expecteof) { - sigaction(SIGINT,&osa, NULL); + sigaction (SIGINT, &osa, NULL); code = 221; return 0; } - lostpeer(0); + lostpeer (0); if (verbose) { - printf("421 Service not available, " - "remote server has closed connection\n"); - fflush(stdout); + 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)); + 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; + *p++ = '\0'; if(isdigit(buf[0])){ sscanf(buf, "%d", &code); if(code == 631){ - krb4_read_mic(buf); + sec_read_msg(buf, prot_safe); sscanf(buf, "%d", &code); lead_string = "S:"; } else if(code == 632){ - krb4_read_enc(buf); + sec_read_msg(buf, prot_private); sscanf(buf, "%d", &code); lead_string = "P:"; }else if(code == 633){ - printf("Received confidential reply!\n"); - }else if(auth_complete) + sec_read_msg(buf, prot_confidential); + sscanf(buf, "%d", &code); + lead_string = "C:"; + }else if(sec_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 (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); + sigaction (SIGINT, &osa, NULL); if (code == 421) - lostpeer(0); + lostpeer (0); #if 1 - if (abrtflag && - osa.sa_handler != cmdabort && + if (abrtflag && + osa.sa_handler != cmdabort && osa.sa_handler != SIG_IGN) - osa.sa_handler(SIGINT); + osa.sa_handler (SIGINT); #endif - if(code == 227){ + if (code == 227) { char *p, *q; + pasv[0] = 0; - p = strchr(reply_string, '('); - if(p){ + p = strchr (reply_string, '('); + if (p) { p++; q = strchr(p, ')'); if(q){ - strncpy(pasv, p, q - p); + memcpy (pasv, p, q - p); pasv[q - p] = 0; } } @@ -393,7 +393,7 @@ getreply(int expecteof) } }else{ if(verbose > 0 || (verbose > -1 && code > 499)){ - if(auth_complete) + if(sec_complete) fprintf(stdout, "!!"); fprintf(stdout, "%s\n", buf); } @@ -404,13 +404,13 @@ getreply(int expecteof) *p++ = c; } } - + } #if 0 int -getreply(int expecteof) +getreply (int expecteof) { int c, n; int dig; @@ -419,24 +419,24 @@ getreply(int expecteof) int pflag = 0; char *cp, *pt = pasv; - oldintr = signal(SIGINT, cmdabort); + 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)) { + 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); + 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); + c = getc (cin); + fprintf (cout, "%c%c%c", IAC, WONT, c); + fflush (cout); break; default: break; @@ -446,14 +446,14 @@ getreply(int expecteof) dig++; if (c == EOF) { if (expecteof) { - signal(SIGINT,oldintr); + signal (SIGINT, oldintr); code = 221; return (0); } - lostpeer(0); + lostpeer (0); if (verbose) { - printf("421 Service not available, remote server has closed connection\n"); - fflush(stdout); + printf ("421 Service not available, remote server has closed connection\n"); + fflush (stdout); } code = 421; return (4); @@ -462,14 +462,14 @@ getreply(int expecteof) (verbose > -1 && n == '5' && dig > 4))) { if (proxflag && (dig == 1 || dig == 5 && verbose == 0)) - printf("%s:",hostname); - putchar(c); + printf ("%s:", hostname); + putchar (c); } - if (dig < 4 && isdigit(c)) + if (dig < 4 && isdigit (c)) code = code * 10 + (c - '0'); if (!pflag && code == 227) pflag = 1; - if (dig > 4 && pflag == 1 && isdigit(c)) + if (dig > 4 && pflag == 1 && isdigit (c)) pflag = 2; if (pflag == 2) { if (c != '\r' && c != ')') @@ -486,11 +486,11 @@ getreply(int expecteof) } if (n == 0) n = c; - if (cp < &reply_string[sizeof(reply_string) - 1]) + if (cp < &reply_string[sizeof (reply_string) - 1]) *cp++ = c; } if (verbose > 0 || verbose > -1 && n == '5') { - putchar(c); + putchar (c); fflush (stdout); } if (continuation && code != originalcode) { @@ -499,112 +499,114 @@ getreply(int expecteof) continue; } *cp = '\0'; - if(auth_complete){ + if(sec_complete){ if(code == 631) - krb4_read_mic(reply_string); - else - krb4_read_enc(reply_string); + sec_read_msg(reply_string, prot_safe); + else if(code == 632) + sec_read_msg(reply_string, prot_private); + else if(code == 633) + sec_read_msg(reply_string, prot_confidential); n = code / 100 + '0'; } - if (n != '1') cpend = 0; - signal(SIGINT,oldintr); + signal (SIGINT, oldintr); if (code == 421 || originalcode == 421) - lostpeer(0); + lostpeer (0); if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) - (*oldintr)(SIGINT); + (*oldintr) (SIGINT); return (n - '0'); } } + #endif int -empty(fd_set *mask, int sec) +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)); + return (select (32, mask, NULL, NULL, &t)); } -jmp_buf sendabort; +jmp_buf sendabort; static RETSIGTYPE -abortsend(int sig) +abortsend (int sig) { mflag = 0; abrtflag = 0; - printf("\nsend aborted\nwaiting for remote to finish abort\n"); - fflush(stdout); - longjmp(sendabort, 1); + 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) +copy_stream (FILE * from, FILE * to) { static size_t bufsize; static char *buf; int n; int bytes = 0; - int werr; + int werr = 0; int hashbytes = HASHBYTES; struct stat st; - -#ifdef HAVE_MMAP + +#if defined(HAVE_MMAP) && !defined(NO_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) { + 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) + res = sec_write (fileno (to), chunk, st.st_size); + if (munmap (chunk, st.st_size) < 0) warn ("munmap"); - sec_fflush(to); + sec_fflush (to); return res; } } #endif buf = alloc_buffer (buf, &bufsize, - fstat(fileno(from), &st) >= 0 ? &st : NULL); + 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) + 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('#'); + while (hash && bytes > hashbytes) { + putchar ('#'); hashbytes += HASHBYTES; } } - sec_fflush(to); - if(n < 0) - warn("local"); + sec_fflush (to); + if (n < 0) + warn ("local"); - if(werr < 0){ - if(errno != EPIPE) - warn("netout"); + if (werr < 0) { + if (errno != EPIPE) + warn ("netout"); bytes = -1; } return bytes; } void -sendrequest(char *cmd, char *local, char *remote, int printnames) +sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames) { struct stat st; struct timeval start, stop; @@ -613,124 +615,123 @@ sendrequest(char *cmd, char *local, char *remote, int printnames) int (*closefunc) (FILE *); RETSIGTYPE (*oldintr)(), (*oldintp)(); long bytes = 0, hashbytes = HASHBYTES; - char *lmode; + char *rmode = "w"; if (verbose && printnames) { - if (local && *local != '-') - printf("local: %s ", local); + if (local && strcmp (local, "-") != 0) + printf ("local: %s ", local); if (remote) - printf("remote: %s\n", remote); + printf ("remote: %s\n", remote); } if (proxy) { - proxtrans(cmd, local, remote); + proxtrans (cmd, local, remote); return; } if (curtype != type) - changetype(type, 0); + changetype (type, 0); closefunc = NULL; oldintr = NULL; oldintp = NULL; - lmode = "w"; - if (setjmp(sendabort)) { + + if (setjmp (sendabort)) { while (cpend) { - getreply(0); + getreply (0); } if (data >= 0) { - close(data); + close (data); data = -1; } if (oldintr) - signal(SIGINT,oldintr); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE,oldintp); + signal (SIGPIPE, oldintp); code = -1; return; } - oldintr = signal(SIGINT, abortsend); - if (strcmp(local, "-") == 0) + oldintr = signal (SIGINT, abortsend); + if (strcmp (local, "-") == 0) fin = stdin; else if (*local == '|') { - oldintp = signal(SIGPIPE,SIG_IGN); - fin = popen(local + 1, "r"); + oldintp = signal (SIGPIPE, SIG_IGN); + fin = popen (local + 1, lmode); if (fin == NULL) { - warn("%s", local + 1); - signal(SIGINT, oldintr); - signal(SIGPIPE, oldintp); + warn ("%s", local + 1); + signal (SIGINT, oldintr); + signal (SIGPIPE, oldintp); code = -1; return; } closefunc = pclose; } else { - fin = fopen(local, "r"); + fin = fopen (local, lmode); if (fin == NULL) { - warn("local: %s", local); - signal(SIGINT, oldintr); + 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); + 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 (initconn ()) { + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); code = -1; if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } - if (setjmp(sendabort)) + if (setjmp (sendabort)) goto abort; if (restart_point && - (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { + (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) { int rc; switch (curtype) { case TYPE_A: - rc = fseek(fin, (long) restart_point, SEEK_SET); + rc = fseek (fin, (long) restart_point, SEEK_SET); break; case TYPE_I: case TYPE_L: - rc = lseek(fileno(fin), restart_point, SEEK_SET); + rc = lseek (fileno (fin), restart_point, SEEK_SET); break; } if (rc < 0) { - warn("local: %s", local); + warn ("local: %s", local); restart_point = 0; if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } - if (command("REST %ld", (long) restart_point) + if (command ("REST %ld", (long) restart_point) != CONTINUE) { restart_point = 0; if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } restart_point = 0; - lmode = "r+w"; + rmode = "r+w"; } if (remote) { - if (command("%s %s", cmd, remote) != PRELIM) { - signal(SIGINT, oldintr); + if (command ("%s %s", cmd, remote) != PRELIM) { + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); if (closefunc != NULL) - (*closefunc)(fin); + (*closefunc) (fin); return; } - } else - if (command("%s", cmd) != PRELIM) { + } else if (command ("%s", cmd) != PRELIM) { signal(SIGINT, oldintr); if (oldintp) signal(SIGPIPE, oldintp); @@ -738,101 +739,102 @@ sendrequest(char *cmd, char *local, char *remote, int printnames) (*closefunc)(fin); return; } - dout = dataconn(lmode); + dout = dataconn(rmode); if (dout == NULL) goto abort; - set_buffer_size(fileno(dout), 0); - gettimeofday(&start, (struct timezone *)0); - oldintp = signal(SIGPIPE, SIG_IGN); + 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); + bytes = copy_stream (fin, dout); break; case TYPE_A: - while ((c = getc(fin)) != EOF) { + while ((c = getc (fin)) != EOF) { if (c == '\n') { while (hash && (bytes >= hashbytes)) { - putchar('#'); - fflush(stdout); + putchar ('#'); + fflush (stdout); hashbytes += HASHBYTES; } - if (ferror(dout)) + if (ferror (dout)) break; - sec_putc('\r', dout); + sec_putc ('\r', dout); bytes++; } - sec_putc(c, dout); + sec_putc (c, dout); bytes++; } - sec_fflush(dout); + sec_fflush (dout); if (hash) { if (bytes < hashbytes) - putchar('#'); - putchar('\n'); - fflush(stdout); + putchar ('#'); + putchar ('\n'); + fflush (stdout); } - if (ferror(fin)) - warn("local: %s", local); - if (ferror(dout)) { + if (ferror (fin)) + warn ("local: %s", local); + if (ferror (dout)) { if (errno != EPIPE) - warn("netout"); + warn ("netout"); bytes = -1; } break; } if (closefunc != NULL) - (*closefunc)(fin); - fclose(dout); - gettimeofday(&stop, (struct timezone *)0); - getreply(0); - signal(SIGINT, oldintr); + (*closefunc) (fin); + fclose (dout); + gettimeofday (&stop, (struct timezone *) 0); + getreply (0); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); if (bytes > 0) - ptransfer("sent", bytes, &start, &stop); + ptransfer ("sent", bytes, &start, &stop); return; abort: - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); + signal (SIGPIPE, oldintp); if (!cpend) { code = -1; return; } if (data >= 0) { - close(data); + close (data); data = -1; } if (dout) - fclose(dout); - getreply(0); + fclose (dout); + getreply (0); code = -1; if (closefunc != NULL && fin != NULL) - (*closefunc)(fin); - gettimeofday(&stop, (struct timezone *)0); + (*closefunc) (fin); + gettimeofday (&stop, (struct timezone *) 0); if (bytes > 0) - ptransfer("sent", bytes, &start, &stop); + ptransfer ("sent", bytes, &start, &stop); } -jmp_buf recvabort; +jmp_buf recvabort; void -abortrecv(int sig) +abortrecv (int sig) { mflag = 0; abrtflag = 0; - printf("\nreceive aborted\nwaiting for remote to finish abort\n"); - fflush(stdout); - longjmp(recvabort, 1); + 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) +recvrequest (char *cmd, char *local, char *remote, + char *lmode, int printnames, int local_given) { FILE *fout, *din = 0; int (*closefunc) (FILE *); @@ -844,72 +846,71 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) struct timeval start, stop; struct stat st; - is_retr = strcmp(cmd, "RETR") == 0; + is_retr = strcmp (cmd, "RETR") == 0; if (is_retr && verbose && printnames) { - if (local && *local != '-') - printf("local: %s ", local); + if (local && strcmp (local, "-") != 0) + printf ("local: %s ", local); if (remote) - printf("remote: %s\n", remote); + printf ("remote: %s\n", remote); } if (proxy && is_retr) { - proxtrans(cmd, local, remote); + proxtrans (cmd, local, remote); return; } closefunc = NULL; oldintr = NULL; oldintp = NULL; tcrflag = !crflag && is_retr; - if (setjmp(recvabort)) { + if (setjmp (recvabort)) { while (cpend) { - getreply(0); + getreply (0); } if (data >= 0) { - close(data); + close (data); data = -1; } if (oldintr) - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); code = -1; return; } - oldintr = signal(SIGINT, abortrecv); - if (strcmp(local, "-") && *local != '|') { - if (access(local, 2) < 0) { - char *dir = strrchr(local, '/'); + oldintr = signal (SIGINT, abortrecv); + if (!local_given || (strcmp (local, "-") && *local != '|')) { + if (access (local, 2) < 0) { + char *dir = strrchr (local, '/'); if (errno != ENOENT && errno != EACCES) { - warn("local: %s", local); - signal(SIGINT, oldintr); + warn ("local: %s", local); + signal (SIGINT, oldintr); code = -1; return; } if (dir != NULL) *dir = 0; - d = access(dir ? local : ".", 2); + d = access (dir ? local : ".", 2); if (dir != NULL) *dir = '/'; if (d < 0) { - warn("local: %s", local); - signal(SIGINT, oldintr); + 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); + 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); + (local = gunique (local)) == NULL) { + signal (SIGINT, oldintr); code = -1; return; } - } - else if (runique && (local = gunique(local)) == NULL) { + } else if (runique && (local = gunique (local)) == NULL) { signal(SIGINT, oldintr); code = -1; return; @@ -917,98 +918,98 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) } if (!is_retr) { if (curtype != TYPE_A) - changetype(TYPE_A, 0); + changetype (TYPE_A, 0); } else if (curtype != type) - changetype(type, 0); - if (initconn()) { - signal(SIGINT, oldintr); + changetype (type, 0); + if (initconn ()) { + signal (SIGINT, oldintr); code = -1; return; } - if (setjmp(recvabort)) + if (setjmp (recvabort)) goto abort; if (is_retr && restart_point && - command("REST %ld", (long) restart_point) != CONTINUE) + command ("REST %ld", (long) restart_point) != CONTINUE) return; if (remote) { - if (command("%s %s", cmd, remote) != PRELIM) { - signal(SIGINT, oldintr); + if (command ("%s %s", cmd, remote) != PRELIM) { + signal (SIGINT, oldintr); return; } } else { - if (command("%s", cmd) != PRELIM) { - signal(SIGINT, oldintr); + if (command ("%s", cmd) != PRELIM) { + signal (SIGINT, oldintr); return; } } - din = dataconn("r"); + din = dataconn ("r"); if (din == NULL) goto abort; - set_buffer_size(fileno(din), 1); - if (strcmp(local, "-") == 0) + set_buffer_size (fileno (din), 1); + if (local_given && strcmp (local, "-") == 0) fout = stdout; - else if (*local == '|') { - oldintp = signal(SIGPIPE, SIG_IGN); - fout = popen(local + 1, "w"); + else if (local_given && *local == '|') { + oldintp = signal (SIGPIPE, SIG_IGN); + fout = popen (local + 1, "w"); if (fout == NULL) { - warn("%s", local+1); + warn ("%s", local + 1); goto abort; } closefunc = pclose; } else { - fout = fopen(local, lmode); + fout = fopen (local, lmode); if (fout == NULL) { - warn("local: %s", local); + warn ("local: %s", local); goto abort; } closefunc = fclose; } buf = alloc_buffer (buf, &bufsize, - fstat(fileno(fout), &st) >= 0 ? &st : NULL); + fstat (fileno (fout), &st) >= 0 ? &st : NULL); if (buf == NULL) goto abort; - gettimeofday(&start, (struct timezone *)0); + 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); + lseek (fileno (fout), restart_point, SEEK_SET) < 0) { + warn ("local: %s", local); if (closefunc != NULL) - (*closefunc)(fout); + (*closefunc) (fout); return; } errno = d = 0; - while ((c = sec_read(fileno(din), buf, bufsize)) > 0) { - if ((d = write(fileno(fout), buf, c)) != c) + 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('#'); + putchar ('#'); hashbytes += HASHBYTES; } - fflush(stdout); + fflush (stdout); } } if (hash && bytes > 0) { if (bytes < HASHBYTES) - putchar('#'); - putchar('\n'); - fflush(stdout); + putchar ('#'); + putchar ('\n'); + fflush (stdout); } if (c < 0) { if (errno != EPIPE) - warn("netin"); + warn ("netin"); bytes = -1; } if (d < c) { if (d < 0) - warn("local: %s", local); + warn ("local: %s", local); else - warnx("%s: short write", local); + warnx ("%s: short write", local); } break; @@ -1016,38 +1017,37 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) if (restart_point) { int i, n, ch; - if (fseek(fout, 0L, SEEK_SET) < 0) + if (fseek (fout, 0L, SEEK_SET) < 0) goto done; n = restart_point; for (i = 0; i++ < n;) { - if ((ch = sec_getc(fout)) == EOF) + 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 (fseek (fout, 0L, SEEK_CUR) < 0) { + done: + warn ("local: %s", local); if (closefunc != NULL) - (*closefunc)(fout); + (*closefunc) (fout); return; } } - while ((c = sec_getc(din)) != EOF) { if (c == '\n') bare_lfs++; while (c == '\r') { while (hash && (bytes >= hashbytes)) { - putchar('#'); - fflush(stdout); + putchar ('#'); + fflush (stdout); hashbytes += HASHBYTES; } bytes++; - if ((c = sec_getc(din)) != '\n' || tcrflag) { - if (ferror(fout)) + if ((c = sec_getc (din)) != '\n' || tcrflag) { + if (ferror (fout)) goto break2; - putc('\r', fout); + putc ('\r', fout); if (c == '\0') { bytes++; goto contin2; @@ -1056,69 +1056,68 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames) goto contin2; } } - putc(c, fout); + putc (c, fout); bytes++; - contin2: ; + contin2:; } - break2: +break2: if (bare_lfs) { - printf("WARNING! %d bare linefeeds received in ASCII mode\n", - bare_lfs); - printf("File may not have transferred correctly.\n"); + 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); + putchar ('#'); + putchar ('\n'); + fflush (stdout); } - if (ferror(din)) { + if (ferror (din)) { if (errno != EPIPE) - warn("netin"); + warn ("netin"); bytes = -1; } - if (ferror(fout)) - warn("local: %s", local); + if (ferror (fout)) + warn ("local: %s", local); break; } if (closefunc != NULL) - (*closefunc)(fout); - signal(SIGINT, oldintr); + (*closefunc) (fout); + signal (SIGINT, oldintr); if (oldintp) - signal(SIGPIPE, oldintp); - fclose(din); - gettimeofday(&stop, (struct timezone *)0); - getreply(0); + signal (SIGPIPE, oldintp); + fclose (din); + gettimeofday (&stop, (struct timezone *) 0); + getreply (0); if (bytes > 0 && is_retr) - ptransfer("received", bytes, &start, &stop); + ptransfer ("received", bytes, &start, &stop); return; abort: /* abort using RFC959 recommended IP,SYNC sequence */ if (oldintp) - signal(SIGPIPE, oldintr); - signal(SIGINT, SIG_IGN); + signal (SIGPIPE, oldintr); + signal (SIGINT, SIG_IGN); if (!cpend) { code = -1; - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); return; } - abort_remote(din); code = -1; if (data >= 0) { - close(data); + close (data); data = -1; } if (closefunc != NULL && fout != NULL) - (*closefunc)(fout); + (*closefunc) (fout); if (din) - fclose(din); - gettimeofday(&stop, (struct timezone *)0); + fclose (din); + gettimeofday (&stop, (struct timezone *) 0); if (bytes > 0) - ptransfer("received", bytes, &start, &stop); - signal(SIGINT, oldintr); + ptransfer ("received", bytes, &start, &stop); + signal (SIGINT, oldintr); } /* @@ -1126,112 +1125,110 @@ abort: * otherwise the server's connect may fail. */ int -initconn(void) +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); + data = socket (AF_INET, SOCK_STREAM, 0); if (data < 0) { - perror("ftp: socket"); - return(1); + 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)"); + 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"); + 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. + * 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"); + 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"); + 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); + 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"); + 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)"); + if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, + sizeof (int)) < 0) + perror ("ftp: setsockopt TOS (ignored)"); #endif - return(0); + return (0); } - noport: data_addr = myctladdr; if (sendport) - data_addr.sin_port = 0; /* let system pick one */ + data_addr.sin_port = 0; /* let system pick one */ if (data != -1) - close(data); - data = socket(AF_INET, SOCK_STREAM, 0); + close (data); + data = socket (AF_INET, SOCK_STREAM, 0); if (data < 0) { - warn("socket"); + 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)"); + 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"); + 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)"); + 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"); + if (getsockname (data, (struct sockaddr *) & data_addr, &len) < 0) { + warn ("getsockname"); goto bad; } - if (listen(data, 1) < 0) - warn("listen"); + 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, @@ -1250,88 +1247,88 @@ noport: 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)"); + if (setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, sizeof (int)) < 0) + warn ("setsockopt TOS (ignored)"); #endif return (0); bad: - close(data), data = -1; + close (data), data = -1; if (tmpno) sendport = 1; return (1); } FILE * -dataconn(char *lmode) +dataconn (char *lmode) { struct sockaddr_in from; int s, fromlen = sizeof (from), tos; if (passivemode) - return (fdopen(data, lmode)); + return (fdopen (data, lmode)); - s = accept(data, (struct sockaddr *) &from, &fromlen); + s = accept (data, (struct sockaddr *) & from, &fromlen); if (s < 0) { - warn("accept"); - close(data), data = -1; + warn ("accept"); + close (data), data = -1; return (NULL); } - close(data); + 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)"); + if (setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0) + warn ("setsockopt TOS (ignored)"); #endif - return (fdopen(data, lmode)); + return (fdopen (data, lmode)); } void -ptransfer(char *direction, long int bytes, - struct timeval *t0, struct timeval *t1) +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){ + 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 = bytes / (s ? s : 1); + if (bs >= 1048576) { bs /= 1048576; unit = "M"; prec = 2; - }else if(bs >= 1024){ + } else if (bs >= 1024) { bs /= 1024; unit = "k"; prec = 1; - }else{ + } else { unit = ""; prec = 0; } - - printf("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n", - bytes, direction, s, prec, bs, unit); + + printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n", + bytes, direction, s, prec, bs, unit); } } void -psabort(int sig) +psabort (int sig) { abrtflag++; } void -pswitch(int flag) +pswitch (int flag) { sighand oldintr; static struct comvars { @@ -1357,7 +1354,7 @@ pswitch(int flag) struct comvars *ip, *op; abrtflag = 0; - oldintr = signal(SIGINT, psabort); + oldintr = signal (SIGINT, psabort); if (flag) { if (proxy) return; @@ -1374,8 +1371,7 @@ pswitch(int flag) ip->connect = connected; connected = op->connect; if (hostname) { - strncpy(ip->name, hostname, sizeof(ip->name) - 1); - ip->name[strlen(ip->name)] = '\0'; + strcpy_truncate (ip->name, hostname, sizeof (ip->name)); } else ip->name[0] = 0; hostname = op->name; @@ -1401,48 +1397,44 @@ pswitch(int flag) 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); + strcpy_truncate (ip->nti, ntin, sizeof (ip->nti)); + strcpy_truncate (ntin, op->nti, 17); + strcpy_truncate (ip->nto, ntout, sizeof (ip->nto)); + strcpy_truncate (ntout, op->nto, 17); 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); + strcpy_truncate (ip->mi, mapin, MaxPathLen); + strcpy_truncate (mapin, op->mi, MaxPathLen); + strcpy_truncate (ip->mo, mapout, MaxPathLen); + strcpy_truncate (mapout, op->mo, MaxPathLen); signal(SIGINT, oldintr); if (abrtflag) { abrtflag = 0; - (*oldintr)(SIGINT); + (*oldintr) (SIGINT); } } void -abortpt(int sig) +abortpt (int sig) { - printf("\n"); - fflush(stdout); + printf ("\n"); + fflush (stdout); ptabflg++; mflag = 0; abrtflag = 0; - longjmp(ptabort, 1); + longjmp (ptabort, 1); } void -proxtrans(char *cmd, char *local, char *remote) +proxtrans (char *cmd, char *local, char *remote) { sighand oldintr; int secndflag = 0, prox_type, nfnd; char *cmd2; fd_set mask; - if (strcmp(cmd, "RETR")) + if (strcmp (cmd, "RETR")) cmd2 = "RETR"; else cmd2 = runique ? "STOU" : "STOR"; @@ -1453,148 +1445,147 @@ proxtrans(char *cmd, char *local, char *remote) 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"); + changetype (prox_type, 1); + if (command ("PASV") != COMPLETE) { + printf ("proxy server does not support third party transfers.\n"); return; } - pswitch(0); + pswitch (0); if (!connected) { - printf("No primary connection\n"); - pswitch(1); + 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); + changetype (prox_type, 1); + if (command ("PORT %s", pasv) != COMPLETE) { + pswitch (1); return; } - if (setjmp(ptabort)) + if (setjmp (ptabort)) goto abort; - oldintr = signal(SIGINT, abortpt); - if (command("%s %s", cmd, remote) != PRELIM) { - signal(SIGINT, oldintr); - pswitch(1); + oldintr = signal (SIGINT, abortpt); + if (command ("%s %s", cmd, remote) != PRELIM) { + signal (SIGINT, oldintr); + pswitch (1); return; } - sleep(2); - pswitch(1); + sleep (2); + pswitch (1); secndflag++; - if (command("%s %s", cmd2, local) != PRELIM) + if (command ("%s %s", cmd2, local) != PRELIM) goto abort; ptflag++; - getreply(0); - pswitch(0); - getreply(0); - signal(SIGINT, oldintr); - pswitch(1); + getreply (0); + pswitch (0); + getreply (0); + signal (SIGINT, oldintr); + pswitch (1); ptflag = 0; - printf("local: %s remote: %s\n", local, remote); + printf ("local: %s remote: %s\n", local, remote); return; abort: - signal(SIGINT, SIG_IGN); + 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 (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); + abort_remote ((FILE *) NULL); } - pswitch(1); + pswitch (1); if (ptabflg) code = -1; - signal(SIGINT, oldintr); + 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); + 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); + abort_remote ((FILE *) NULL); + pswitch (1); if (ptabflg) code = -1; - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); return; } } if (cpend) - abort_remote((FILE *) NULL); - pswitch(!proxy); + abort_remote ((FILE *) NULL); + pswitch (!proxy); if (cpend) { - FD_ZERO(&mask); - FD_SET(fileno(cin), &mask); - if ((nfnd = empty(&mask, 10)) <= 0) { + FD_ZERO (&mask); + FD_SET (fileno (cin), &mask); + if ((nfnd = empty (&mask, 10)) <= 0) { if (nfnd < 0) { - warn("abort"); + warn ("abort"); } if (ptabflg) code = -1; - lostpeer(0); + lostpeer (0); } - getreply(0); - getreply(0); + getreply (0); + getreply (0); } if (proxy) - pswitch(0); - pswitch(1); + pswitch (0); + pswitch (1); if (ptabflg) code = -1; - signal(SIGINT, oldintr); + signal (SIGINT, oldintr); } void -reset(int argc, char **argv) +reset (int argc, char **argv) { fd_set mask; int nfnd = 1; - FD_ZERO(&mask); + FD_ZERO (&mask); while (nfnd > 0) { - FD_SET(fileno(cin), &mask); - if ((nfnd = empty(&mask,0)) < 0) { - warn("reset"); + FD_SET (fileno (cin), &mask); + if ((nfnd = empty (&mask, 0)) < 0) { + warn ("reset"); code = -1; lostpeer(0); - } - else if (nfnd) { + } else if (nfnd) { getreply(0); } } } char * -gunique(char *local) +gunique (char *local) { static char new[MaxPathLen]; - char *cp = strrchr(local, '/'); - int d, count=0; + char *cp = strrchr (local, '/'); + int d, count = 0; char ext = '1'; if (cp) *cp = '\0'; - d = access(cp ? local : ".", 2); + d = access (cp ? local : ".", 2); if (cp) *cp = '/'; if (d < 0) { - warn("local: %s", local); + warn ("local: %s", local); return NULL; } - strcpy(new, local); + strcpy_truncate (new, local, sizeof(new)); cp = new + strlen(new); *cp++ = '.'; while (!d) { if (++count == 100) { - printf("runique: can't find unique file name.\n"); + printf ("runique: can't find unique file name.\n"); return NULL; } *cp++ = ext; @@ -1603,7 +1594,7 @@ gunique(char *local) ext = '0'; else ext++; - if ((d = access(new, 0)) < 0) + if ((d = access (new, 0)) < 0) break; if (ext != '0') cp--; @@ -1618,7 +1609,7 @@ gunique(char *local) } void -abort_remote(FILE *din) +abort_remote (FILE * din) { char buf[BUFSIZ]; int nfnd; @@ -1628,31 +1619,31 @@ abort_remote(FILE *din) * 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) { + 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"); + warn ("abort"); } if (ptabflg) code = -1; - lostpeer(0); + lostpeer (0); } - if (din && FD_ISSET(fileno(din), &mask)) { - while (read(fileno(din), buf, BUFSIZ) > 0) - /* LOOP */; + if (din && FD_ISSET (fileno (din), &mask)) { + while (read (fileno (din), buf, BUFSIZ) > 0) + /* LOOP */ ; } - if (getreply(0) == ERROR && code == 552) { + if (getreply (0) == ERROR && code == 552) { /* 552 needed for nic style abort */ - getreply(0); + getreply (0); } - getreply(0); + getreply (0); } diff --git a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h index 6ead793..5ae44b1 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h +++ b/crypto/kerberosIV/appl/ftp/ftp/ftp_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,7 +36,7 @@ * SUCH DAMAGE. */ -/* $Id: ftp_locl.h,v 1.29 1997/05/20 18:40:28 bg Exp $ */ +/* $Id: ftp_locl.h,v 1.33 1998/06/13 00:06:40 assar Exp $ */ #ifndef __FTP_LOCL_H__ #define __FTP_LOCL_H__ @@ -45,8 +45,6 @@ #include <config.h> #endif -#include <sys/cdefs.h> - #ifdef HAVE_PWD_H #include <pwd.h> #endif @@ -121,7 +119,12 @@ #ifdef SOCKS #include <socks.h> -extern int LIBPREFIX(fclose) __P((FILE *)); +extern int LIBPREFIX(fclose) (FILE *); + +/* This doesn't belong here. */ +struct tm *localtime(const time_t *); +struct hostent *gethostbyname(const char *); + #endif #include "ftp_var.h" @@ -129,13 +132,9 @@ extern int LIBPREFIX(fclose) __P((FILE *)); #include "common.h" #include "pathnames.h" -#include <des.h> - -#include <krb.h> - -#include "krb4.h" - #include "roken.h" +#include "security.h" +#include <des.h> /* for des_read_pw_string */ #if defined(__sun__) && !defined(__svr4) int fclose(FILE*); diff --git a/crypto/kerberosIV/appl/ftp/ftp/gssapi.c b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c new file mode 100644 index 0000000..bc001a4 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/gssapi.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 1998, 1999 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 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 FTP_SERVER +#include "ftpd_locl.h" +#else +#include "ftp_locl.h" +#endif +#include <gssapi.h> + +RCSID("$Id: gssapi.c,v 1.7 1999/04/10 15:08:39 assar Exp $"); + +struct gss_data { + gss_ctx_id_t context_hdl; + char *client_name; +}; + +static int +gss_init(void *app_data) +{ + struct gss_data *d = app_data; + d->context_hdl = GSS_C_NO_CONTEXT; + return 0; +} + +static int +gss_check_prot(void *app_data, int level) +{ + if(level == prot_confidential) + return -1; + return 0; +} + +static int +gss_decode(void *app_data, void *buf, int len, int level) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc input, output; + gss_qop_t qop_state; + int conf_state; + struct gss_data *d = app_data; + + input.length = len; + input.value = buf; + maj_stat = gss_unwrap (&min_stat, + d->context_hdl, + &input, + &output, + &conf_state, + &qop_state); + if(GSS_ERROR(maj_stat)) + return -1; + memmove(buf, output.value, output.length); + return output.length; +} + +static int +gss_overhead(void *app_data, int level, int len) +{ + return 100; /* dunno? */ +} + + +static int +gss_encode(void *app_data, void *from, int length, int level, void **to) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc input, output; + int conf_state; + struct gss_data *d = app_data; + + input.length = length; + input.value = from; + maj_stat = gss_wrap (&min_stat, + d->context_hdl, + level == prot_private, + GSS_C_QOP_DEFAULT, + &input, + &conf_state, + &output); + *to = output.value; + return output.length; +} + +/* end common stuff */ + +#ifdef FTP_SERVER + +static int +gss_adat(void *app_data, void *buf, size_t len) +{ + char *p = NULL; + gss_buffer_desc input_token, output_token; + OM_uint32 maj_stat, min_stat; + gss_name_t client_name; + struct gss_data *d = app_data; + + gss_channel_bindings_t bindings = malloc(sizeof(*bindings)); + bindings->initiator_addrtype = GSS_C_AF_INET; + bindings->initiator_address.length = 4; + bindings->initiator_address.value = &his_addr.sin_addr; + bindings->acceptor_addrtype = GSS_C_AF_INET; + bindings->acceptor_address.length = 4; + bindings->acceptor_address.value = &ctrl_addr.sin_addr; + bindings->application_data.length = 0; + bindings->application_data.value = NULL; + + input_token.value = buf; + input_token.length = len; + + maj_stat = gss_accept_sec_context (&min_stat, + &d->context_hdl, + GSS_C_NO_CREDENTIAL, + &input_token, + bindings, + &client_name, + NULL, + &output_token, + NULL, + NULL, + NULL); + + if(output_token.length) { + if(base64_encode(output_token.value, output_token.length, &p) < 0) { + reply(535, "Out of memory base64-encoding."); + return -1; + } + } + if(maj_stat == GSS_S_COMPLETE){ + char *name; + gss_buffer_desc export_name; + maj_stat = gss_export_name(&min_stat, client_name, &export_name); + if(maj_stat != 0) { + reply(500, "Error exporting name"); + goto out; + } + name = realloc(export_name.value, export_name.length + 1); + if(name == NULL) { + reply(500, "Out of memory"); + free(export_name.value); + goto out; + } + name[export_name.length] = '\0'; + d->client_name = name; + if(p) + reply(235, "ADAT=%s", p); + else + reply(235, "ADAT Complete"); + sec_complete = 1; + + } else if(maj_stat == GSS_S_CONTINUE_NEEDED) { + if(p) + reply(335, "ADAT=%s", p); + else + reply(335, "OK, need more data"); + } else + reply(535, "foo?"); +out: + free(p); + return 0; +} + +int gss_userok(void*, char*); + +struct sec_server_mech gss_server_mech = { + "GSSAPI", + sizeof(struct gss_data), + gss_init, /* init */ + NULL, /* end */ + gss_check_prot, + gss_overhead, + gss_encode, + gss_decode, + /* */ + NULL, + gss_adat, + NULL, /* pbsz */ + NULL, /* ccc */ + gss_userok +}; + +#else /* FTP_SERVER */ + +extern struct sockaddr_in hisctladdr, myctladdr; + +static int +gss_auth(void *app_data, char *host) +{ + + OM_uint32 maj_stat, min_stat; + gss_buffer_desc name; + gss_name_t target_name; + gss_buffer_desc input, output_token; + int context_established = 0; + char *p; + int n; + gss_channel_bindings_t bindings; + struct gss_data *d = app_data; + + name.length = asprintf((char**)&name.value, "ftp@%s", host); + maj_stat = gss_import_name(&min_stat, + &name, + GSS_C_NT_HOSTBASED_SERVICE, + &target_name); + free(name.value); + + + input.length = 0; + input.value = NULL; + + bindings = malloc(sizeof(*bindings)); + bindings->initiator_addrtype = GSS_C_AF_INET; + bindings->initiator_address.length = 4; + bindings->initiator_address.value = &myctladdr.sin_addr; + bindings->acceptor_addrtype = GSS_C_AF_INET; + bindings->acceptor_address.length = 4; + bindings->acceptor_address.value = &hisctladdr.sin_addr; + bindings->application_data.length = 0; + bindings->application_data.value = NULL; + + while(!context_established) { + maj_stat = gss_init_sec_context(&min_stat, + GSS_C_NO_CREDENTIAL, + &d->context_hdl, + target_name, + GSS_C_NO_OID, + GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG, + 0, + bindings, + &input, + NULL, + &output_token, + NULL, + NULL); + if (GSS_ERROR(maj_stat)) { + int new_stat; + int msg_ctx = 0; + gss_buffer_desc status_string; + + gss_display_status(&new_stat, + min_stat, + GSS_C_MECH_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + printf("Error initializing security context: %s\n", + (char*)status_string.value); + gss_release_buffer(&new_stat, &status_string); + return AUTH_CONTINUE; + } + + gss_release_buffer(&min_stat, &input); + if (output_token.length != 0) { + base64_encode(output_token.value, output_token.length, &p); + gss_release_buffer(&min_stat, &output_token); + n = command("ADAT %s", p); + free(p); + } + if (GSS_ERROR(maj_stat)) { + if (d->context_hdl != GSS_C_NO_CONTEXT) + gss_delete_sec_context (&min_stat, + &d->context_hdl, + GSS_C_NO_BUFFER); + break; + } + if (maj_stat & GSS_S_CONTINUE_NEEDED) { + p = strstr(reply_string, "ADAT="); + if(p == NULL){ + printf("Error: expected ADAT in reply.\n"); + return AUTH_ERROR; + } else { + p+=5; + input.value = malloc(strlen(p)); + input.length = base64_decode(p, input.value); + } + } else { + if(code != 235) { + printf("Unrecognized response code: %d\n", code); + return AUTH_ERROR; + } + context_established = 1; + } + } + return AUTH_OK; +} + +struct sec_client_mech gss_client_mech = { + "GSSAPI", + sizeof(struct gss_data), + gss_init, + gss_auth, + NULL, /* end */ + gss_check_prot, + gss_overhead, + gss_encode, + gss_decode, +}; + +#endif /* FTP_SERVER */ diff --git a/crypto/kerberosIV/appl/ftp/ftp/kauth.c b/crypto/kerberosIV/appl/ftp/ftp/kauth.c index 8bc9b9b..434dfb8 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/kauth.c +++ b/crypto/kerberosIV/appl/ftp/ftp/kauth.c @@ -37,9 +37,11 @@ */ #include "ftp_locl.h" -RCSID("$Id: kauth.c,v 1.14 1997/05/11 04:08:04 assar Exp $"); +#include <krb.h> +RCSID("$Id: kauth.c,v 1.17 1998/03/26 02:55:38 joda Exp $"); -void kauth(int argc, char **argv) +void +kauth(int argc, char **argv) { int ret; char buf[1024]; @@ -120,7 +122,11 @@ void kauth(int argc, char **argv) memset(key, 0, sizeof(key)); memset(schedule, 0, sizeof(schedule)); memset(passwd, 0, sizeof(passwd)); - base64_encode(tktcopy.dat, tktcopy.length, &p); + if(base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) { + printf("Out of memory base64-encoding.\n"); + code = -1; + return; + } memset (tktcopy.dat, 0, tktcopy.length); ret = command("SITE KAUTH %s %s", name, p); free(p); @@ -131,7 +137,8 @@ void kauth(int argc, char **argv) code = 0; } -void klist(int argc, char **argv) +void +klist(int argc, char **argv) { int ret; if(argc != 1){ @@ -143,3 +150,45 @@ void klist(int argc, char **argv) ret = command("SITE KLIST"); code = (ret == COMPLETE); } + +void +kdestroy(int argc, char **argv) +{ + int ret; + if (argc != 1) { + printf("usage: %s\n", argv[0]); + code = -1; + return; + } + ret = command("SITE KDESTROY"); + code = (ret == COMPLETE); +} + +void +krbtkfile(int argc, char **argv) +{ + int ret; + if(argc != 2) { + printf("usage: %s tktfile\n", argv[0]); + code = -1; + return; + } + ret = command("SITE KRBTKFILE %s", argv[1]); + code = (ret == COMPLETE); +} + +void +afslog(int argc, char **argv) +{ + int ret; + if(argc > 2) { + printf("usage: %s [cell]\n", argv[0]); + code = -1; + return; + } + if(argc == 2) + ret = command("SITE AFSLOG %s", argv[1]); + else + ret = command("SITE AFSLOG"); + code = (ret == COMPLETE); +} diff --git a/crypto/kerberosIV/appl/ftp/ftp/krb4.c b/crypto/kerberosIV/appl/ftp/ftp/krb4.c index 872c5bc..5b9b9b8 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/krb4.c +++ b/crypto/kerberosIV/appl/ftp/ftp/krb4.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,532 +36,260 @@ * SUCH DAMAGE. */ +#ifdef FTP_SERVER +#include "ftpd_locl.h" +#else #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" } +#endif +#include <krb.h> + +RCSID("$Id: krb4.c,v 1.30 1999/06/15 03:50:28 assar Exp $"); + +#ifdef FTP_SERVER +#define LOCAL_ADDR ctrl_addr +#define REMOTE_ADDR his_addr +#else +#define LOCAL_ADDR myctladdr +#define REMOTE_ADDR hisctladdr +#endif +extern struct sockaddr_in LOCAL_ADDR, REMOTE_ADDR; + +struct krb4_data { + des_cblock key; + des_key_schedule schedule; + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; }; -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) +krb4_check_prot(void *app_data, 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"); + if(level == prot_confidential) 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) +static int +krb4_decode(void *app_data, void *buf, int len, int level) { - 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; - } + MSG_DAT m; + int e; + struct krb4_data *d = app_data; - 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); + if(level == prot_safe) + e = krb_rd_safe(buf, len, &d->key, &REMOTE_ADDR, &LOCAL_ADDR, &m); else - return getc(F); + e = krb_rd_priv(buf, len, d->schedule, &d->key, + &REMOTE_ADDR, &LOCAL_ADDR, &m); + if(e){ + return -1; + } + memmove(buf, m.app_data, m.app_length); + return m.app_length; } -int sec_read(int fd, void *data, int length) +static int +krb4_overhead(void *app_data, int level, int len) { - if(auth_complete && data_prot) - return krb4_read(fd, data, length); - else - return read(fd, data, length); + return 31; } static int -krb4_recv(int fd) +krb4_encode(void *app_data, void *from, int length, int level, void **to) { - 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); + struct krb4_data *d = app_data; + *to = malloc(length + 31); + if(level == prot_safe) + return krb_mk_safe(from, *to, length, &d->key, + &LOCAL_ADDR, &REMOTE_ADDR); + else if(level == prot_private) + return krb_mk_priv(from, *to, length, d->schedule, &d->key, + &LOCAL_ADDR, &REMOTE_ADDR); 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; } +#ifdef FTP_SERVER -int krb4_getc(FILE *F) +static int +krb4_adat(void *app_data, void *buf, size_t len) { - 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++]; + KTEXT_ST tkt; + AUTH_DAT auth_dat; + char *p; + int kerror; + u_int32_t cs; + char msg[35]; /* size of encrypted block */ + int tmp_len; + struct krb4_data *d = app_data; + char inst[INST_SZ]; + + memcpy(tkt.dat, buf, len); + tkt.length = len; + + k_getsockinst(0, inst, sizeof(inst)); + kerror = krb_rd_req(&tkt, "ftp", inst, + his_addr.sin_addr.s_addr, &auth_dat, ""); + if(kerror == RD_AP_UNDEC){ + k_getsockinst(0, inst, sizeof(inst)); + kerror = krb_rd_req(&tkt, "rcmd", inst, + his_addr.sin_addr.s_addr, &auth_dat, ""); } - 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(kerror){ + reply(535, "Error reading request: %s.", krb_get_err_text(kerror)); + return -1; } - if(left){ - if(length < len) - len = length; - memmove(data, data_buffer + index, len); - length -= len; - index += len; - rx += len; - left -= len; + memcpy(d->key, auth_dat.session, sizeof(d->key)); + des_set_key(&d->key, d->schedule); + + strcpy_truncate(d->name, auth_dat.pname, sizeof(d->name)); + strcpy_truncate(d->instance, auth_dat.pinst, sizeof(d->instance)); + strcpy_truncate(d->realm, auth_dat.prealm, sizeof(d->instance)); + + cs = auth_dat.checksum + 1; + { + unsigned char tmp[4]; + KRB_PUT_INT(cs, tmp, 4, sizeof(tmp)); + tmp_len = krb_mk_safe(tmp, msg, 4, &d->key, &LOCAL_ADDR, &REMOTE_ADDR); } - - 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; + if(tmp_len < 0){ + reply(535, "Error creating reply: %s.", strerror(errno)); + return -1; } - 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; + len = tmp_len; + if(base64_encode(msg, len, &p) < 0) { + reply(535, "Out of memory base64-encoding."); + return -1; } - return putc(c, F); + reply(235, "ADAT=%s", p); + sec_complete = 1; + free(p); + return 0; } static int -sec_send(int fd, char *from, int length) +krb4_userok(void *app_data, char *user) { - 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; + struct krb4_data *d = app_data; + return krb_kuserok(d->name, d->instance, d->realm, user); } -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; -} +struct sec_server_mech krb4_server_mech = { + "KERBEROS_V4", + sizeof(struct krb4_data), + NULL, /* init */ + NULL, /* end */ + krb4_check_prot, + krb4_overhead, + krb4_encode, + krb4_decode, + /* */ + NULL, + krb4_adat, + NULL, /* pbsz */ + NULL, /* ccc */ + krb4_userok +}; -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; -} +#else /* FTP_SERVER */ static int -do_auth(char *service, char *host, int checksum) +mk_auth(struct krb4_data *d, KTEXT adat, + 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); + + strcpy_truncate(sname, service, sizeof(sname)); + strcpy_truncate(inst, krb_get_phost(host), sizeof(inst)); + strcpy_truncate(realm, krb_realmofhost(host), sizeof(realm)); + ret = krb_mk_req(adat, sname, inst, realm, checksum); if(ret) return ret; - strcpy(sname, service); - strcpy(inst, krb_get_phost(host)); - strcpy(realm, krb_realmofhost(host)); + strcpy_truncate(sname, service, sizeof(sname)); + strcpy_truncate(inst, krb_get_phost(host), sizeof(inst)); + strcpy_truncate(realm, krb_realmofhost(host), sizeof(realm)); ret = krb_get_cred(sname, inst, realm, &cred); - memmove(&key, &cred.session, sizeof(des_cblock)); - des_key_sched(&key, schedule); + memmove(&d->key, &cred.session, sizeof(des_cblock)); + des_key_sched(&d->key, d->schedule); memset(&cred, 0, sizeof(cred)); return ret; } - -int -do_klogin(char *host) +static int +krb4_auth(void *app_data, char *host) { int ret; char *p; int len; - char adat[1024]; + KTEXT_ST adat; 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; - } + u_int32_t cs; + struct krb4_data *d = app_data; checksum = getpid(); - ret = do_auth("ftp", host, checksum); + ret = mk_auth(d, &adat, "ftp", host, checksum); if(ret == KDC_PR_UNKNOWN) - ret = do_auth("rcmd", host, checksum); + ret = mk_auth(d, &adat, "rcmd", host, checksum); if(ret){ printf("%s\n", krb_get_err_text(ret)); - verbose = old_verbose; - return ret; + return AUTH_CONTINUE; } - base64_encode(krb4_adat.dat, krb4_adat.length, &p); + if(base64_encode(adat.dat, adat.length, &p) < 0) { + printf("Out of memory base64-encoding.\n"); + return AUTH_CONTINUE; + } ret = command("ADAT %s", p); free(p); if(ret != COMPLETE){ printf("Server didn't accept auth data.\n"); - verbose = old_verbose; - return -1; + return AUTH_ERROR; } p = strstr(reply_string, "ADAT="); if(!p){ printf("Remote host didn't send adat reply.\n"); - verbose = old_verbose; - return -1; + return AUTH_ERROR; } - p+=5; - len = base64_decode(p, adat); + p += 5; + len = base64_decode(p, adat.dat); if(len < 0){ printf("Failed to decode base64 from server.\n"); - verbose = old_verbose; - return -1; + return AUTH_ERROR; } - ret = krb_rd_safe(adat, len, &key, + adat.length = len; + ret = krb_rd_safe(adat.dat, adat.length, &d->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; + return AUTH_ERROR; } - { - /* 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; - } + krb_get_int(msg_data.app_data, &cs, 4, 0); + if(cs - checksum != 1){ + printf("Bad checksum returned from server.\n"); + return AUTH_ERROR; } - 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; + return AUTH_OK; } +struct sec_client_mech krb4_client_mech = { + "KERBEROS_V4", + sizeof(struct krb4_data), + NULL, /* init */ + krb4_auth, + NULL, /* end */ + krb4_check_prot, + krb4_overhead, + krb4_encode, + krb4_decode +}; -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); -} - +#endif /* FTP_SERVER */ diff --git a/crypto/kerberosIV/appl/ftp/ftp/main.c b/crypto/kerberosIV/appl/ftp/ftp/main.c index 4d1b6a5..5b0fe36 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/main.c +++ b/crypto/kerberosIV/appl/ftp/ftp/main.c @@ -36,7 +36,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: main.c,v 1.20 1997/04/20 16:14:55 joda Exp $"); +RCSID("$Id: main.c,v 1.25 1999/05/08 02:22:09 assar Exp $"); int main(int argc, char **argv) @@ -54,8 +54,9 @@ main(int argc, char **argv) doglob = 1; interactive = 1; autologin = 1; + passivemode = 0; /* passive mode not active */ - while ((ch = getopt(argc, argv, "dgintv")) != EOF) { + while ((ch = getopt(argc, argv, "dginptv")) != EOF) { switch (ch) { case 'd': options |= SO_DEBUG; @@ -74,6 +75,9 @@ main(int argc, char **argv) autologin = 0; break; + case 'p': + passivemode = 1; + break; case 't': trace++; break; @@ -84,7 +88,7 @@ main(int argc, char **argv) default: fprintf(stderr, - "usage: ftp [-dgintv] [host [port]]\n"); + "usage: ftp [-dginptv] [host [port]]\n"); exit(1); } } @@ -96,7 +100,6 @@ main(int argc, char **argv) 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 */ /* @@ -104,8 +107,8 @@ main(int argc, char **argv) */ pw = k_getpwuid(getuid()); if (pw != NULL) { + strcpy_truncate(homedir, pw->pw_dir, sizeof(homedir)); home = homedir; - strcpy(home, pw->pw_dir); } if (argc > 0) { char *xargv[5]; @@ -174,6 +177,7 @@ lostpeer(int sig) } proxflag = 0; pswitch(0); + sec_end(); SIGRETURN(0); } @@ -242,8 +246,7 @@ cmdscanner(int top) p = readline("ftp> "); if(p == NULL) quit(0, 0); - strncpy(line, p, sizeof(line)); - line[sizeof(line) - 1] = 0; + strcpy_truncate(line, p, sizeof(line)); add_history(p); free(p); } else{ @@ -337,12 +340,16 @@ makeargv(void) for (margc = 0; ; margc++) { /* Expand array if necessary */ if (margc == margvlen) { + int i; + margv = (margvlen == 0) ? (char **)malloc(20 * sizeof(char *)) : (char **)realloc(margv, (margvlen + 20)*sizeof(char *)); if (margv == NULL) errx(1, "cannot realloc argv array"); + for(i = margvlen; i < margvlen + 20; ++i) + margv[i] = NULL; margvlen += 20; argp = margv + margc; } diff --git a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c index 8cea6d4..043e6fb 100644 --- a/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c +++ b/crypto/kerberosIV/appl/ftp/ftp/ruserpass.c @@ -32,7 +32,7 @@ */ #include "ftp_locl.h" -RCSID("$Id: ruserpass.c,v 1.10 1997/05/02 14:27:55 assar Exp $"); +RCSID("$Id: ruserpass.c,v 1.15 1999/03/11 13:54:58 joda Exp $"); static int token (void); static FILE *cfile; @@ -63,175 +63,213 @@ static struct toktab { { NULL, 0 } }; +/* + * Write a copy of the hostname into `hostname, sz' and return a guess + * as to the `domain' of that hostname. + */ + +static char * +guess_domain (char *hostname, size_t sz) +{ + struct hostent *he; + char *dot; + char *a; + char **aliases; + + if (gethostname (hostname, sz) < 0) { + strcpy_truncate (hostname, "", sz); + return ""; + } + dot = strchr (hostname, '.'); + if (dot != NULL) + return dot + 1; + + he = gethostbyname (hostname); + if (he == NULL) + return hostname; + + dot = strchr (he->h_name, '.'); + if (dot != NULL) { + strcpy_truncate (hostname, he->h_name, sz); + return dot + 1; + } + for (aliases = he->h_aliases; (a = *aliases) != NULL; ++aliases) { + dot = strchr (a, '.'); + if (dot != NULL) { + strcpy_truncate (hostname, a, sz); + return dot + 1; + } + } + return hostname; +} + int ruserpass(char *host, char **aname, char **apass, char **aacct) { - char *hdir, buf[BUFSIZ], *tmp; - int t, i, c, usedefault = 0; - struct stat stb; + 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); - } + mydomain = guess_domain (myhostname, MaxHostNameLen); + + 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) { + while ((t = token())) switch(t) { - case DEFAULT: - usedefault = 1; - /* FALL THROUGH */ + 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 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); + 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'; } - goto done; + 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); + fclose(cfile); + return (0); bad: - fclose(cfile); - return (-1); + fclose(cfile); + return (-1); } static int diff --git a/crypto/kerberosIV/appl/ftp/ftp/security.c b/crypto/kerberosIV/appl/ftp/ftp/security.c new file mode 100644 index 0000000..96d598f --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/security.c @@ -0,0 +1,730 @@ +/* + * Copyright (c) 1998, 1999 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 FTP_SERVER +#include "ftpd_locl.h" +#else +#include "ftp_locl.h" +#endif + +RCSID("$Id: security.c,v 1.8 1999/04/07 14:16:48 joda Exp $"); + +static enum protection_level command_prot; +static enum protection_level data_prot; +static size_t buffer_size; + +struct buffer { + void *data; + size_t size; + size_t index; + int eof_flag; +}; + +static struct buffer in_buffer, out_buffer; +int sec_complete; + +static struct { + enum protection_level level; + const char *name; +} level_names[] = { + { prot_clear, "clear" }, + { prot_safe, "safe" }, + { prot_confidential, "confidential" }, + { prot_private, "private" } +}; + +static const char * +level_to_name(enum protection_level 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"; +} + +#ifndef FTP_SERVER /* not used in server */ +static enum protection_level +name_to_level(const 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 (enum protection_level)-1; +} +#endif + +#ifdef FTP_SERVER + +static struct sec_server_mech *mechs[] = { +#ifdef KRB5 + &gss_server_mech, +#endif +#ifdef KRB4 + &krb4_server_mech, +#endif + NULL +}; + +static struct sec_server_mech *mech; + +#else + +static struct sec_client_mech *mechs[] = { +#ifdef KRB5 + &gss_client_mech, +#endif +#ifdef KRB4 + &krb4_client_mech, +#endif + NULL +}; + +static struct sec_client_mech *mech; + +#endif + +static void *app_data; + +int +sec_getc(FILE *F) +{ + if(sec_complete && data_prot) { + char c; + if(sec_read(fileno(F), &c, 1) == 0) + return EOF; + return c; + } else + return getc(F); +} + +static int +block_read(int fd, void *buf, size_t len) +{ + unsigned char *p = buf; + int b; + while(len) { + b = read(fd, p, len); + if(b <= 0) + return -1; + len -= b; + p += b; + } + return p - (unsigned char*)buf; +} + +static int +block_write(int fd, void *buf, size_t len) +{ + unsigned char *p = buf; + int b; + while(len) { + b = write(fd, p, len); + if(b < 0) + return -1; + len -= b; + p += b; + } + return p - (unsigned char*)buf; +} + +static int +sec_get_data(int fd, struct buffer *buf, int level) +{ + int len; + + if(block_read(fd, &len, sizeof(len)) < 0) + return -1; + len = ntohl(len); + buf->data = realloc(buf->data, len); + if(block_read(fd, buf->data, len) < 0) + return -1; + buf->size = (*mech->decode)(app_data, buf->data, len, data_prot); + buf->index = 0; + return 0; +} + +static size_t +buffer_read(struct buffer *buf, void *data, size_t len) +{ + len = min(len, buf->size - buf->index); + memcpy(data, (char*)buf->data + buf->index, len); + buf->index += len; + return len; +} + +static size_t +buffer_write(struct buffer *buf, void *data, size_t len) +{ + if(buf->index + len > buf->size) { + void *tmp; + if(buf->data == NULL) + tmp = malloc(1024); + else + tmp = realloc(buf->data, buf->index + len); + if(tmp == NULL) + return -1; + buf->data = tmp; + buf->size = buf->index + len; + } + memcpy((char*)buf->data + buf->index, data, len); + buf->index += len; + return len; +} + +int +sec_read(int fd, void *data, int length) +{ + size_t len; + int rx = 0; + + if(sec_complete == 0 || data_prot == 0) + return read(fd, data, length); + + if(in_buffer.eof_flag){ + in_buffer.eof_flag = 0; + return 0; + } + + len = buffer_read(&in_buffer, data, length); + length -= len; + rx += len; + data = (char*)data + len; + + while(length){ + if(sec_get_data(fd, &in_buffer, data_prot) < 0) + return -1; + if(in_buffer.size == 0) { + if(rx) + in_buffer.eof_flag = 1; + return rx; + } + len = buffer_read(&in_buffer, data, length); + length -= len; + rx += len; + data = (char*)data + len; + } + return rx; +} + +static int +sec_send(int fd, char *from, int length) +{ + int bytes; + void *buf; + bytes = (*mech->encode)(app_data, from, length, data_prot, &buf); + bytes = htonl(bytes); + block_write(fd, &bytes, sizeof(bytes)); + block_write(fd, buf, ntohl(bytes)); + free(buf); + return length; +} + +int +sec_fflush(FILE *F) +{ + if(data_prot != prot_clear) { + if(out_buffer.index > 0){ + sec_write(fileno(F), out_buffer.data, out_buffer.index); + out_buffer.index = 0; + } + sec_send(fileno(F), NULL, 0); + } + fflush(F); + return 0; +} + +int +sec_write(int fd, char *data, int length) +{ + int len = buffer_size; + int tx = 0; + + if(data_prot == prot_clear) + return write(fd, data, length); + + len -= (*mech->overhead)(app_data, data_prot, len); + while(length){ + if(length < len) + len = length; + sec_send(fd, data, len); + length -= len; + data += len; + tx += len; + } + return tx; +} + +int +sec_putc(int c, FILE *F) +{ + char ch = c; + if(data_prot == prot_clear) + return putc(c, F); + + buffer_write(&out_buffer, &ch, 1); + if(c == '\n' || out_buffer.index >= 1024 /* XXX */) { + sec_write(fileno(F), out_buffer.data, out_buffer.index); + out_buffer.index = 0; + } + return c; +} + +int +sec_read_msg(char *s, int level) +{ + int len; + char *buf; + int code; + + buf = malloc(strlen(s)); + len = base64_decode(s + 4, buf); /* XXX */ + + len = (*mech->decode)(app_data, buf, len, level); + if(len < 0) + return -1; + + buf[len] = '\0'; + + if(buf[3] == '-') + code = 0; + else + sscanf(buf, "%d", &code); + if(buf[len-1] == '\n') + buf[len-1] = '\0'; + strcpy(s, buf); + free(buf); + return code; +} + +int +sec_vfprintf(FILE *f, const char *fmt, va_list ap) +{ + char *buf; + void *enc; + int len; + if(!sec_complete) + return vfprintf(f, fmt, ap); + + vasprintf(&buf, fmt, ap); + len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc); + free(buf); + if(len < 0) { + printf("Failed to encode command.\n"); + return -1; + } + if(base64_encode(enc, len, &buf) < 0){ + printf("Out of memory base64-encoding.\n"); + return -1; + } +#ifdef FTP_SERVER + if(command_prot == prot_safe) + fprintf(f, "631 %s\r\n", buf); + else if(command_prot == prot_private) + fprintf(f, "632 %s\r\n", buf); + else if(command_prot == prot_confidential) + fprintf(f, "633 %s\r\n", buf); +#else + if(command_prot == prot_safe) + fprintf(f, "MIC %s", buf); + else if(command_prot == prot_private) + fprintf(f, "ENC %s", buf); + else if(command_prot == prot_confidential) + fprintf(f, "CONF %s", buf); +#endif + free(buf); + return 0; +} + +int +sec_fprintf(FILE *f, const char *fmt, ...) +{ + va_list ap; + int ret; + va_start(ap, fmt); + ret = sec_vfprintf(f, fmt, ap); + va_end(ap); + return ret; +} + +/* end common stuff */ + +#ifdef FTP_SERVER + +void +auth(char *auth_name) +{ + int i; + for(i = 0; (mech = mechs[i]) != NULL; i++){ + if(!strcasecmp(auth_name, mech->name)){ + app_data = realloc(app_data, mech->size); + if(mech->init && (*mech->init)(app_data) != 0) { + reply(431, "Unable to accept %s at this time", mech->name); + return; + } + if(mech->auth) { + (*mech->auth)(app_data); + return; + } + if(mech->adat) + reply(334, "Send authorization data."); + else + reply(234, "Authorization complete."); + return; + } + } + free (app_data); + reply(504, "%s is unknown to me", auth_name); +} + +void +adat(char *auth_data) +{ + if(mech && !sec_complete) { + void *buf = malloc(strlen(auth_data)); + size_t len; + len = base64_decode(auth_data, buf); + (*mech->adat)(app_data, buf, len); + free(buf); + } else + reply(503, "You must %sissue an AUTH first.", mech ? "re-" : ""); +} + +void pbsz(int size) +{ + size_t new = size; + if(!sec_complete) + reply(503, "Incomplete security data exchange."); + if(mech->pbsz) + new = (*mech->pbsz)(app_data, size); + if(buffer_size != new){ + buffer_size = size; + } + if(new != size) + reply(200, "PBSZ=%lu", (unsigned long)new); + else + reply(200, "OK"); +} + +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; + else if(!strcasecmp(pl, "S")) + p = prot_safe; + else if(!strcasecmp(pl, "E")) + p = prot_confidential; + else if(!strcasecmp(pl, "P")) + p = prot_private; + else { + reply(504, "Unrecognized protection level."); + return; + } + + if(sec_complete){ + if((*mech->check_prot)(app_data, p)){ + reply(536, "%s does not support %s protection.", + mech->name, level_to_name(p)); + }else{ + data_prot = (enum protection_level)p; + reply(200, "Data protection is %s.", level_to_name(p)); + } + }else{ + reply(503, "Incomplete security data exchange."); + } +} + +void ccc(void) +{ + if(sec_complete){ + if(mech->ccc && (*mech->ccc)(app_data) == 0) + command_prot = data_prot = prot_clear; + else + reply(534, "You must be joking."); + }else + reply(503, "Incomplete security data exchange."); +} + +void mec(char *msg, enum protection_level level) +{ + void *buf; + size_t len; + if(!sec_complete) { + reply(503, "Incomplete security data exchange."); + return; + } + buf = malloc(strlen(msg) + 2); /* XXX go figure out where that 2 + comes from :-) */ + len = base64_decode(msg, buf); + command_prot = level; + if(len == (size_t)-1) { + reply(501, "Failed to base64-decode command"); + return; + } + len = (*mech->decode)(app_data, buf, len, level); + if(len == (size_t)-1) { + reply(535, "Failed to decode command"); + return; + } + ((char*)buf)[len] = '\0'; + if(strstr((char*)buf, "\r\n") == NULL) + strcat((char*)buf, "\r\n"); + new_ftp_command(buf); +} + +/* ------------------------------------------------------------ */ + +int +sec_userok(char *user) +{ + if(sec_complete) + return (*mech->userok)(app_data, user); + return 0; +} + +char *ftp_command; + +void +new_ftp_command(char *command) +{ + ftp_command = command; +} + +void +delete_ftp_command(void) +{ + free(ftp_command); + ftp_command = NULL; +} + +int +secure_command(void) +{ + return ftp_command != NULL; +} + +#else /* FTP_SERVER */ + +void +sec_status(void) +{ + if(sec_complete){ + printf("Using %s for authentication.\n", mech->name); + printf("Using %s command channel.\n", level_to_name(command_prot)); + printf("Using %s data channel.\n", level_to_name(data_prot)); + if(buffer_size > 0) + printf("Protection buffer size: %lu.\n", + (unsigned long)buffer_size); + }else{ + printf("Not using any security mechanism.\n"); + } +} + +static int +sec_prot_internal(int level) +{ + int ret; + char *p; + unsigned int s = 1048576; + + int old_verbose = verbose; + verbose = 0; + + if(!sec_complete){ + printf("No security data exchange has taken place.\n"); + return -1; + } + + if(level){ + ret = command("PBSZ %u", s); + if(ret != COMPLETE){ + printf("Failed to set protection buffer size.\n"); + return -1; + } + buffer_size = s; + p = strstr(reply_string, "PBSZ="); + if(p) + sscanf(p, "PBSZ=%u", &s); + if(s < buffer_size) + buffer_size = s; + } + verbose = old_verbose; + ret = command("PROT %c", level["CSEP"]); /* XXX :-) */ + if(ret != COMPLETE){ + printf("Failed to set protection level.\n"); + return -1; + } + + data_prot = (enum protection_level)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(!sec_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((*mech->check_prot)(app_data, level)) { + printf("%s does not implement %s protection.\n", + mech->name, level_to_name(level)); + code = -1; + return; + } + + if(sec_prot_internal(level) < 0){ + code = -1; + return; + } + code = 0; +} + +static enum protection_level request_data_prot; + +void +sec_set_protection_level(void) +{ + if(sec_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 = (enum protection_level)l; + return 0; +} + +int +sec_login(char *host) +{ + int ret; + struct sec_client_mech **m; + int old_verbose = verbose; + + verbose = -1; /* shut up all messages this will produce (they + are usually not very user friendly) */ + + for(m = mechs; *m && (*m)->name; m++) { + app_data = realloc(app_data, (*m)->size); + if((*m)->init && (*(*m)->init)(app_data) != 0) { + printf("Skipping %s...\n", (*m)->name); + continue; + } + printf("Trying %s...\n", (*m)->name); + ret = command("AUTH %s", (*m)->name); + if(ret != CONTINUE){ + if(code == 504){ + printf("%s is not supported by the server.\n", (*m)->name); + }else if(code == 534){ + printf("%s rejected as security mechanism.\n", (*m)->name); + }else if(ret == ERROR) { + printf("The server doesn't support the FTP " + "security extensions.\n"); + verbose = old_verbose; + return -1; + } + continue; + } + + ret = (*(*m)->auth)(app_data, host); + + if(ret == AUTH_CONTINUE) + continue; + else if(ret != AUTH_OK){ + /* mechanism is supposed to output error string */ + verbose = old_verbose; + return -1; + } + mech = *m; + sec_complete = 1; + command_prot = prot_safe; + break; + } + + verbose = old_verbose; + return *m == NULL; +} + +void +sec_end(void) +{ + if (mech != NULL) { + if(mech->end) + (*mech->end)(app_data); + memset(app_data, 0, mech->size); + free(app_data); + } + sec_complete = 0; + data_prot = (enum protection_level)0; +} + +#endif /* FTP_SERVER */ + diff --git a/crypto/kerberosIV/appl/ftp/ftp/security.h b/crypto/kerberosIV/appl/ftp/ftp/security.h new file mode 100644 index 0000000..adac689 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftp/security.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1998, 1999 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 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: security.h,v 1.3 1999/04/07 14:15:20 joda Exp $ */ + +#ifndef __security_h__ +#define __security_h__ + +enum protection_level { + prot_clear, + prot_safe, + prot_confidential, + prot_private +}; + +struct sec_client_mech { + char *name; + size_t size; + int (*init)(void *); + int (*auth)(void *, char*); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, void*, int, int, void**); + int (*decode)(void *, void*, int, int); +}; + +struct sec_server_mech { + char *name; + size_t size; + int (*init)(void *); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, void*, int, int, void**); + int (*decode)(void *, void*, int, int); + + int (*auth)(void *); + int (*adat)(void *, void*, size_t); + size_t (*pbsz)(void *, size_t); + int (*ccc)(void*); + int (*userok)(void*, char*); +}; + +#define AUTH_OK 0 +#define AUTH_CONTINUE 1 +#define AUTH_ERROR 2 + +#ifdef FTP_SERVER +extern struct sec_server_mech krb4_server_mech, gss_server_mech; +#else +extern struct sec_client_mech krb4_client_mech, gss_client_mech; +#endif + +extern int sec_complete; + +#ifdef FTP_SERVER +extern char *ftp_command; +void new_ftp_command(char*); +void delete_ftp_command(void); +#endif + +/* ---- */ + + +int sec_fflush (FILE *); +int sec_fprintf (FILE *, const char *, ...); +int sec_getc (FILE *); +int sec_putc (int, FILE *); +int sec_read (int, void *, int); +int sec_read_msg (char *, int); +int sec_vfprintf (FILE *, const char *, va_list); +int sec_write (int, char *, int); + +#ifdef FTP_SERVER +void adat (char *); +void auth (char *); +void ccc (void); +void mec (char *, enum protection_level); +void pbsz (int); +void prot (char *); +void delete_ftp_command (void); +void new_ftp_command (char *); +int sec_userok (char *); +int secure_command (void); +#else +void sec_end (void); +int sec_login (char *); +void sec_prot (int, char **); +int sec_request_prot (char *); +void sec_set_protection_level (void); +void sec_status (void); +#endif + +#endif /* __security_h__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am new file mode 100644 index 0000000..187fca3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am @@ -0,0 +1,53 @@ +# $Id: Makefile.am,v 1.19 1999/04/25 13:24:55 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER + +libexec_PROGRAMS = ftpd + +CHECK_LOCAL = + +if KRB4 +krb4_sources = krb4.c kauth.c +endif +if KRB5 +krb5_sources = gssapi.c gss_userok.c +endif + +ftpd_SOURCES = \ + extern.h \ + ftpcmd.y \ + ftpd.c \ + ftpd_locl.h \ + logwtmp.c \ + pathnames.h \ + popen.c \ + security.c \ + $(krb4_sources) \ + $(krb5_sources) + +EXTRA_ftpd_SOURCES = krb4.c kauth.c gssapi.c gss_userok.c + +$(ftpd_OBJECTS): security.h + +security.c: + @test -f security.c || $(LN_S) $(srcdir)/../ftp/security.c . +security.h: + @test -f security.h || $(LN_S) $(srcdir)/../ftp/security.h . +krb4.c: + @test -f krb4.c || $(LN_S) $(srcdir)/../ftp/krb4.c . +gssapi.c: + @test -f gssapi.c || $(LN_S) $(srcdir)/../ftp/gssapi.c . + +CLEANFILES = security.c security.h krb4.c gssapi.c ftpcmd.c + +LDADD = ../common/libcommon.a \ + $(LIB_kafs) \ + $(LIB_gssapi) \ + $(LIB_krb5) \ + $(LIB_krb4) \ + $(LIB_otp) \ + $(top_builddir)/lib/des/libdes.la \ + $(LIB_roken) \ + $(DBLIB) diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in index 55981de..3b555a6 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in @@ -1,12 +1,12 @@ # -# $Id: Makefile.in,v 1.31 1997/05/02 17:49:27 assar Exp $ +# $Id: Makefile.in,v 1.40 1999/03/10 19:01:11 joda Exp $ # srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -topdir = ../../.. +top_builddir = ../../.. SHELL = /bin/sh @@ -14,7 +14,8 @@ CC = @CC@ YACC = @YACC@ RANLIB = @RANLIB@ DEFS = @DEFS@ -CFLAGS = @CFLAGS@ +WFLAGS = @WFLAGS@ +CFLAGS = @CFLAGS@ $(WFLAGS) LD_FLAGS = @LD_FLAGS@ LIBS = @LIBS@ LIB_DBM = @LIB_DBM@ @@ -23,6 +24,8 @@ MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ +LN_S = @LN_S@ + prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@ @@ -39,31 +42,42 @@ LIBTOP = $(ATHENA)/lib LIBKAFS = @KRB_KAFS_LIB@ LIBKRB = -L$(LIBTOP)/krb -lkrb LIBDES = -L$(LIBTOP)/des -ldes -LIBOTP = -L$(LIBTOP)/otp -lotp +LIBOTP = @LIB_otp@ 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 +ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c popen.c security.c krb4.c kauth.c +ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o security.o krb4.o kauth.o SOURCES = $(ftpd_SOURCES) OBJECTS = $(ftpd_OBJS) all: $(PROGS) +$(ftpd_OBJS): security.h + +security.c: + $(LN_S) $(srcdir)/../ftp/security.c . +security.h: + $(LN_S) $(srcdir)/../ftp/security.h . +krb4.c: + $(LN_S) $(srcdir)/../ftp/krb4.c . +gssapi.c: + $(LN_S) $(srcdir)/../ftp/gssapi.c . + .c.o: - $(CC) -c $(CFLAGS) -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $< + $(CC) -c -DFTP_SERVER -I. -I$(srcdir) -I$(srcdir)/../common -I$(INCTOP) $(DEFS) $(CFLAGS) $(CPPFLAGS) $< install: all - $(MKINSTALLDIRS) $(libexecdir) + $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir) for x in $(PROGS); do \ - $(INSTALL_PROGRAM) $$x $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + $(INSTALL_PROGRAM) $$x $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ done uninstall: for x in $(PROGS); do \ - rm -f $(libexecdir)/`echo $$x | sed '$(transform)'`; \ + rm -f $(DESTDIR)$(libexecdir)/`echo $$x | sed '$(transform)'`; \ done ftpd$(EXECSUFFIX): $(ftpd_OBJS) @@ -77,8 +91,12 @@ ftpcmd.c: ftpcmd.y TAGS: $(SOURCES) etags $(SOURCES) +CLEANFILES = ftpd$(EXECSUFFIX) ftpcmd.c security.c security.h krb4.c gssapi.c + clean cleandir: - rm -f *~ *.o core ftpd ftpcmd.c \#* + rm -f *~ *.o core \#* $(CLEANFILES) distclean: rm -f Makefile + +.PHONY: all install uninstall clean cleandir distclean diff --git a/crypto/kerberosIV/appl/ftp/ftpd/extern.h b/crypto/kerberosIV/appl/ftp/ftpd/extern.h index f9b800f..e96809e 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/extern.h +++ b/crypto/kerberosIV/appl/ftp/ftpd/extern.h @@ -36,6 +36,9 @@ #ifndef _EXTERN_H_ #define _EXTERN_H_ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif @@ -49,8 +52,13 @@ #ifdef HAVE_PWD_H #include <pwd.h> #endif -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#ifndef NBBY +#define NBBY CHAR_BIT #endif void abor(void); @@ -63,8 +71,8 @@ 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 *); +char *ftpd_getline(char *, int); +void ftpd_logwtmp(char *, char *, char *); void lreply(int, const char *, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) @@ -105,6 +113,11 @@ void yyerror(char *); void kauth(char *, char*); void klist(void); +void cond_kdestroy(void); +void kdestroy(void); +void krbtkfile(const char *tkfile); +void afslog(const char *cell); +void afsunlog(void); int find(char *); diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y index 9368cdb..be36ea2 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y @@ -42,73 +42,15 @@ %{ - -#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" +#include "ftpd_locl.h" +RCSID("$Id: ftpcmd.y,v 1.48 1999/05/08 02:22:43 assar Exp $"); off_t restart_point; static int cmd_type; static int cmd_form; static int cmd_bytesz; -char cbuf[512]; +char cbuf[2048]; char *fromname; struct tab { @@ -122,13 +64,13 @@ struct tab { extern struct tab cmdtab[]; extern struct tab sitetab[]; -static char *copy (char *); -static void help (struct tab *, char *); +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); + lookup (struct tab *, char *); +static void sizecmd (char *); +static RETSIGTYPE toolong (int); +static int yylex (void); /* This is for bison */ @@ -154,7 +96,7 @@ static int yylex (void); APPE MLFL MAIL MSND MSOM MSAM MRSQ MRCP ALLO REST RNFR RNTO ABOR DELE CWD LIST NLST SITE - STAT HELP NOOP MKD RMD PWD + sTAT HELP NOOP MKD RMD PWD CDUP STOU SMNT SYST SIZE MDTM UMASK IDLE CHMOD @@ -162,14 +104,15 @@ static int yylex (void); AUTH ADAT PROT PBSZ CCC MIC CONF ENC - KAUTH KLIST FIND URL + KAUTH KLIST KDESTROY KRBTKFILE AFSLOG + FIND URL LEXERR %token <s> STRING %token <i> NUMBER -%type <i> check_login check_login_no_guest octal_number byte_size +%type <i> check_login check_login_no_guest check_secure octal_number byte_size %type <i> struct_code mode_code type_code form_code %type <s> pathstring pathname password username @@ -193,38 +136,6 @@ cmd 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); @@ -311,100 +222,102 @@ cmd { reply(202, "ALLO command ignored."); } - | RETR check_login SP pathname CRLF + | RETR SP pathname CRLF check_login { - if ($2 && $4 != NULL) - retrieve((char *) 0, $4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + retrieve(0, $3); + if ($3 != NULL) + free($3); } - | STOR check_login SP pathname CRLF + | STOR SP pathname CRLF check_login { - if ($2 && $4 != NULL) - do_store($4, "w", 0); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_store($3, "w", 0); + if ($3 != NULL) + free($3); } - | APPE check_login SP pathname CRLF + | APPE SP pathname CRLF check_login { - if ($2 && $4 != NULL) - do_store($4, "a", 0); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_store($3, "a", 0); + if ($3 != NULL) + free($3); } - | NLST check_login CRLF + | NLST CRLF check_login { - if ($2) + if ($3) send_file_list("."); } - | NLST check_login SP STRING CRLF + | NLST SP STRING CRLF check_login { - if ($2 && $4 != NULL) - send_file_list($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + send_file_list($3); + if ($3 != NULL) + free($3); } - | LIST check_login CRLF + | LIST CRLF check_login { #ifdef HAVE_LS_A char *cmd = "/bin/ls -lA"; #else char *cmd = "/bin/ls -la"; #endif - if ($2) + if ($3) retrieve(cmd, ""); } - | LIST check_login SP pathname CRLF + | LIST SP pathname CRLF check_login { #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(); + if ($5 && $3 != NULL) + retrieve(cmd, $3); + if ($3 != NULL) + free($3); + } + | sTAT SP pathname CRLF check_login + { + if ($5 && $3 != NULL) + statfilecmd($3); + if ($3 != NULL) + free($3); + } + | sTAT CRLF + { + if(oobflag){ + if (file_size != (off_t) -1) + reply(213, "Status: %lu of %lu bytes transferred", + (unsigned long)byte_count, + (unsigned long)file_size); + else + reply(213, "Status: %lu bytes transferred", + (unsigned long)byte_count); + }else + statcmd(); } - | DELE check_login_no_guest SP pathname CRLF + | DELE SP pathname CRLF check_login_no_guest { - if ($2 && $4 != NULL) - do_delete($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_delete($3); + if ($3 != NULL) + free($3); } - | RNTO check_login_no_guest SP pathname CRLF + | RNTO SP pathname CRLF check_login_no_guest { - if($2){ + if($5){ if (fromname) { - renamecmd(fromname, $4); + renamecmd(fromname, $3); free(fromname); fromname = (char *) 0; } else { reply(503, "Bad sequence of commands."); } } - if ($4 != NULL) - free($4); + if ($3 != NULL) + free($3); } | ABOR CRLF { @@ -416,17 +329,17 @@ cmd }else reply(225, "ABOR command successful."); } - | CWD check_login CRLF + | CWD CRLF check_login { - if ($2) + if ($3) cwd(pw->pw_dir); } - | CWD check_login SP pathname CRLF + | CWD SP pathname CRLF check_login { - if ($2 && $4 != NULL) - cwd($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + cwd($3); + if ($3 != NULL) + free($3); } | HELP CRLF { @@ -451,28 +364,28 @@ cmd { reply(200, "NOOP command successful."); } - | MKD check_login SP pathname CRLF + | MKD SP pathname CRLF check_login { - if ($2 && $4 != NULL) - makedir($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + makedir($3); + if ($3 != NULL) + free($3); } - | RMD check_login_no_guest SP pathname CRLF + | RMD SP pathname CRLF check_login_no_guest { - if ($2 && $4 != NULL) - removedir($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + removedir($3); + if ($3 != NULL) + free($3); } - | PWD check_login CRLF + | PWD CRLF check_login { - if ($2) + if ($3) pwd(); } - | CDUP check_login CRLF + | CDUP CRLF check_login { - if ($2) + if ($3) cwd(".."); } | SITE SP HELP CRLF @@ -483,44 +396,40 @@ cmd { help(sitetab, $5); } - | SITE SP UMASK check_login CRLF + | SITE SP UMASK CRLF check_login { - int oldmask; - - if ($4) { - oldmask = umask(0); + if ($5) { + int oldmask = umask(0); umask(oldmask); reply(200, "Current UMASK is %03o", oldmask); } } - | SITE SP UMASK check_login_no_guest SP octal_number CRLF + | SITE SP UMASK SP octal_number CRLF check_login_no_guest { - int oldmask; - - if ($4) { - if (($6 == -1) || ($6 > 0777)) { + if ($7) { + if (($5 == -1) || ($5 > 0777)) { reply(501, "Bad UMASK value"); } else { - oldmask = umask($6); + int oldmask = umask($5); reply(200, - "UMASK set to %03o (was %03o)", - $6, oldmask); + "UMASK set to %03o (was %03o)", + $5, oldmask); } } } - | SITE SP CHMOD check_login_no_guest SP octal_number SP pathname CRLF + | SITE SP CHMOD SP octal_number SP pathname CRLF check_login_no_guest { - if ($4 && $8 != NULL) { - if ($6 > 0777) + if ($9 && $7 != NULL) { + if ($5 > 0777) reply(501, "CHMOD: Mode value must be between 0 and 0777"); - else if (chmod($8, $6) < 0) - perror_reply(550, $8); + else if (chmod($7, $5) < 0) + perror_reply(550, $7); else reply(200, "CHMOD command successful."); } - if ($8 != NULL) - free($8); + if ($7 != NULL) + free($7); } | SITE SP IDLE CRLF { @@ -543,47 +452,102 @@ cmd } } - | SITE SP KAUTH check_login SP STRING CRLF + | SITE SP KAUTH SP STRING CRLF check_login { +#ifdef KRB4 char *p; if(guest) reply(500, "Can't be done as guest."); else{ - if($4 && $6 != NULL){ - p = strpbrk($6, " \t"); + if($7 && $5 != NULL){ + p = strpbrk($5, " \t"); if(p){ *p++ = 0; - kauth($6, p + strspn(p, " \t")); + kauth($5, p + strspn(p, " \t")); }else - kauth($6, NULL); + kauth($5, NULL); } } - if($6 != NULL) - free($6); + if($5 != NULL) + free($5); +#else + reply(500, "Command not implemented."); +#endif } - | SITE SP KLIST check_login CRLF + | SITE SP KLIST CRLF check_login { - if($4) +#ifdef KRB4 + if($5) klist(); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP KDESTROY CRLF check_login + { +#ifdef KRB4 + if($5) + kdestroy(); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP KRBTKFILE SP STRING CRLF check_login + { +#ifdef KRB4 + if(guest) + reply(500, "Can't be done as guest."); + else if($7 && $5) + krbtkfile($5); + if($5) + free($5); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP AFSLOG CRLF check_login + { +#ifdef KRB4 + if(guest) + reply(500, "Can't be done as guest."); + else if($5) + afslog(NULL); +#else + reply(500, "Command not implemented."); +#endif + } + | SITE SP AFSLOG SP STRING CRLF check_login + { +#ifdef KRB4 + if(guest) + reply(500, "Can't be done as guest."); + else if($7){ + afslog($5); + } + if($5) + free($5); +#else + reply(500, "Command not implemented."); +#endif } - | SITE SP FIND check_login SP STRING CRLF + | SITE SP FIND SP STRING CRLF check_login { - if($4 && $6 != NULL) - find($6); - if($6 != NULL) - free($6); + if($7 && $5 != NULL) + find($5); + if($5 != NULL) + free($5); } | SITE SP URL CRLF { reply(200, "http://www.pdc.kth.se/kth-krb/"); } - | STOU check_login SP pathname CRLF + | STOU SP pathname CRLF check_login { - if ($2 && $4 != NULL) - do_store($4, "w", 1); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + do_store($3, "w", 1); + if ($3 != NULL) + free($3); } | SYST CRLF { @@ -601,12 +565,12 @@ cmd * Return size of file in a format suitable for * using with RESTART (we just count bytes). */ - | SIZE check_login SP pathname CRLF + | SIZE SP pathname CRLF check_login { - if ($2 && $4 != NULL) - sizecmd($4); - if ($4 != NULL) - free($4); + if ($5 && $3 != NULL) + sizecmd($3); + if ($3 != NULL) + free($3); } /* @@ -618,15 +582,16 @@ cmd * where xxx is the fractional second (of any precision, * not necessarily 3 digits) */ - | MDTM check_login SP pathname CRLF + | MDTM SP pathname CRLF check_login { - if ($2 && $4 != NULL) { + if ($5 && $3 != NULL) { struct stat stbuf; - if (stat($4, &stbuf) < 0) + if (stat($3, &stbuf) < 0) reply(550, "%s: %s", - $4, strerror(errno)); + $3, strerror(errno)); else if (!S_ISREG(stbuf.st_mode)) { - reply(550, "%s: not a plain file.", $4); + reply(550, + "%s: not a plain file.", $3); } else { struct tm *t; t = gmtime(&stbuf.st_mtime); @@ -640,8 +605,8 @@ cmd t->tm_sec); } } - if ($4 != NULL) - free($4); + if ($3 != NULL) + free($3); } | QUIT CRLF { @@ -654,13 +619,13 @@ cmd } ; rcmd - : RNFR check_login_no_guest SP pathname CRLF + : RNFR SP pathname CRLF check_login_no_guest { restart_point = (off_t) 0; - if ($2 && $4) { - fromname = renamefrom($4); - if (fromname == (char *) 0 && $4) { - free($4); + if ($5 && $3) { + fromname = renamefrom($3); + if (fromname == (char *) 0 && $3) { + free($3); } } } @@ -672,9 +637,41 @@ rcmd (long)restart_point, "Send STORE or RETRIEVE to initiate transfer."); } + | 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 + { + mec($3, prot_safe); + free($3); + } + | CONF SP STRING CRLF + { + mec($3, prot_confidential); + free($3); + } | ENC SP STRING CRLF { - enc($3); + mec($3, prot_private); free($3); } ; @@ -861,19 +858,24 @@ check_login_no_guest : check_login } ; -check_login - : /* empty */ +check_login : check_secure { - if(auth_complete && prot_level == prot_clear){ - reply(533, "Command protection level denied for paranoid reasons."); - $$ = 0; - }else - if (logged_in) - $$ = 1; - else { + if($1) { + if(($$ = logged_in) == 0) reply(530, "Please login with USER and PASS."); - $$ = 0; - } + } else + $$ = 0; + } + ; + +check_secure : /* empty */ + { + $$ = 1; + if(sec_complete && !secure_command()) { + $$ = 0; + reply(533, "Command protection level denied " + "for paranoid reasons."); + } } ; @@ -925,7 +927,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "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 ]" }, + { "STAT", sTAT, OSTR, 1, "[ <sp> path-name ]" }, { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" }, { "NOOP", NOOP, ARGS, 1, "" }, { "MKD", MKD, STR1, 1, "<sp> path-name" }, @@ -940,7 +942,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "SIZE", SIZE, OSTR, 1, "<sp> path-name" }, { "MDTM", MDTM, OSTR, 1, "<sp> path-name" }, - /* extensions from draft-ietf-cat-ftpsec-08 */ + /* extensions from RFC2228 */ { "AUTH", AUTH, STR1, 1, "<sp> auth-type" }, { "ADAT", ADAT, STR1, 1, "<sp> auth-data" }, { "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" }, @@ -961,6 +963,9 @@ struct tab sitetab[] = { { "KAUTH", KAUTH, STR1, 1, "<sp> principal [ <sp> ticket ]" }, { "KLIST", KLIST, ARGS, 1, "(show ticket file)" }, + { "KDESTROY", KDESTROY, ARGS, 1, "(destroy tickets)" }, + { "KRBTKFILE", KRBTKFILE, STR1, 1, "<sp> ticket-file" }, + { "AFSLOG", AFSLOG, OSTR, 1, "[<sp> cell]" }, { "FIND", FIND, STR1, 1, "<sp> globexpr" }, @@ -979,13 +984,11 @@ lookup(struct tab *p, char *cmd) return (0); } -#include <arpa/telnet.h> - /* - * getline - a hacked up version of fgets to ignore TELNET escape codes. + * ftpd_getline - a hacked up version of fgets to ignore TELNET escape codes. */ char * -getline(char *s, int n) +ftpd_getline(char *s, int n) { int c; char *cs; @@ -993,7 +996,7 @@ getline(char *s, int n) cs = s; /* tmpline may contain saved command from urgent mode interruption */ if(ftp_command){ - strncpy(s, ftp_command, n); + strcpy_truncate(s, ftp_command, n); if (debug) syslog(LOG_DEBUG, "command: %s", s); #ifdef XXX @@ -1001,7 +1004,6 @@ getline(char *s, int n) #endif return s; } - prot_level = prot_clear; while ((c = getc(stdin)) != EOF) { c &= 0377; if (c == IAC) { @@ -1087,15 +1089,15 @@ yylex(void) case CMD: signal(SIGALRM, toolong); alarm((unsigned) ftpd_timeout); - if (getline(cbuf, sizeof(cbuf)-1) == NULL) { + if (ftpd_getline(cbuf, sizeof(cbuf)-1) == NULL) { reply(221, "You could at least say goodbye."); dologout(0); } alarm(0); -#ifdef HASSETPROCTITLE +#ifdef HAVE_SETPROCTITLE if (strncasecmp(cbuf, "PASS", 4) != NULL) setproctitle("%s: %s", proctitle, cbuf); -#endif /* HASSETPROCTITLE */ +#endif /* HAVE_SETPROCTITLE */ if ((cp = strchr(cbuf, '\r'))) { *cp++ = '\n'; *cp = '\0'; @@ -1333,16 +1335,21 @@ help(struct tab *ctab, char *s) columns = 1; lines = (NCMDS + columns - 1) / columns; for (i = 0; i < lines; i++) { - strcpy (buf, " "); + strcpy_truncate (buf, " ", sizeof(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 ? ' ' : '*'); + 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, " "); + strcat_truncate (buf, + " ", + sizeof(buf)); w++; } } @@ -1375,11 +1382,12 @@ sizecmd(char *filename) reply(550, "%s: not a plain file.", filename); else reply(213, "%lu", (unsigned long)stbuf.st_size); - break; } + break; + } case TYPE_A: { FILE *fin; int c; - off_t count; + size_t count; struct stat stbuf; fin = fopen(filename, "r"); if (fin == NULL) { @@ -1400,8 +1408,9 @@ sizecmd(char *filename) } fclose(fin); - reply(213, "%ld", count); - break; } + reply(213, "%lu", (unsigned long)count); + break; + } default: reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); } diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h new file mode 100644 index 0000000..4bb3ad3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1998, 1999 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 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: ftpd_locl.h,v 1.5.2.1 1999/07/22 03:24:42 assar Exp $ */ + +#ifndef __ftpd_locl_h__ +#define __ftpd_locl_h__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#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 != 40 +#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 + +#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 <fnmatch.h> + +#ifdef HAVE_BSD_BSD_H +#include <bsd/bsd.h> +#endif + +#include <err.h> + +#include "pathnames.h" +#include "extern.h" +#include "common.h" + +#include "security.h" + +#include "roken.h" + +#ifdef KRB4 +#include <krb.h> +#include <kafs.h> +#endif + +#ifdef OTP +#include <otp.h> +#endif + +#ifdef SOCKS +#include <socks.h> +extern int LIBPREFIX(fclose) (FILE *); +#endif + +int yyparse(); + +#ifndef LOG_FTP +#define LOG_FTP LOG_DAEMON +#endif + +#endif /* __ftpd_locl_h__ */ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c new file mode 100644 index 0000000..8a1a8e3 --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1998 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 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 "ftpd_locl.h" +#include <gssapi.h> +#include <krb5.h> + +RCSID("$Id: gss_userok.c,v 1.1 1998/05/12 12:15:22 joda Exp $"); + +/* XXX a bit too much of krb5 dependency here... + What is the correct way to do this? + */ + +extern krb5_context gssapi_krb5_context; + +/* XXX sync with gssapi.c */ +struct gss_data { + gss_ctx_id_t context_hdl; + char *client_name; +}; + +int gss_userok(void*, char*); /* to keep gcc happy */ + +int +gss_userok(void *app_data, char *username) +{ + struct gss_data *data = app_data; + if(gssapi_krb5_context) { + krb5_principal client; + krb5_error_code ret; + ret = krb5_parse_name(gssapi_krb5_context, data->client_name, &client); + if(ret) + return 1; + ret = krb5_kuserok(gssapi_krb5_context, client, username); + krb5_free_principal(gssapi_krb5_context, client); + return !ret; + } + return 1; +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c index 02d23d6..33795b6 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -36,34 +36,9 @@ * 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 "ftpd_locl.h" -#include "extern.h" -#include "krb4.h" -#include "auth.h" -#include "base64.h" +RCSID("$Id: kauth.c,v 1.22 1999/06/29 21:19:33 bg Exp $"); static KTEXT_ST cip; static unsigned int lifetime; @@ -71,9 +46,15 @@ static time_t local_time; static krb_principal pr; +static int do_destroy_tickets = 1; + static int -save_tkt(char *user, char *instance, char *realm, void *arg, - int (*key_proc)(char*, char*, char*, void*, des_cblock*), KTEXT *cipp) +save_tkt(const char *user, + const char *instance, + const char *realm, + const void *arg, + key_proc_t key_proc, + KTEXT *cipp) { local_time = time(0); memmove(&cip, *cipp, sizeof(cip)); @@ -89,11 +70,9 @@ store_ticket(KTEXT cip) unsigned char kvno; KTEXT_ST tkt; int left = cip->length; - + int len; int kerror; - time_t kdc_time; - ptr = (char *) cip->dat; /* extract session key */ @@ -101,29 +80,32 @@ store_ticket(KTEXT cip) ptr += 8; left -= 8; - if (strnlen(ptr, left) == left) + len = strnlen(ptr, left); + if (len == left) return(INTK_BADPW); /* extract server's name */ - strcpy(sp.name, ptr); - ptr += strlen(sp.name) + 1; - left -= strlen(sp.name) + 1; + strcpy_truncate(sp.name, ptr, sizeof(sp.name)); + ptr += len + 1; + left -= len + 1; - if (strnlen(ptr, left) == left) + len = strnlen(ptr, left); + if (len == left) return(INTK_BADPW); - + /* extract server's instance */ - strcpy(sp.instance, ptr); - ptr += strlen(sp.instance) + 1; - left -= strlen(sp.instance) + 1; + strcpy_truncate(sp.instance, ptr, sizeof(sp.instance)); + ptr += len + 1; + left -= len + 1; - if (strnlen(ptr, left) == left) + len = strnlen(ptr, left); + if (len == left) return(INTK_BADPW); - + /* extract server's realm */ - strcpy(sp.realm,ptr); - ptr += strlen(sp.realm) + 1; - left -= strlen(sp.realm) + 1; + strcpy_truncate(sp.realm, ptr, sizeof(sp.realm)); + ptr += len + 1; + left -= len + 1; if(left < 3) return INTK_BADPW; @@ -154,14 +136,18 @@ store_ticket(KTEXT cip) #if 0 /* check KDC time stamp */ - memmove(&kdc_time, ptr, sizeof(kdc_time)); - if (swap_bytes) swap_u_long(kdc_time); + { + time_t kdc_time; - ptr += 4; + 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 + if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) { + return(RD_AP_TIME); /* XXX should probably be better code */ + } } #endif @@ -184,7 +170,8 @@ store_ticket(KTEXT cip) return(kerror); } -void kauth(char *principal, char *ticket) +void +kauth(char *principal, char *ticket) { char *p; int ret; @@ -209,8 +196,10 @@ void kauth(char *principal, char *ticket) memset(&cip, 0, sizeof(cip)); return; } + do_destroy_tickets = 1; + if(k_hasafs()) - k_afsklog(0, 0); + krb_afslog(0, 0); reply(200, "Tickets will be destroyed on exit."); return; } @@ -226,7 +215,10 @@ void kauth(char *principal, char *ticket) reply(500, "Kerberos error: %s.", krb_get_err_text(ret)); return; } - base64_encode(cip.dat, cip.length, &p); + if(base64_encode(cip.dat, cip.length, &p) < 0) { + reply(500, "Out of memory while base64-encoding."); + return; + } reply(300, "P=%s T=%s", krb_unparse_name(&pr), p); free(p); memset(&cip, 0, sizeof(cip)); @@ -245,7 +237,8 @@ short_date(int32_t dp) return (cp); } -void klist(void) +void +klist(void) { int err; @@ -302,6 +295,8 @@ void klist(void) * it was done before tf_init. */ + lreply(200, "Ticket file: %s", tkt_string()); + lreply(200, "Principal: %s", krb_unparse_name(&pr)); while ((err = tf_get_cred(&c)) == KSUCCESS) { if (header) { @@ -309,17 +304,63 @@ void klist(void) " Issued", " Expires", " Principal (kvno)"); header = 0; } - strcpy(buf1, short_date(c.issue_date)); + strcpy_truncate(buf1, short_date(c.issue_date), sizeof(buf1)); 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)); + strcpy_truncate(buf2, short_date(c.issue_date), sizeof(buf2)); else - strcpy(buf2, ">>> Expired <<< "); + strcpy_truncate(buf2, ">>> Expired <<< ", sizeof(buf2)); 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, ""); + reply(200, " "); +} + +/* + * Only destroy if we created the tickets + */ + +void +cond_kdestroy(void) +{ + if (do_destroy_tickets) + dest_tkt(); + afsunlog(); +} + +void +kdestroy(void) +{ + dest_tkt(); + afsunlog(); + reply(200, "Tickets destroyed"); +} + +void +krbtkfile(const char *tkfile) +{ + do_destroy_tickets = 0; + krb_set_tkt_string(tkfile); + reply(200, "Using ticket file %s", tkfile); +} + +void +afslog(const char *cell) +{ + if(k_hasafs()) { + krb_afslog(cell, 0); + reply(200, "afslog done"); + } else { + reply(200, "no AFS present"); + } +} + +void +afsunlog(void) +{ + if(k_hasafs()) + k_unlog(); } diff --git a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c index 95ab216..d948a5a 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c @@ -38,7 +38,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: logwtmp.c,v 1.10 1997/05/25 15:17:56 assar Exp $"); +RCSID("$Id: logwtmp.c,v 1.13 1999/03/01 09:49:37 joda Exp $"); #endif #include <stdio.h> @@ -74,18 +74,20 @@ RCSID("$Id: logwtmp.c,v 1.10 1997/05/25 15:17:56 assar Exp $"); #endif void -logwtmp(char *line, char *name, char *host) +ftpd_logwtmp(char *line, char *name, char *host) { static int init = 0; - static int fd, fdx; - struct timeval tv; + static int fd; +#ifdef WTMPX_FILE + static int fdx; +#endif struct utmp ut; #ifdef WTMPX_FILE struct utmpx utx; #endif memset(&ut, 0, sizeof(struct utmp)); -#ifdef HAVE_UT_TYPE +#ifdef HAVE_STRUCT_UTMP_UT_TYPE if(name[0]) ut.ut_type = USER_PROCESS; else @@ -93,10 +95,10 @@ logwtmp(char *line, char *name, char *host) #endif strncpy(ut.ut_line, line, sizeof(ut.ut_line)); strncpy(ut.ut_name, name, sizeof(ut.ut_name)); -#ifdef HAVE_UT_PID +#ifdef HAVE_STRUCT_UTMP_UT_PID ut.ut_pid = getpid(); #endif -#ifdef HAVE_UT_HOST +#ifdef HAVE_STRUCT_UTMP_UT_HOST strncpy(ut.ut_host, host, sizeof(ut.ut_host)); #endif ut.ut_time = time(NULL); @@ -105,14 +107,18 @@ logwtmp(char *line, char *name, char *host) 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 +#ifdef HAVE_STRUCT_UTMPX_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; + { + struct timeval tv; + + 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; diff --git a/crypto/kerberosIV/appl/ftp/ftpd/popen.c b/crypto/kerberosIV/appl/ftp/ftpd/popen.c index 58c4985..4bd5e04 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/popen.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/popen.c @@ -37,7 +37,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: popen.c,v 1.16 1997/06/01 03:14:06 assar Exp $"); +RCSID("$Id: popen.c,v 1.18 1998/06/09 19:24:24 joda Exp $"); #endif #include <sys/types.h> @@ -89,10 +89,10 @@ ftp_rooted(const char *path) if(!home[0]) if((pwd = k_getpwnam("ftp"))) - strcpy(home, pwd->pw_dir); + strcpy_truncate(home, pwd->pw_dir, sizeof(home)); snprintf(newpath, sizeof(newpath), "%s/%s", home, path); if(access(newpath, X_OK)) - strcpy(newpath, path); + strcpy_truncate(newpath, path, sizeof(newpath)); return newpath; } @@ -125,8 +125,8 @@ ftpd_popen(char *program, char *type, int do_stderr, int no_glob) return (NULL); /* break up string into pieces */ + foo = NULL; for (argc = 0, cp = program;; cp = NULL) { - foo = NULL; if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo))) break; } |