diff options
author | dfr <dfr@FreeBSD.org> | 2008-05-07 13:39:42 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2008-05-07 13:39:42 +0000 |
commit | 52bf09d8197dd1ec84e1ab72684f2058f0eae9e1 (patch) | |
tree | 07a0d6761d1b42410a27e4c7d583b766d6671f80 /crypto/heimdal/appl/ftp/ftpd | |
parent | 6c68306921f6e85bce52c905cf2606c25acdb436 (diff) | |
parent | 51b6601db456e699ea5d4843cbc7239ee92d9c13 (diff) | |
download | FreeBSD-src-52bf09d8197dd1ec84e1ab72684f2058f0eae9e1.zip FreeBSD-src-52bf09d8197dd1ec84e1ab72684f2058f0eae9e1.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r178825,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'crypto/heimdal/appl/ftp/ftpd')
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/Makefile.am | 14 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/Makefile.in | 357 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/extern.h | 6 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/ftpcmd.c | 3551 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/ftpcmd.y | 147 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/ftpd.8 | 4 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/ftpd.c | 95 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h | 4 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/ftpusers.5 | 2 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/gss_userok.c | 149 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/gssapi.c | 528 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/kauth.c | 167 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/klist.c | 178 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/krb4.c | 340 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/logwtmp.c | 2 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/ls.c | 93 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/pathnames.h | 2 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/popen.c | 2 | ||||
-rw-r--r-- | crypto/heimdal/appl/ftp/ftpd/security.c | 883 |
19 files changed, 6069 insertions, 455 deletions
diff --git a/crypto/heimdal/appl/ftp/ftpd/Makefile.am b/crypto/heimdal/appl/ftp/ftpd/Makefile.am index 20f8b57..b404876 100644 --- a/crypto/heimdal/appl/ftp/ftpd/Makefile.am +++ b/crypto/heimdal/appl/ftp/ftpd/Makefile.am @@ -1,15 +1,15 @@ -# $Id: Makefile.am,v 1.26 2001/09/06 12:18:34 assar Exp $ +# $Id: Makefile.am 21031 2007-06-09 05:00:27Z lha $ include $(top_srcdir)/Makefile.am.common -INCLUDES += -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER +AM_CPPFLAGS += -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER libexec_PROGRAMS = ftpd CHECK_LOCAL = if KRB4 -krb4_sources = krb4.c kauth.c +krb4_sources = krb4.c endif if KRB5 krb5_sources = gssapi.c gss_userok.c @@ -25,6 +25,8 @@ ftpd_SOURCES = \ pathnames.h \ popen.c \ security.c \ + kauth.c \ + klist.c \ $(krb4_sources) \ $(krb5_sources) @@ -41,7 +43,7 @@ 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 +CLEANFILES = security.c security.h krb4.c gssapi.c man_MANS = ftpd.8 ftpusers.5 @@ -51,5 +53,7 @@ LDADD = ../common/libcommon.a \ $(LIB_krb5) \ $(LIB_kafs) \ $(LIB_krb4) \ - $(LIB_des) \ + $(LIB_hcrypto) \ $(LIB_roken) + +EXTRA_DIST = $(man_MANS) diff --git a/crypto/heimdal/appl/ftp/ftpd/Makefile.in b/crypto/heimdal/appl/ftp/ftpd/Makefile.in index b6d8f62..c7a6a8f 100644 --- a/crypto/heimdal/appl/ftp/ftpd/Makefile.in +++ b/crypto/heimdal/appl/ftp/ftpd/Makefile.in @@ -1,8 +1,8 @@ -# Makefile.in generated by automake 1.8.3 from Makefile.am. +# Makefile.in generated by automake 1.10 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -14,23 +14,17 @@ @SET_MAKE@ -# $Id: Makefile.am,v 1.26 2001/09/06 12:18:34 assar Exp $ +# $Id: Makefile.am 21031 2007-06-09 05:00:27Z lha $ -# $Id: Makefile.am.common,v 1.5 2002/05/19 18:35:37 joda Exp $ +# $Id: Makefile.am.common 10998 2002-05-19 18:35:37Z joda $ -# $Id: Makefile.am.common,v 1.37.2.2 2003/10/13 13:15:39 joda Exp $ +# $Id: Makefile.am.common 22488 2008-01-21 11:47:22Z lha $ -SOURCES = $(ftpd_SOURCES) $(EXTRA_ftpd_SOURCES) - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = ../../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c @@ -42,6 +36,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : +build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/Makefile.am.common \ @@ -50,16 +45,14 @@ libexec_PROGRAMS = ftpd$(EXEEXT) subdir = appl/ftp/ftpd ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \ - $(top_srcdir)/cf/auth-modules.m4 \ + $(top_srcdir)/cf/auth-modules.m4 $(top_srcdir)/cf/autobuild.m4 \ $(top_srcdir)/cf/broken-getaddrinfo.m4 \ - $(top_srcdir)/cf/broken-getnameinfo.m4 \ $(top_srcdir)/cf/broken-glob.m4 \ $(top_srcdir)/cf/broken-realloc.m4 \ $(top_srcdir)/cf/broken-snprintf.m4 $(top_srcdir)/cf/broken.m4 \ $(top_srcdir)/cf/broken2.m4 $(top_srcdir)/cf/c-attribute.m4 \ $(top_srcdir)/cf/capabilities.m4 \ $(top_srcdir)/cf/check-compile-et.m4 \ - $(top_srcdir)/cf/check-declaration.m4 \ $(top_srcdir)/cf/check-getpwnam_r-posix.m4 \ $(top_srcdir)/cf/check-man.m4 \ $(top_srcdir)/cf/check-netinet-ip-and-tcp.m4 \ @@ -72,6 +65,7 @@ am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \ $(top_srcdir)/cf/find-func-no-libs2.m4 \ $(top_srcdir)/cf/find-func.m4 \ $(top_srcdir)/cf/find-if-not-broken.m4 \ + $(top_srcdir)/cf/framework-security.m4 \ $(top_srcdir)/cf/have-struct-field.m4 \ $(top_srcdir)/cf/have-type.m4 $(top_srcdir)/cf/irix.m4 \ $(top_srcdir)/cf/krb-bigendian.m4 \ @@ -80,56 +74,61 @@ am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \ $(top_srcdir)/cf/krb-readline.m4 \ $(top_srcdir)/cf/krb-struct-spwd.m4 \ $(top_srcdir)/cf/krb-struct-winsize.m4 \ - $(top_srcdir)/cf/mips-abi.m4 $(top_srcdir)/cf/misc.m4 \ - $(top_srcdir)/cf/need-proto.m4 $(top_srcdir)/cf/osfc2.m4 \ - $(top_srcdir)/cf/otp.m4 $(top_srcdir)/cf/proto-compat.m4 \ - $(top_srcdir)/cf/retsigtype.m4 $(top_srcdir)/cf/roken-frag.m4 \ - $(top_srcdir)/cf/sunos.m4 $(top_srcdir)/cf/telnet.m4 \ - $(top_srcdir)/cf/test-package.m4 $(top_srcdir)/cf/wflags.m4 \ - $(top_srcdir)/cf/with-all.m4 $(top_srcdir)/configure.in + $(top_srcdir)/cf/largefile.m4 $(top_srcdir)/cf/mips-abi.m4 \ + $(top_srcdir)/cf/misc.m4 $(top_srcdir)/cf/need-proto.m4 \ + $(top_srcdir)/cf/osfc2.m4 $(top_srcdir)/cf/otp.m4 \ + $(top_srcdir)/cf/proto-compat.m4 $(top_srcdir)/cf/pthreads.m4 \ + $(top_srcdir)/cf/resolv.m4 $(top_srcdir)/cf/retsigtype.m4 \ + $(top_srcdir)/cf/roken-frag.m4 \ + $(top_srcdir)/cf/socket-wrapper.m4 $(top_srcdir)/cf/sunos.m4 \ + $(top_srcdir)/cf/telnet.m4 $(top_srcdir)/cf/test-package.m4 \ + $(top_srcdir)/cf/version-script.m4 $(top_srcdir)/cf/wflags.m4 \ + $(top_srcdir)/cf/win32.m4 $(top_srcdir)/cf/with-all.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h CONFIG_CLEAN_FILES = -am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" +am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(man5dir)" \ + "$(DESTDIR)$(man8dir)" libexecPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(libexec_PROGRAMS) am__ftpd_SOURCES_DIST = extern.h ftpcmd.y ftpd.c ftpd_locl.h logwtmp.c \ - ls.c pathnames.h popen.c security.c krb4.c kauth.c gssapi.c \ - gss_userok.c -@KRB4_TRUE@am__objects_1 = krb4.$(OBJEXT) kauth.$(OBJEXT) + ls.c pathnames.h popen.c security.c kauth.c klist.c krb4.c \ + gssapi.c gss_userok.c +@KRB4_TRUE@am__objects_1 = krb4.$(OBJEXT) @KRB5_TRUE@am__objects_2 = gssapi.$(OBJEXT) gss_userok.$(OBJEXT) am_ftpd_OBJECTS = ftpcmd.$(OBJEXT) ftpd.$(OBJEXT) logwtmp.$(OBJEXT) \ ls.$(OBJEXT) popen.$(OBJEXT) security.$(OBJEXT) \ - $(am__objects_1) $(am__objects_2) + kauth.$(OBJEXT) klist.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) ftpd_OBJECTS = $(am_ftpd_OBJECTS) ftpd_LDADD = $(LDADD) am__DEPENDENCIES_1 = -@KRB5_TRUE@am__DEPENDENCIES_2 = \ -@KRB5_TRUE@ $(top_builddir)/lib/gssapi/libgssapi.la -@KRB5_TRUE@am__DEPENDENCIES_3 = $(top_builddir)/lib/krb5/libkrb5.la \ -@KRB5_TRUE@ $(top_builddir)/lib/asn1/libasn1.la -am__DEPENDENCIES_4 = $(top_builddir)/lib/kafs/libkafs.la \ +am__DEPENDENCIES_2 = $(top_builddir)/lib/kafs/libkafs.la \ $(am__DEPENDENCIES_1) ftpd_DEPENDENCIES = ../common/libcommon.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \ - $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include + $(LIB_gssapi) $(LIB_krb5) $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I. -I$(top_builddir)/include@am__isrc@ depcomp = am__depfiles_maybe = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) -LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ || YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) -LTYACCCOMPILE = $(LIBTOOL) --mode=compile $(YACC) $(YFLAGS) \ - $(AM_YFLAGS) +LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS) +YLWRAP = $(top_srcdir)/ylwrap SOURCES = $(ftpd_SOURCES) $(EXTRA_ftpd_SOURCES) DIST_SOURCES = $(am__ftpd_SOURCES_DIST) $(EXTRA_ftpd_SOURCES) man5dir = $(mandir)/man5 @@ -139,13 +138,7 @@ ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AIX4_FALSE = @AIX4_FALSE@ -AIX4_TRUE = @AIX4_TRUE@ -AIX_DYNAMIC_AFS_FALSE = @AIX_DYNAMIC_AFS_FALSE@ -AIX_DYNAMIC_AFS_TRUE = @AIX_DYNAMIC_AFS_TRUE@ AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@ -AIX_FALSE = @AIX_FALSE@ -AIX_TRUE = @AIX_TRUE@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ @@ -155,8 +148,6 @@ AWK = @AWK@ CANONICAL_HOST = @CANONICAL_HOST@ CATMAN = @CATMAN@ CATMANEXT = @CATMANEXT@ -CATMAN_FALSE = @CATMAN_FALSE@ -CATMAN_TRUE = @CATMAN_TRUE@ CC = @CC@ CFLAGS = @CFLAGS@ COMPILE_ET = @COMPILE_ET@ @@ -167,11 +158,10 @@ CXXCPP = @CXXCPP@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBLIB = @DBLIB@ -DCE_FALSE = @DCE_FALSE@ -DCE_TRUE = @DCE_TRUE@ DEFS = @DEFS@ DIR_com_err = @DIR_com_err@ -DIR_des = @DIR_des@ +DIR_hcrypto = @DIR_hcrypto@ +DIR_hdbdir = @DIR_hdbdir@ DIR_roken = @DIR_roken@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ @@ -179,42 +169,27 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -EXTRA_LIB45 = @EXTRA_LIB45@ F77 = @F77@ FFLAGS = @FFLAGS@ +GREP = @GREP@ GROFF = @GROFF@ -HAVE_DB1_FALSE = @HAVE_DB1_FALSE@ -HAVE_DB1_TRUE = @HAVE_DB1_TRUE@ -HAVE_DB3_FALSE = @HAVE_DB3_FALSE@ -HAVE_DB3_TRUE = @HAVE_DB3_TRUE@ -HAVE_DLOPEN_FALSE = @HAVE_DLOPEN_FALSE@ -HAVE_DLOPEN_TRUE = @HAVE_DLOPEN_TRUE@ -HAVE_NDBM_FALSE = @HAVE_NDBM_FALSE@ -HAVE_NDBM_TRUE = @HAVE_NDBM_TRUE@ -HAVE_OPENSSL_FALSE = @HAVE_OPENSSL_FALSE@ -HAVE_OPENSSL_TRUE = @HAVE_OPENSSL_TRUE@ -HAVE_X_FALSE = @HAVE_X_FALSE@ -HAVE_X_TRUE = @HAVE_X_TRUE@ INCLUDES_roken = @INCLUDES_roken@ -INCLUDE_des = @INCLUDE_des@ +INCLUDE_hcrypto = @INCLUDE_hcrypto@ INCLUDE_hesiod = @INCLUDE_hesiod@ INCLUDE_krb4 = @INCLUDE_krb4@ INCLUDE_openldap = @INCLUDE_openldap@ INCLUDE_readline = @INCLUDE_readline@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -IRIX_FALSE = @IRIX_FALSE@ -IRIX_TRUE = @IRIX_TRUE@ -KRB4_FALSE = @KRB4_FALSE@ -KRB4_TRUE = @KRB4_TRUE@ -KRB5_FALSE = @KRB5_FALSE@ -KRB5_TRUE = @KRB5_TRUE@ LDFLAGS = @LDFLAGS@ +LDFLAGS_VERSION_SCRIPT = @LDFLAGS_VERSION_SCRIPT@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_roken = @LIBADD_roken@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ @@ -232,12 +207,9 @@ LIB_crypt = @LIB_crypt@ LIB_db_create = @LIB_db_create@ LIB_dbm_firstkey = @LIB_dbm_firstkey@ LIB_dbopen = @LIB_dbopen@ -LIB_des = @LIB_des@ -LIB_des_a = @LIB_des_a@ -LIB_des_appl = @LIB_des_appl@ -LIB_des_so = @LIB_des_so@ LIB_dlopen = @LIB_dlopen@ LIB_dn_expand = @LIB_dn_expand@ +LIB_door_create = @LIB_door_create@ LIB_el_init = @LIB_el_init@ LIB_freeaddrinfo = @LIB_freeaddrinfo@ LIB_gai_strerror = @LIB_gai_strerror@ @@ -247,15 +219,14 @@ LIB_gethostbyname2 = @LIB_gethostbyname2@ LIB_getnameinfo = @LIB_getnameinfo@ LIB_getpwnam_r = @LIB_getpwnam_r@ LIB_getsockopt = @LIB_getsockopt@ +LIB_hcrypto = @LIB_hcrypto@ +LIB_hcrypto_a = @LIB_hcrypto_a@ +LIB_hcrypto_appl = @LIB_hcrypto_appl@ +LIB_hcrypto_so = @LIB_hcrypto_so@ LIB_hesiod = @LIB_hesiod@ LIB_hstrerror = @LIB_hstrerror@ LIB_kdb = @LIB_kdb@ LIB_krb4 = @LIB_krb4@ -LIB_krb_disable_debug = @LIB_krb_disable_debug@ -LIB_krb_enable_debug = @LIB_krb_enable_debug@ -LIB_krb_get_kdc_time_diff = @LIB_krb_get_kdc_time_diff@ -LIB_krb_get_our_ip_for_realm = @LIB_krb_get_our_ip_for_realm@ -LIB_krb_kdctimeofday = @LIB_krb_kdctimeofday@ LIB_loadquery = @LIB_loadquery@ LIB_logout = @LIB_logout@ LIB_logwtmp = @LIB_logwtmp@ @@ -264,6 +235,7 @@ LIB_openpty = @LIB_openpty@ LIB_otp = @LIB_otp@ LIB_pidfile = @LIB_pidfile@ LIB_readline = @LIB_readline@ +LIB_res_ndestroy = @LIB_res_ndestroy@ LIB_res_nsearch = @LIB_res_nsearch@ LIB_res_search = @LIB_res_search@ LIB_roken = @LIB_roken@ @@ -275,15 +247,10 @@ LIB_tgetent = @LIB_tgetent@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ -NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@ -NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@ +MKDIR_P = @MKDIR_P@ NROFF = @NROFF@ OBJEXT = @OBJEXT@ -OTP_FALSE = @OTP_FALSE@ -OTP_TRUE = @OTP_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ @@ -291,74 +258,80 @@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ +PTHREADS_LIBS = @PTHREADS_LIBS@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +VERSIONING = @VERSIONING@ VOID_RETSIGTYPE = @VOID_RETSIGTYPE@ WFLAGS = @WFLAGS@ WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@ WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@ +XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ YACC = @YACC@ -ac_ct_AR = @ac_ct_AR@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_F77 = @ac_ct_F77@ -ac_ct_RANLIB = @ac_ct_RANLIB@ -ac_ct_STRIP = @ac_ct_STRIP@ am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ -do_roken_rename_FALSE = @do_roken_rename_FALSE@ -do_roken_rename_TRUE = @do_roken_rename_TRUE@ +datarootdir = @datarootdir@ +docdir = @docdir@ dpagaix_cflags = @dpagaix_cflags@ dpagaix_ldadd = @dpagaix_ldadd@ dpagaix_ldflags = @dpagaix_ldflags@ -el_compat_FALSE = @el_compat_FALSE@ -el_compat_TRUE = @el_compat_TRUE@ +dvidir = @dvidir@ exec_prefix = @exec_prefix@ -have_err_h_FALSE = @have_err_h_FALSE@ -have_err_h_TRUE = @have_err_h_TRUE@ -have_fnmatch_h_FALSE = @have_fnmatch_h_FALSE@ -have_fnmatch_h_TRUE = @have_fnmatch_h_TRUE@ -have_glob_h_FALSE = @have_glob_h_FALSE@ -have_glob_h_TRUE = @have_glob_h_TRUE@ -have_ifaddrs_h_FALSE = @have_ifaddrs_h_FALSE@ -have_ifaddrs_h_TRUE = @have_ifaddrs_h_TRUE@ -have_vis_h_FALSE = @have_vis_h_FALSE@ -have_vis_h_TRUE = @have_vis_h_TRUE@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ +htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ +psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ -SUFFIXES = .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 -INCLUDES = -I$(top_builddir)/include $(INCLUDES_roken) -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUFFIXES = .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 +AM_CPPFLAGS = -I$(top_builddir)/include $(INCLUDES_roken) \ + -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER @do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME AM_CFLAGS = $(WFLAGS) CP = cp @@ -375,9 +348,10 @@ LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS) @KRB5_TRUE@ $(top_builddir)/lib/asn1/libasn1.la @KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la +@KRB5_TRUE@LIB_tsasl = $(top_builddir)/lib/tsasl/libtsasl.la @DCE_TRUE@LIB_kdfs = $(top_builddir)/lib/kdfs/libkdfs.la CHECK_LOCAL = -@KRB4_TRUE@krb4_sources = krb4.c kauth.c +@KRB4_TRUE@krb4_sources = krb4.c @KRB5_TRUE@krb5_sources = gssapi.c gss_userok.c ftpd_SOURCES = \ extern.h \ @@ -389,11 +363,13 @@ ftpd_SOURCES = \ pathnames.h \ popen.c \ security.c \ + kauth.c \ + klist.c \ $(krb4_sources) \ $(krb5_sources) EXTRA_ftpd_SOURCES = krb4.c kauth.c gssapi.c gss_userok.c -CLEANFILES = security.c security.h krb4.c gssapi.c ftpcmd.c +CLEANFILES = security.c security.h krb4.c gssapi.c man_MANS = ftpd.8 ftpusers.5 LDADD = ../common/libcommon.a \ $(LIB_otp) \ @@ -401,13 +377,14 @@ LDADD = ../common/libcommon.a \ $(LIB_krb5) \ $(LIB_kafs) \ $(LIB_krb4) \ - $(LIB_des) \ + $(LIB_hcrypto) \ $(LIB_roken) +EXTRA_DIST = $(man_MANS) all: all-am .SUFFIXES: -.SUFFIXES: .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .c .lo .o .obj .y +.SUFFIXES: .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .c .lo .o .obj .y $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -439,7 +416,7 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(libexecdir)" || $(mkdir_p) "$(DESTDIR)$(libexecdir)" + test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)" @list='$(libexec_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ @@ -467,7 +444,7 @@ clean-libexecPROGRAMS: done ftpd$(EXEEXT): $(ftpd_OBJECTS) $(ftpd_DEPENDENCIES) @rm -f ftpd$(EXEEXT) - $(LINK) $(ftpd_LDFLAGS) $(ftpd_OBJECTS) $(ftpd_LDADD) $(LIBS) + $(LINK) $(ftpd_OBJECTS) $(ftpd_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -485,37 +462,16 @@ distclean-compile: $(LTCOMPILE) -c -o $@ $< .y.c: - $(YACCCOMPILE) $< - if test -f y.tab.h; then \ - to=`echo "$*_H" | sed \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ - -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`; \ - sed "/^#/ s/Y_TAB_H/$$to/g" y.tab.h >$*.ht; \ - rm -f y.tab.h; \ - if cmp -s $*.ht $*.h; then \ - rm -f $*.ht ;\ - else \ - mv $*.ht $*.h; \ - fi; \ - fi - if test -f y.output; then \ - mv y.output $*.output; \ - fi - sed '/^#/ s|y\.tab\.c|$@|' y.tab.c >$@t && mv $@t $@ - rm -f y.tab.c + $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: install-man5: $(man5_MANS) $(man_MANS) @$(NORMAL_INSTALL) - test -z "$(man5dir)" || $(mkdir_p) "$(DESTDIR)$(man5dir)" + test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)" @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ @@ -560,7 +516,7 @@ uninstall-man5: done install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) - test -z "$(man8dir)" || $(mkdir_p) "$(DESTDIR)$(man8dir)" + test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ @@ -624,9 +580,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ - test -z "$(ETAGS_ARGS)$$tags$$unique" \ - || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) @@ -651,23 +609,21 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/../../.. $(distdir)/../../../cf - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ @@ -687,7 +643,7 @@ check: check-am all-am: Makefile $(PROGRAMS) $(MANS) all-local installdirs: for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \ - test -z "$$dir" || $(mkdir_p) "$$dir"; \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am @@ -709,7 +665,7 @@ clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: - -rm -f $(CONFIG_CLEAN_FILES) + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -723,7 +679,7 @@ clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ - distclean-libtool distclean-tags + distclean-tags dvi: dvi-am @@ -739,14 +695,22 @@ install-data-am: install-man @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-am + install-exec-am: install-libexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + install-info: install-info-am install-man: install-man5 install-man8 +install-pdf: install-pdf-am + +install-ps: install-ps-am + installcheck-am: maintainer-clean: maintainer-clean-am @@ -766,23 +730,29 @@ ps: ps-am ps-am: -uninstall-am: uninstall-info-am uninstall-libexecPROGRAMS \ - uninstall-man +uninstall-am: uninstall-libexecPROGRAMS uninstall-man + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook uninstall-man: uninstall-man5 uninstall-man8 +.MAKE: install-am install-data-am install-exec-am install-strip \ + uninstall-am + .PHONY: CTAGS GTAGS all all-am all-local check check-am check-local \ clean clean-generic clean-libexecPROGRAMS clean-libtool ctags \ - distclean distclean-compile distclean-generic \ + dist-hook distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-libexecPROGRAMS install-man \ - install-man5 install-man8 install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-info-am \ + install-data-am install-data-hook install-dvi install-dvi-am \ + install-exec install-exec-am install-exec-hook install-html \ + install-html-am install-info install-info-am \ + install-libexecPROGRAMS install-man install-man5 install-man8 \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am uninstall-hook \ uninstall-libexecPROGRAMS uninstall-man uninstall-man5 \ uninstall-man8 @@ -799,8 +769,8 @@ install-suid-programs: install-exec-hook: install-suid-programs -install-build-headers:: $(include_HEADERS) $(build_HEADERZ) - @foo='$(include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \ +install-build-headers:: $(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ) $(nobase_include_HEADERS) + @foo='$(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \ for f in $$foo; do \ f=`basename $$f`; \ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \ @@ -810,19 +780,31 @@ install-build-headers:: $(include_HEADERS) $(build_HEADERZ) echo " $(CP) $$file $(buildinclude)/$$f"; \ $(CP) $$file $(buildinclude)/$$f; \ fi ; \ + done ; \ + foo='$(nobase_include_HEADERS)'; \ + for f in $$foo; do \ + if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \ + else file="$$f"; fi; \ + $(mkdir_p) $(buildinclude)/`dirname $$f` ; \ + if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \ + : ; else \ + echo " $(CP) $$file $(buildinclude)/$$f"; \ + $(CP) $$file $(buildinclude)/$$f; \ + fi ; \ done all-local: install-build-headers check-local:: - @if test '$(CHECK_LOCAL)'; then \ + @if test '$(CHECK_LOCAL)' = "no-check-local"; then \ + foo=''; elif test '$(CHECK_LOCAL)'; then \ foo='$(CHECK_LOCAL)'; else \ foo='$(PROGRAMS)'; fi; \ if test "$$foo"; then \ failed=0; all=0; \ for i in $$foo; do \ all=`expr $$all + 1`; \ - if ./$$i --version > /dev/null 2>&1; then \ + if (./$$i --version && ./$$i --help) > /dev/null 2>&1; then \ echo "PASS: $$i"; \ else \ echo "FAIL: $$i"; \ @@ -838,7 +820,7 @@ check-local:: echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes"; \ - test "$$failed" -eq 0; \ + test "$$failed" -eq 0 || exit 1; \ fi .x.c: @@ -908,15 +890,40 @@ dist-cat8-mans: dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans install-cat-mans: - $(SHELL) $(top_srcdir)/cf/install-catman.sh "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS) + $(SHELL) $(top_srcdir)/cf/install-catman.sh install "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS) + +uninstall-cat-mans: + $(SHELL) $(top_srcdir)/cf/install-catman.sh uninstall "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS) install-data-hook: install-cat-mans +uninstall-hook: uninstall-cat-mans .et.h: $(COMPILE_ET) $< .et.c: $(COMPILE_ET) $< +# +# Useful target for debugging +# + +check-valgrind: + tobjdir=`cd $(top_builddir) && pwd` ; \ + tsrcdir=`cd $(top_srcdir) && pwd` ; \ + env TESTS_ENVIRONMENT="$${tobjdir}/libtool --mode execute valgrind --leak-check=full --trace-children=yes --quiet -q --num-callers=30 --suppressions=$${tsrcdir}/cf/valgrind-suppressions" make check + +# +# Target to please samba build farm, builds distfiles in-tree. +# Will break when automake changes... +# + +distdir-in-tree: $(DISTFILES) $(INFO_DEPS) + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" != .; then \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) distdir-in-tree) ; \ + fi ; \ + done + $(ftpd_OBJECTS): security.h security.c: diff --git a/crypto/heimdal/appl/ftp/ftpd/extern.h b/crypto/heimdal/appl/ftp/ftpd/extern.h index 751d04c..db40f2f 100644 --- a/crypto/heimdal/appl/ftp/ftpd/extern.h +++ b/crypto/heimdal/appl/ftp/ftpd/extern.h @@ -107,9 +107,12 @@ void klist(void); void cond_kdestroy(void); void kdestroy(void); void krbtkfile(const char *tkfile); -void afslog(const char *cell); +void afslog(const char *, int); void afsunlog(void); +extern int do_destroy_tickets; +extern char *k5ccname; + int find(char *); int builtin_ls(FILE*, const char*); @@ -130,6 +133,7 @@ extern int logging; extern int type; extern off_t file_size; extern off_t byte_count; +extern int ccc_passed; extern int form; extern int debug; diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpcmd.c b/crypto/heimdal/appl/ftp/ftpd/ftpcmd.c new file mode 100644 index 0000000..94eadee --- /dev/null +++ b/crypto/heimdal/appl/ftp/ftpd/ftpcmd.c @@ -0,0 +1,3551 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + A = 258, + B = 259, + C = 260, + E = 261, + F = 262, + I = 263, + L = 264, + N = 265, + P = 266, + R = 267, + S = 268, + T = 269, + SP = 270, + CRLF = 271, + COMMA = 272, + USER = 273, + PASS = 274, + ACCT = 275, + REIN = 276, + QUIT = 277, + PORT = 278, + PASV = 279, + TYPE = 280, + STRU = 281, + MODE = 282, + RETR = 283, + STOR = 284, + APPE = 285, + MLFL = 286, + MAIL = 287, + MSND = 288, + MSOM = 289, + MSAM = 290, + MRSQ = 291, + MRCP = 292, + ALLO = 293, + REST = 294, + RNFR = 295, + RNTO = 296, + ABOR = 297, + DELE = 298, + CWD = 299, + LIST = 300, + NLST = 301, + SITE = 302, + sTAT = 303, + HELP = 304, + NOOP = 305, + MKD = 306, + RMD = 307, + PWD = 308, + CDUP = 309, + STOU = 310, + SMNT = 311, + SYST = 312, + SIZE = 313, + MDTM = 314, + EPRT = 315, + EPSV = 316, + UMASK = 317, + IDLE = 318, + CHMOD = 319, + AUTH = 320, + ADAT = 321, + PROT = 322, + PBSZ = 323, + CCC = 324, + MIC = 325, + CONF = 326, + ENC = 327, + KAUTH = 328, + KLIST = 329, + KDESTROY = 330, + KRBTKFILE = 331, + AFSLOG = 332, + LOCATE = 333, + URL = 334, + FEAT = 335, + OPTS = 336, + LEXERR = 337, + STRING = 338, + NUMBER = 339 + }; +#endif +/* Tokens. */ +#define A 258 +#define B 259 +#define C 260 +#define E 261 +#define F 262 +#define I 263 +#define L 264 +#define N 265 +#define P 266 +#define R 267 +#define S 268 +#define T 269 +#define SP 270 +#define CRLF 271 +#define COMMA 272 +#define USER 273 +#define PASS 274 +#define ACCT 275 +#define REIN 276 +#define QUIT 277 +#define PORT 278 +#define PASV 279 +#define TYPE 280 +#define STRU 281 +#define MODE 282 +#define RETR 283 +#define STOR 284 +#define APPE 285 +#define MLFL 286 +#define MAIL 287 +#define MSND 288 +#define MSOM 289 +#define MSAM 290 +#define MRSQ 291 +#define MRCP 292 +#define ALLO 293 +#define REST 294 +#define RNFR 295 +#define RNTO 296 +#define ABOR 297 +#define DELE 298 +#define CWD 299 +#define LIST 300 +#define NLST 301 +#define SITE 302 +#define sTAT 303 +#define HELP 304 +#define NOOP 305 +#define MKD 306 +#define RMD 307 +#define PWD 308 +#define CDUP 309 +#define STOU 310 +#define SMNT 311 +#define SYST 312 +#define SIZE 313 +#define MDTM 314 +#define EPRT 315 +#define EPSV 316 +#define UMASK 317 +#define IDLE 318 +#define CHMOD 319 +#define AUTH 320 +#define ADAT 321 +#define PROT 322 +#define PBSZ 323 +#define CCC 324 +#define MIC 325 +#define CONF 326 +#define ENC 327 +#define KAUTH 328 +#define KLIST 329 +#define KDESTROY 330 +#define KRBTKFILE 331 +#define AFSLOG 332 +#define LOCATE 333 +#define URL 334 +#define FEAT 335 +#define OPTS 336 +#define LEXERR 337 +#define STRING 338 +#define NUMBER 339 + + + + +/* Copy the first part of user declarations. */ +#line 43 "ftpcmd.y" + + +#include "ftpd_locl.h" +RCSID("$Id: ftpcmd.y 15677 2005-07-19 18:33:08Z lha $"); + +off_t restart_point; + +static int hasyyerrored; + + +static int cmd_type; +static int cmd_form; +static int cmd_bytesz; +char cbuf[64*1024]; +char *fromname; + +struct tab { + char *name; + short token; + short state; + short implemented; /* 1 if command is implemented */ + char *help; +}; + +extern struct tab cmdtab[]; +extern struct tab sitetab[]; + +static char *copy (char *); +static void help (struct tab *, char *); +static struct tab * + lookup (struct tab *, char *); +static void sizecmd (char *); +static RETSIGTYPE toolong (int); +static int yylex (void); + +/* This is for bison */ + +#if !defined(alloca) && !defined(HAVE_ALLOCA) +#define alloca(x) malloc(x) +#endif + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 86 "ftpcmd.y" +{ + int i; + char *s; +} +/* Line 193 of yacc.c. */ +#line 312 "ftpcmd.c" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 216 of yacc.c. */ +#line 325 "ftpcmd.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 327 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 85 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 18 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 98 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 317 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 339 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 4, 7, 10, 16, 22, 28, 34, + 38, 42, 48, 54, 60, 66, 72, 82, 88, 94, + 100, 104, 110, 114, 120, 126, 130, 136, 142, 146, + 150, 156, 160, 166, 170, 176, 182, 186, 190, 194, + 200, 206, 214, 220, 228, 238, 244, 252, 260, 266, + 272, 280, 286, 294, 302, 308, 314, 318, 324, 330, + 334, 337, 343, 349, 354, 359, 365, 371, 375, 380, + 385, 390, 392, 393, 395, 397, 409, 411, 413, 415, + 417, 421, 423, 427, 429, 431, 435, 438, 440, 442, + 444, 446, 448, 450, 452, 454, 456, 458, 460 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 86, 0, -1, -1, 86, 87, -1, 86, 88, -1, + 18, 15, 89, 16, 102, -1, 19, 15, 90, 16, + 102, -1, 23, 15, 92, 16, 102, -1, 60, 15, + 83, 16, 102, -1, 24, 16, 101, -1, 61, 16, + 101, -1, 61, 15, 83, 16, 101, -1, 25, 15, + 94, 16, 102, -1, 26, 15, 95, 16, 102, -1, + 27, 15, 96, 16, 102, -1, 38, 15, 84, 16, + 102, -1, 38, 15, 84, 15, 12, 15, 84, 16, + 102, -1, 28, 15, 97, 16, 101, -1, 29, 15, + 97, 16, 101, -1, 30, 15, 97, 16, 101, -1, + 46, 16, 101, -1, 46, 15, 83, 16, 101, -1, + 45, 16, 101, -1, 45, 15, 97, 16, 101, -1, + 48, 15, 97, 16, 101, -1, 48, 16, 102, -1, + 43, 15, 97, 16, 100, -1, 41, 15, 97, 16, + 100, -1, 42, 16, 102, -1, 44, 16, 101, -1, + 44, 15, 97, 16, 101, -1, 49, 16, 102, -1, + 49, 15, 83, 16, 102, -1, 50, 16, 102, -1, + 51, 15, 97, 16, 101, -1, 52, 15, 97, 16, + 100, -1, 53, 16, 101, -1, 54, 16, 101, -1, + 80, 16, 102, -1, 81, 15, 83, 16, 102, -1, + 47, 15, 49, 16, 102, -1, 47, 15, 49, 15, + 83, 16, 102, -1, 47, 15, 62, 16, 101, -1, + 47, 15, 62, 15, 99, 16, 100, -1, 47, 15, + 64, 15, 99, 15, 97, 16, 100, -1, 47, 15, + 63, 16, 102, -1, 47, 15, 63, 15, 84, 16, + 102, -1, 47, 15, 73, 15, 83, 16, 101, -1, + 47, 15, 74, 16, 101, -1, 47, 15, 75, 16, + 101, -1, 47, 15, 76, 15, 83, 16, 101, -1, + 47, 15, 77, 16, 101, -1, 47, 15, 77, 15, + 83, 16, 101, -1, 47, 15, 78, 15, 83, 16, + 101, -1, 47, 15, 79, 16, 102, -1, 55, 15, + 97, 16, 101, -1, 57, 16, 102, -1, 58, 15, + 97, 16, 101, -1, 59, 15, 97, 16, 101, -1, + 22, 16, 102, -1, 1, 16, -1, 40, 15, 97, + 16, 100, -1, 39, 15, 91, 16, 102, -1, 65, + 15, 83, 16, -1, 66, 15, 83, 16, -1, 68, + 15, 84, 16, 102, -1, 67, 15, 83, 16, 102, + -1, 69, 16, 102, -1, 70, 15, 83, 16, -1, + 71, 15, 83, 16, -1, 72, 15, 83, 16, -1, + 83, -1, -1, 83, -1, 84, -1, 84, 17, 84, + 17, 84, 17, 84, 17, 84, 17, 84, -1, 10, + -1, 14, -1, 5, -1, 3, -1, 3, 15, 93, + -1, 6, -1, 6, 15, 93, -1, 8, -1, 9, + -1, 9, 15, 91, -1, 9, 91, -1, 7, -1, + 12, -1, 11, -1, 13, -1, 4, -1, 5, -1, + 98, -1, 83, -1, 84, -1, 101, -1, 102, -1, + -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 129, 129, 131, 136, 140, 146, 153, 164, 170, + 175, 180, 186, 223, 237, 251, 257, 263, 272, 281, + 290, 295, 304, 309, 315, 322, 327, 334, 348, 353, + 358, 365, 370, 387, 392, 399, 406, 411, 416, 426, + 433, 438, 443, 451, 464, 478, 485, 502, 525, 530, + 539, 552, 563, 576, 583, 588, 595, 613, 630, 658, + 665, 671, 681, 691, 696, 701, 706, 711, 716, 721, + 726, 734, 739, 742, 746, 750, 763, 767, 771, 778, + 783, 788, 793, 798, 802, 807, 813, 821, 825, 829, + 836, 840, 844, 851, 879, 883, 909, 917, 928 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "A", "B", "C", "E", "F", "I", "L", "N", + "P", "R", "S", "T", "SP", "CRLF", "COMMA", "USER", "PASS", "ACCT", + "REIN", "QUIT", "PORT", "PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", + "APPE", "MLFL", "MAIL", "MSND", "MSOM", "MSAM", "MRSQ", "MRCP", "ALLO", + "REST", "RNFR", "RNTO", "ABOR", "DELE", "CWD", "LIST", "NLST", "SITE", + "sTAT", "HELP", "NOOP", "MKD", "RMD", "PWD", "CDUP", "STOU", "SMNT", + "SYST", "SIZE", "MDTM", "EPRT", "EPSV", "UMASK", "IDLE", "CHMOD", "AUTH", + "ADAT", "PROT", "PBSZ", "CCC", "MIC", "CONF", "ENC", "KAUTH", "KLIST", + "KDESTROY", "KRBTKFILE", "AFSLOG", "LOCATE", "URL", "FEAT", "OPTS", + "LEXERR", "STRING", "NUMBER", "$accept", "cmd_list", "cmd", "rcmd", + "username", "password", "byte_size", "host_port", "form_code", + "type_code", "struct_code", "mode_code", "pathname", "pathstring", + "octal_number", "check_login_no_guest", "check_login", "check_secure", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 85, 86, 86, 86, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 89, 90, 90, 91, 92, 93, 93, 93, 94, + 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, + 96, 96, 96, 97, 98, 99, 100, 101, 102 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 2, 2, 5, 5, 5, 5, 3, + 3, 5, 5, 5, 5, 5, 9, 5, 5, 5, + 3, 5, 3, 5, 5, 3, 5, 5, 3, 3, + 5, 3, 5, 3, 5, 5, 3, 3, 3, 5, + 5, 7, 5, 7, 9, 5, 7, 7, 5, 5, + 7, 5, 7, 7, 5, 5, 3, 5, 5, 3, + 2, 5, 5, 4, 4, 5, 5, 3, 4, 4, + 4, 1, 0, 1, 1, 11, 1, 1, 1, 1, + 3, 1, 3, 1, 1, 3, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, + 60, 0, 72, 98, 0, 98, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 98, 0, 0, 98, + 0, 98, 0, 98, 0, 0, 98, 0, 98, 98, + 0, 0, 98, 98, 0, 98, 0, 0, 0, 0, + 98, 0, 0, 0, 0, 98, 0, 0, 0, 98, + 0, 71, 0, 73, 0, 59, 0, 0, 9, 97, + 79, 81, 83, 84, 0, 87, 89, 88, 0, 91, + 92, 90, 0, 94, 0, 93, 0, 0, 0, 74, + 0, 0, 0, 28, 0, 0, 29, 0, 22, 0, + 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 25, 0, 31, 33, 0, 0, 36, + 37, 0, 56, 0, 0, 0, 0, 10, 0, 0, + 0, 0, 67, 0, 0, 0, 38, 0, 98, 98, + 0, 98, 0, 0, 0, 86, 98, 98, 98, 98, + 98, 98, 0, 98, 98, 98, 98, 98, 98, 98, + 98, 0, 98, 0, 98, 0, 98, 0, 0, 98, + 98, 0, 0, 98, 0, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 63, 64, 98, 98, 68, + 69, 70, 98, 5, 6, 0, 7, 78, 76, 77, + 80, 82, 85, 12, 13, 14, 17, 18, 19, 0, + 15, 62, 61, 96, 27, 26, 30, 23, 21, 0, + 40, 95, 0, 42, 0, 45, 0, 0, 48, 49, + 0, 0, 51, 0, 54, 24, 32, 34, 35, 55, + 57, 58, 8, 11, 66, 65, 39, 0, 0, 98, + 98, 98, 0, 98, 98, 98, 98, 0, 0, 41, + 43, 46, 0, 47, 50, 52, 53, 0, 98, 98, + 0, 16, 44, 0, 0, 0, 75 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 1, 48, 49, 102, 104, 130, 107, 240, 114, + 118, 122, 124, 125, 262, 252, 253, 109 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -196 +static const yytype_int16 yypact[] = +{ + -196, 246, -196, 3, 13, 20, 11, 24, 21, 26, + 30, 45, 66, 67, 68, 69, 70, 71, 72, 76, + 73, -7, -5, 15, 78, 28, 32, 80, 79, 82, + 83, 91, 93, 94, 96, 97, 98, 38, 100, 101, + 102, 103, 104, 106, 107, 108, 111, 109, -196, -196, + -196, -66, 36, -196, 14, -196, 12, 22, 1, 46, + 46, 46, 25, 48, 46, 46, -196, 46, 46, -196, + 46, -196, 53, -196, 27, 46, -196, 55, -196, -196, + 46, 46, -196, -196, 46, -196, 46, 46, 56, 59, + -196, 60, 61, 62, 63, -196, 65, 77, 85, -196, + 86, -196, 114, -196, 115, -196, 120, 130, -196, -196, + 135, 136, -196, -11, 138, -196, -196, -196, 139, -196, + -196, -196, 143, -196, 145, -196, 147, 156, 47, -196, + 157, 162, 165, -196, 166, 168, -196, 170, -196, 174, + -196, 49, 52, 54, 137, 177, 178, 179, 181, 64, + 182, 183, 184, -196, 185, -196, -196, 186, 187, -196, + -196, 188, -196, 189, 190, 191, 192, -196, 193, 194, + 195, 196, -196, 197, 198, 199, -196, 200, -196, -196, + 133, -196, 2, 2, 48, -196, -196, -196, -196, -196, + -196, -196, 206, -196, -196, -196, -196, -196, -196, -196, + -196, 110, -196, 140, -196, 141, -196, 140, 144, -196, + -196, 146, 148, -196, 149, -196, -196, -196, -196, -196, + -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, + -196, -196, -196, -196, -196, 202, -196, -196, -196, -196, + -196, -196, -196, -196, -196, -196, -196, -196, -196, 205, + -196, -196, -196, -196, -196, -196, -196, -196, -196, 207, + -196, -196, 210, -196, 212, -196, 215, 217, -196, -196, + 218, 219, -196, 221, -196, -196, -196, -196, -196, -196, + -196, -196, -196, -196, -196, -196, -196, 155, 158, -196, + -196, -196, 46, -196, -196, -196, -196, 204, 224, -196, + -196, -196, 225, -196, -196, -196, -196, 159, -196, -196, + 227, -196, -196, 161, 231, 167, -196 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -196, -196, -196, -196, -196, -196, -110, -196, 39, -196, + -196, -196, -9, -196, 42, -195, -33, -53 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint16 yytable[] = +{ + 105, 254, 255, 185, 184, 119, 120, 237, 68, 69, + 70, 71, 238, 133, 121, 110, 239, 101, 111, 50, + 112, 113, 108, 153, 278, 155, 156, 53, 51, 115, + 72, 73, 162, 116, 117, 52, 136, 55, 138, 54, + 140, 56, 172, 75, 76, 57, 176, 77, 78, 159, + 160, 126, 127, 89, 90, 131, 132, 167, 134, 135, + 58, 137, 192, 193, 201, 202, 152, 203, 204, 205, + 206, 157, 158, 129, 242, 161, 141, 163, 164, 212, + 213, 59, 60, 61, 62, 63, 64, 65, 67, 142, + 143, 144, 66, 74, 80, 300, 79, 81, 106, 82, + 145, 146, 147, 148, 149, 150, 151, 83, 84, 128, + 85, 86, 87, 88, 312, 91, 92, 93, 94, 103, + 95, 96, 97, 98, 100, 233, 234, 99, 236, 123, + 178, 179, 129, 243, 244, 245, 139, 180, 154, 165, + 250, 251, 166, 168, 169, 170, 181, 171, 173, 260, + 182, 183, 207, 265, 186, 187, 246, 247, 248, 188, + 174, 189, 274, 190, 276, 256, 257, 258, 175, 177, + 282, 263, 191, 194, 284, 285, 268, 269, 195, 286, + 272, 196, 197, 275, 198, 277, 199, 279, 280, 281, + 200, 283, 208, 259, 209, 210, 211, 214, 0, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 229, 230, 231, 232, 235, 249, 287, + 288, 307, 241, 289, 261, 264, 290, 267, 291, 270, + 292, 271, 273, 293, 294, 295, 299, 296, 301, 297, + 308, 309, 298, 310, 313, 314, 2, 3, 315, 266, + 0, 316, 0, 0, 0, 311, 0, 0, 0, 0, + 303, 304, 305, 306, 4, 5, 0, 0, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, + 0, 0, 0, 302, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 0, 33, 34, 35, 36, 37, 0, 0, + 0, 38, 39, 40, 41, 42, 43, 44, 45, 0, + 0, 0, 0, 0, 0, 0, 46, 47 +}; + +static const yytype_int16 yycheck[] = +{ + 53, 196, 197, 113, 15, 4, 5, 5, 15, 16, + 15, 16, 10, 66, 13, 3, 14, 83, 6, 16, + 8, 9, 55, 76, 219, 78, 79, 16, 15, 7, + 15, 16, 85, 11, 12, 15, 69, 16, 71, 15, + 73, 15, 95, 15, 16, 15, 99, 15, 16, 82, + 83, 60, 61, 15, 16, 64, 65, 90, 67, 68, + 15, 70, 15, 16, 15, 16, 75, 15, 16, 15, + 16, 80, 81, 84, 184, 84, 49, 86, 87, 15, + 16, 15, 15, 15, 15, 15, 15, 15, 15, 62, + 63, 64, 16, 15, 15, 290, 16, 15, 84, 16, + 73, 74, 75, 76, 77, 78, 79, 16, 15, 84, + 16, 15, 15, 15, 309, 15, 15, 15, 15, 83, + 16, 15, 15, 15, 15, 178, 179, 16, 181, 83, + 16, 16, 84, 186, 187, 188, 83, 17, 83, 83, + 193, 194, 83, 83, 83, 83, 16, 84, 83, 202, + 15, 15, 15, 206, 16, 16, 189, 190, 191, 16, + 83, 16, 215, 16, 217, 198, 199, 200, 83, 83, + 223, 204, 16, 16, 227, 228, 209, 210, 16, 232, + 213, 16, 16, 216, 16, 218, 16, 220, 221, 222, + 16, 224, 15, 83, 16, 16, 15, 15, -1, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 84, 12, 17, + 15, 17, 183, 16, 84, 84, 16, 83, 16, 83, + 15, 83, 83, 16, 16, 16, 289, 16, 291, 84, + 16, 16, 84, 84, 17, 84, 0, 1, 17, 207, + -1, 84, -1, -1, -1, 308, -1, -1, -1, -1, + 293, 294, 295, 296, 18, 19, -1, -1, 22, 23, + 24, 25, 26, 27, 28, 29, 30, -1, -1, -1, + -1, -1, -1, 292, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, -1, 57, 58, 59, 60, 61, -1, -1, + -1, 65, 66, 67, 68, 69, 70, 71, 72, -1, + -1, -1, -1, -1, -1, -1, 80, 81 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 86, 0, 1, 18, 19, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 57, 58, 59, 60, 61, 65, 66, + 67, 68, 69, 70, 71, 72, 80, 81, 87, 88, + 16, 15, 15, 16, 15, 16, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 16, 15, 15, 16, + 15, 16, 15, 16, 15, 15, 16, 15, 16, 16, + 15, 15, 16, 16, 15, 16, 15, 15, 15, 15, + 16, 15, 15, 15, 15, 16, 15, 15, 15, 16, + 15, 83, 89, 83, 90, 102, 84, 92, 101, 102, + 3, 6, 8, 9, 94, 7, 11, 12, 95, 4, + 5, 13, 96, 83, 97, 98, 97, 97, 84, 84, + 91, 97, 97, 102, 97, 97, 101, 97, 101, 83, + 101, 49, 62, 63, 64, 73, 74, 75, 76, 77, + 78, 79, 97, 102, 83, 102, 102, 97, 97, 101, + 101, 97, 102, 97, 97, 83, 83, 101, 83, 83, + 83, 84, 102, 83, 83, 83, 102, 83, 16, 16, + 17, 16, 15, 15, 15, 91, 16, 16, 16, 16, + 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 15, 16, 15, 16, 15, 16, 15, 15, 16, + 16, 15, 15, 16, 15, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 102, 102, 84, 102, 5, 10, 14, + 93, 93, 91, 102, 102, 102, 101, 101, 101, 12, + 102, 102, 100, 101, 100, 100, 101, 101, 101, 83, + 102, 84, 99, 101, 84, 102, 99, 83, 101, 101, + 83, 83, 101, 83, 102, 101, 102, 101, 100, 101, + 101, 101, 102, 101, 102, 102, 102, 17, 15, 16, + 16, 16, 15, 16, 16, 16, 16, 84, 84, 102, + 100, 102, 97, 101, 101, 101, 101, 17, 16, 16, + 84, 102, 100, 17, 84, 17, 84 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 3: +#line 132 "ftpcmd.y" + { + fromname = (char *) 0; + restart_point = (off_t) 0; + } + break; + + case 5: +#line 141 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + user((yyvsp[(3) - (5)].s)); + free((yyvsp[(3) - (5)].s)); + } + break; + + case 6: +#line 147 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + pass((yyvsp[(3) - (5)].s)); + memset ((yyvsp[(3) - (5)].s), 0, strlen((yyvsp[(3) - (5)].s))); + free((yyvsp[(3) - (5)].s)); + } + break; + + case 7: +#line 154 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + usedefault = 0; + if (pdata >= 0) { + close(pdata); + pdata = -1; + } + reply(200, "PORT command successful."); + } + } + break; + + case 8: +#line 165 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + eprt ((yyvsp[(3) - (5)].s)); + free ((yyvsp[(3) - (5)].s)); + } + break; + + case 9: +#line 171 "ftpcmd.y" + { + if((yyvsp[(3) - (3)].i)) + pasv (); + } + break; + + case 10: +#line 176 "ftpcmd.y" + { + if((yyvsp[(3) - (3)].i)) + epsv (NULL); + } + break; + + case 11: +#line 181 "ftpcmd.y" + { + if((yyvsp[(5) - (5)].i)) + epsv ((yyvsp[(3) - (5)].s)); + free ((yyvsp[(3) - (5)].s)); + } + break; + + case 12: +#line 187 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + switch (cmd_type) { + + case TYPE_A: + if (cmd_form == FORM_N) { + reply(200, "Type set to A."); + type = cmd_type; + form = cmd_form; + } else + reply(504, "Form must be N."); + break; + + case TYPE_E: + reply(504, "Type E not implemented."); + break; + + case TYPE_I: + reply(200, "Type set to I."); + type = cmd_type; + break; + + case TYPE_L: +#if NBBY == 8 + if (cmd_bytesz == 8) { + reply(200, + "Type set to L (byte size 8)."); + type = cmd_type; + } else + reply(504, "Byte size must be 8."); +#else /* NBBY == 8 */ + UNIMPLEMENTED for NBBY != 8 +#endif /* NBBY == 8 */ + } + } + } + break; + + case 13: +#line 224 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + switch ((yyvsp[(3) - (5)].i)) { + + case STRU_F: + reply(200, "STRU F ok."); + break; + + default: + reply(504, "Unimplemented STRU type."); + } + } + } + break; + + case 14: +#line 238 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + switch ((yyvsp[(3) - (5)].i)) { + + case MODE_S: + reply(200, "MODE S ok."); + break; + + default: + reply(502, "Unimplemented MODE type."); + } + } + } + break; + + case 15: +#line 252 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + reply(202, "ALLO command ignored."); + } + } + break; + + case 16: +#line 258 "ftpcmd.y" + { + if ((yyvsp[(9) - (9)].i)) { + reply(202, "ALLO command ignored."); + } + } + break; + + case 17: +#line 264 "ftpcmd.y" + { + char *name = (yyvsp[(3) - (5)].s); + + if ((yyvsp[(5) - (5)].i) && name != NULL) + retrieve(0, name); + if (name != NULL) + free(name); + } + break; + + case 18: +#line 273 "ftpcmd.y" + { + char *name = (yyvsp[(3) - (5)].s); + + if ((yyvsp[(5) - (5)].i) && name != NULL) + do_store(name, "w", 0); + if (name != NULL) + free(name); + } + break; + + case 19: +#line 282 "ftpcmd.y" + { + char *name = (yyvsp[(3) - (5)].s); + + if ((yyvsp[(5) - (5)].i) && name != NULL) + do_store(name, "a", 0); + if (name != NULL) + free(name); + } + break; + + case 20: +#line 291 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + send_file_list("."); + } + break; + + case 21: +#line 296 "ftpcmd.y" + { + char *name = (yyvsp[(3) - (5)].s); + + if ((yyvsp[(5) - (5)].i) && name != NULL) + send_file_list(name); + if (name != NULL) + free(name); + } + break; + + case 22: +#line 305 "ftpcmd.y" + { + if((yyvsp[(3) - (3)].i)) + list_file("."); + } + break; + + case 23: +#line 310 "ftpcmd.y" + { + if((yyvsp[(5) - (5)].i)) + list_file((yyvsp[(3) - (5)].s)); + free((yyvsp[(3) - (5)].s)); + } + break; + + case 24: +#line 316 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) + statfilecmd((yyvsp[(3) - (5)].s)); + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 25: +#line 323 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + statcmd(); + } + break; + + case 26: +#line 328 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) + do_delete((yyvsp[(3) - (5)].s)); + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 27: +#line 335 "ftpcmd.y" + { + if((yyvsp[(5) - (5)].i)){ + if (fromname) { + renamecmd(fromname, (yyvsp[(3) - (5)].s)); + free(fromname); + fromname = (char *) 0; + } else { + reply(503, "Bad sequence of commands."); + } + } + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 28: +#line 349 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + reply(225, "ABOR command successful."); + } + break; + + case 29: +#line 354 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + cwd(pw->pw_dir); + } + break; + + case 30: +#line 359 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) + cwd((yyvsp[(3) - (5)].s)); + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 31: +#line 366 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + help(cmdtab, (char *) 0); + } + break; + + case 32: +#line 371 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + char *cp = (yyvsp[(3) - (5)].s); + + if (strncasecmp(cp, "SITE", 4) == 0) { + cp = (yyvsp[(3) - (5)].s) + 4; + if (*cp == ' ') + cp++; + if (*cp) + help(sitetab, cp); + else + help(sitetab, (char *) 0); + } else + help(cmdtab, (yyvsp[(3) - (5)].s)); + } + } + break; + + case 33: +#line 388 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + reply(200, "NOOP command successful."); + } + break; + + case 34: +#line 393 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) + makedir((yyvsp[(3) - (5)].s)); + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 35: +#line 400 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) + removedir((yyvsp[(3) - (5)].s)); + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 36: +#line 407 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + pwd(); + } + break; + + case 37: +#line 412 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + cwd(".."); + } + break; + + case 38: +#line 417 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) { + lreply(211, "Supported features:"); + lreply(0, " MDTM"); + lreply(0, " REST STREAM"); + lreply(0, " SIZE"); + reply(211, "End"); + } + } + break; + + case 39: +#line 427 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + reply(501, "Bad options"); + free ((yyvsp[(3) - (5)].s)); + } + break; + + case 40: +#line 434 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + help(sitetab, (char *) 0); + } + break; + + case 41: +#line 439 "ftpcmd.y" + { + if ((yyvsp[(7) - (7)].i)) + help(sitetab, (yyvsp[(5) - (7)].s)); + } + break; + + case 42: +#line 444 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + int oldmask = umask(0); + umask(oldmask); + reply(200, "Current UMASK is %03o", oldmask); + } + } + break; + + case 43: +#line 452 "ftpcmd.y" + { + if ((yyvsp[(7) - (7)].i)) { + if (((yyvsp[(5) - (7)].i) == -1) || ((yyvsp[(5) - (7)].i) > 0777)) { + reply(501, "Bad UMASK value"); + } else { + int oldmask = umask((yyvsp[(5) - (7)].i)); + reply(200, + "UMASK set to %03o (was %03o)", + (yyvsp[(5) - (7)].i), oldmask); + } + } + } + break; + + case 44: +#line 465 "ftpcmd.y" + { + if ((yyvsp[(9) - (9)].i) && (yyvsp[(7) - (9)].s) != NULL) { + if ((yyvsp[(5) - (9)].i) > 0777) + reply(501, + "CHMOD: Mode value must be between 0 and 0777"); + else if (chmod((yyvsp[(7) - (9)].s), (yyvsp[(5) - (9)].i)) < 0) + perror_reply(550, (yyvsp[(7) - (9)].s)); + else + reply(200, "CHMOD command successful."); + } + if ((yyvsp[(7) - (9)].s) != NULL) + free((yyvsp[(7) - (9)].s)); + } + break; + + case 45: +#line 479 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + reply(200, + "Current IDLE time limit is %d seconds; max %d", + ftpd_timeout, maxtimeout); + } + break; + + case 46: +#line 486 "ftpcmd.y" + { + if ((yyvsp[(7) - (7)].i)) { + if ((yyvsp[(5) - (7)].i) < 30 || (yyvsp[(5) - (7)].i) > maxtimeout) { + reply(501, + "Maximum IDLE time must be between 30 and %d seconds", + maxtimeout); + } else { + ftpd_timeout = (yyvsp[(5) - (7)].i); + alarm((unsigned) ftpd_timeout); + reply(200, + "Maximum IDLE time set to %d seconds", + ftpd_timeout); + } + } + } + break; + + case 47: +#line 503 "ftpcmd.y" + { +#ifdef KRB4 + char *p; + + if(guest) + reply(500, "Can't be done as guest."); + else{ + if((yyvsp[(7) - (7)].i) && (yyvsp[(5) - (7)].s) != NULL){ + p = strpbrk((yyvsp[(5) - (7)].s), " \t"); + if(p){ + *p++ = 0; + kauth((yyvsp[(5) - (7)].s), p + strspn(p, " \t")); + }else + kauth((yyvsp[(5) - (7)].s), NULL); + } + } + if((yyvsp[(5) - (7)].s) != NULL) + free((yyvsp[(5) - (7)].s)); +#else + reply(500, "Command not implemented."); +#endif + } + break; + + case 48: +#line 526 "ftpcmd.y" + { + if((yyvsp[(5) - (5)].i)) + klist(); + } + break; + + case 49: +#line 531 "ftpcmd.y" + { +#ifdef KRB4 + if((yyvsp[(5) - (5)].i)) + kdestroy(); +#else + reply(500, "Command not implemented."); +#endif + } + break; + + case 50: +#line 540 "ftpcmd.y" + { +#ifdef KRB4 + if(guest) + reply(500, "Can't be done as guest."); + else if((yyvsp[(7) - (7)].i) && (yyvsp[(5) - (7)].s)) + krbtkfile((yyvsp[(5) - (7)].s)); + if((yyvsp[(5) - (7)].s)) + free((yyvsp[(5) - (7)].s)); +#else + reply(500, "Command not implemented."); +#endif + } + break; + + case 51: +#line 553 "ftpcmd.y" + { +#if defined(KRB4) || defined(KRB5) + if(guest) + reply(500, "Can't be done as guest."); + else if((yyvsp[(5) - (5)].i)) + afslog(NULL, 0); +#else + reply(500, "Command not implemented."); +#endif + } + break; + + case 52: +#line 564 "ftpcmd.y" + { +#if defined(KRB4) || defined(KRB5) + if(guest) + reply(500, "Can't be done as guest."); + else if((yyvsp[(7) - (7)].i)) + afslog((yyvsp[(5) - (7)].s), 0); + if((yyvsp[(5) - (7)].s)) + free((yyvsp[(5) - (7)].s)); +#else + reply(500, "Command not implemented."); +#endif + } + break; + + case 53: +#line 577 "ftpcmd.y" + { + if((yyvsp[(7) - (7)].i) && (yyvsp[(5) - (7)].s) != NULL) + find((yyvsp[(5) - (7)].s)); + if((yyvsp[(5) - (7)].s) != NULL) + free((yyvsp[(5) - (7)].s)); + } + break; + + case 54: +#line 584 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + reply(200, "http://www.pdc.kth.se/heimdal/"); + } + break; + + case 55: +#line 589 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) + do_store((yyvsp[(3) - (5)].s), "w", 1); + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 56: +#line 596 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) { +#if !defined(WIN32) && !defined(__EMX__) && !defined(__OS2__) && !defined(__CYGWIN32__) + reply(215, "UNIX Type: L%d", NBBY); +#else + reply(215, "UNKNOWN Type: L%d", NBBY); +#endif + } + } + break; + + case 57: +#line 614 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) + sizecmd((yyvsp[(3) - (5)].s)); + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 58: +#line 631 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s) != NULL) { + struct stat stbuf; + if (stat((yyvsp[(3) - (5)].s), &stbuf) < 0) + reply(550, "%s: %s", + (yyvsp[(3) - (5)].s), strerror(errno)); + else if (!S_ISREG(stbuf.st_mode)) { + reply(550, + "%s: not a plain file.", (yyvsp[(3) - (5)].s)); + } else { + struct tm *t; + time_t mtime = stbuf.st_mtime; + + t = gmtime(&mtime); + reply(213, + "%04d%02d%02d%02d%02d%02d", + t->tm_year + 1900, + t->tm_mon + 1, + t->tm_mday, + t->tm_hour, + t->tm_min, + t->tm_sec); + } + } + if ((yyvsp[(3) - (5)].s) != NULL) + free((yyvsp[(3) - (5)].s)); + } + break; + + case 59: +#line 659 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) { + reply(221, "Goodbye."); + dologout(0); + } + } + break; + + case 60: +#line 666 "ftpcmd.y" + { + yyerrok; + } + break; + + case 61: +#line 672 "ftpcmd.y" + { + restart_point = (off_t) 0; + if ((yyvsp[(5) - (5)].i) && (yyvsp[(3) - (5)].s)) { + fromname = renamefrom((yyvsp[(3) - (5)].s)); + if (fromname == (char *) 0 && (yyvsp[(3) - (5)].s)) { + free((yyvsp[(3) - (5)].s)); + } + } + } + break; + + case 62: +#line 682 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) { + fromname = (char *) 0; + restart_point = (yyvsp[(3) - (5)].i); /* XXX $3 is only "int" */ + reply(350, "Restarting at %ld. %s", + (long)restart_point, + "Send STORE or RETRIEVE to initiate transfer."); + } + } + break; + + case 63: +#line 692 "ftpcmd.y" + { + auth((yyvsp[(3) - (4)].s)); + free((yyvsp[(3) - (4)].s)); + } + break; + + case 64: +#line 697 "ftpcmd.y" + { + adat((yyvsp[(3) - (4)].s)); + free((yyvsp[(3) - (4)].s)); + } + break; + + case 65: +#line 702 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + pbsz((yyvsp[(3) - (5)].i)); + } + break; + + case 66: +#line 707 "ftpcmd.y" + { + if ((yyvsp[(5) - (5)].i)) + prot((yyvsp[(3) - (5)].s)); + } + break; + + case 67: +#line 712 "ftpcmd.y" + { + if ((yyvsp[(3) - (3)].i)) + ccc(); + } + break; + + case 68: +#line 717 "ftpcmd.y" + { + mec((yyvsp[(3) - (4)].s), prot_safe); + free((yyvsp[(3) - (4)].s)); + } + break; + + case 69: +#line 722 "ftpcmd.y" + { + mec((yyvsp[(3) - (4)].s), prot_confidential); + free((yyvsp[(3) - (4)].s)); + } + break; + + case 70: +#line 727 "ftpcmd.y" + { + mec((yyvsp[(3) - (4)].s), prot_private); + free((yyvsp[(3) - (4)].s)); + } + break; + + case 72: +#line 739 "ftpcmd.y" + { + (yyval.s) = (char *)calloc(1, sizeof(char)); + } + break; + + case 75: +#line 752 "ftpcmd.y" + { + struct sockaddr_in *sin4 = (struct sockaddr_in *)data_dest; + + sin4->sin_family = AF_INET; + sin4->sin_port = htons((yyvsp[(9) - (11)].i) * 256 + (yyvsp[(11) - (11)].i)); + sin4->sin_addr.s_addr = + htonl(((yyvsp[(1) - (11)].i) << 24) | ((yyvsp[(3) - (11)].i) << 16) | ((yyvsp[(5) - (11)].i) << 8) | (yyvsp[(7) - (11)].i)); + } + break; + + case 76: +#line 764 "ftpcmd.y" + { + (yyval.i) = FORM_N; + } + break; + + case 77: +#line 768 "ftpcmd.y" + { + (yyval.i) = FORM_T; + } + break; + + case 78: +#line 772 "ftpcmd.y" + { + (yyval.i) = FORM_C; + } + break; + + case 79: +#line 779 "ftpcmd.y" + { + cmd_type = TYPE_A; + cmd_form = FORM_N; + } + break; + + case 80: +#line 784 "ftpcmd.y" + { + cmd_type = TYPE_A; + cmd_form = (yyvsp[(3) - (3)].i); + } + break; + + case 81: +#line 789 "ftpcmd.y" + { + cmd_type = TYPE_E; + cmd_form = FORM_N; + } + break; + + case 82: +#line 794 "ftpcmd.y" + { + cmd_type = TYPE_E; + cmd_form = (yyvsp[(3) - (3)].i); + } + break; + + case 83: +#line 799 "ftpcmd.y" + { + cmd_type = TYPE_I; + } + break; + + case 84: +#line 803 "ftpcmd.y" + { + cmd_type = TYPE_L; + cmd_bytesz = NBBY; + } + break; + + case 85: +#line 808 "ftpcmd.y" + { + cmd_type = TYPE_L; + cmd_bytesz = (yyvsp[(3) - (3)].i); + } + break; + + case 86: +#line 814 "ftpcmd.y" + { + cmd_type = TYPE_L; + cmd_bytesz = (yyvsp[(2) - (2)].i); + } + break; + + case 87: +#line 822 "ftpcmd.y" + { + (yyval.i) = STRU_F; + } + break; + + case 88: +#line 826 "ftpcmd.y" + { + (yyval.i) = STRU_R; + } + break; + + case 89: +#line 830 "ftpcmd.y" + { + (yyval.i) = STRU_P; + } + break; + + case 90: +#line 837 "ftpcmd.y" + { + (yyval.i) = MODE_S; + } + break; + + case 91: +#line 841 "ftpcmd.y" + { + (yyval.i) = MODE_B; + } + break; + + case 92: +#line 845 "ftpcmd.y" + { + (yyval.i) = MODE_C; + } + break; + + case 93: +#line 852 "ftpcmd.y" + { + /* + * Problem: this production is used for all pathname + * processing, but only gives a 550 error reply. + * This is a valid reply in some cases but not in others. + */ + if (logged_in && (yyvsp[(1) - (1)].s) && *(yyvsp[(1) - (1)].s) == '~') { + glob_t gl; + int flags = + GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + if (glob((yyvsp[(1) - (1)].s), flags, NULL, &gl) || + gl.gl_pathc == 0) { + reply(550, "not found"); + (yyval.s) = NULL; + } else { + (yyval.s) = strdup(gl.gl_pathv[0]); + } + globfree(&gl); + free((yyvsp[(1) - (1)].s)); + } else + (yyval.s) = (yyvsp[(1) - (1)].s); + } + break; + + case 95: +#line 884 "ftpcmd.y" + { + int ret, dec, multby, digit; + + /* + * Convert a number that was read as decimal number + * to what it would be if it had been read as octal. + */ + dec = (yyvsp[(1) - (1)].i); + multby = 1; + ret = 0; + while (dec) { + digit = dec%10; + if (digit > 7) { + ret = -1; + break; + } + ret += digit * multby; + multby *= 8; + dec /= 10; + } + (yyval.i) = ret; + } + break; + + case 96: +#line 910 "ftpcmd.y" + { + (yyval.i) = (yyvsp[(1) - (1)].i) && !guest; + if((yyvsp[(1) - (1)].i) && !(yyval.i)) + reply(550, "Permission denied"); + } + break; + + case 97: +#line 918 "ftpcmd.y" + { + if((yyvsp[(1) - (1)].i)) { + if(((yyval.i) = logged_in) == 0) + reply(530, "Please login with USER and PASS."); + } else + (yyval.i) = 0; + } + break; + + case 98: +#line 928 "ftpcmd.y" + { + (yyval.i) = 1; + if(sec_complete && !ccc_passed && !secure_command()) { + (yyval.i) = 0; + reply(533, "Command protection level denied " + "for paranoid reasons."); + } + } + break; + + +/* Line 1267 of yacc.c. */ +#line 2778 "ftpcmd.c" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 938 "ftpcmd.y" + + +#define CMD 0 /* beginning of command */ +#define ARGS 1 /* expect miscellaneous arguments */ +#define STR1 2 /* expect SP followed by STRING */ +#define STR2 3 /* expect STRING */ +#define OSTR 4 /* optional SP then STRING */ +#define ZSTR1 5 /* SP then optional STRING */ +#define ZSTR2 6 /* optional STRING after SP */ +#define SITECMD 7 /* SITE command */ +#define NSTR 8 /* Number followed by a string */ + +struct tab cmdtab[] = { /* In order defined in RFC 765 */ + { "USER", USER, STR1, 1, "<sp> username" }, + { "PASS", PASS, ZSTR1, 1, "<sp> password" }, + { "ACCT", ACCT, STR1, 0, "(specify account)" }, + { "SMNT", SMNT, ARGS, 0, "(structure mount)" }, + { "REIN", REIN, ARGS, 0, "(reinitialize server state)" }, + { "QUIT", QUIT, ARGS, 1, "(terminate service)", }, + { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" }, + { "EPRT", EPRT, STR1, 1, "<sp> string" }, + { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, + { "EPSV", EPSV, OSTR, 1, "[<sp> foo]" }, + { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" }, + { "STRU", STRU, ARGS, 1, "(specify file structure)" }, + { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, + { "RETR", RETR, STR1, 1, "<sp> file-name" }, + { "STOR", STOR, STR1, 1, "<sp> file-name" }, + { "APPE", APPE, STR1, 1, "<sp> file-name" }, + { "MLFL", MLFL, OSTR, 0, "(mail file)" }, + { "MAIL", MAIL, OSTR, 0, "(mail to user)" }, + { "MSND", MSND, OSTR, 0, "(mail send to terminal)" }, + { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" }, + { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" }, + { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" }, + { "MRCP", MRCP, STR1, 0, "(mail recipient)" }, + { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" }, + { "REST", REST, ARGS, 1, "<sp> offset (restart command)" }, + { "RNFR", RNFR, STR1, 1, "<sp> file-name" }, + { "RNTO", RNTO, STR1, 1, "<sp> file-name" }, + { "ABOR", ABOR, ARGS, 1, "(abort operation)" }, + { "DELE", DELE, STR1, 1, "<sp> file-name" }, + { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" }, + { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" }, + { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" }, + { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" }, + { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" }, + { "SYST", SYST, ARGS, 1, "(get type of operating system)" }, + { "STAT", sTAT, OSTR, 1, "[ <sp> path-name ]" }, + { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" }, + { "NOOP", NOOP, ARGS, 1, "" }, + { "MKD", MKD, STR1, 1, "<sp> path-name" }, + { "XMKD", MKD, STR1, 1, "<sp> path-name" }, + { "RMD", RMD, STR1, 1, "<sp> path-name" }, + { "XRMD", RMD, STR1, 1, "<sp> path-name" }, + { "PWD", PWD, ARGS, 1, "(return current directory)" }, + { "XPWD", PWD, ARGS, 1, "(return current directory)" }, + { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "STOU", STOU, STR1, 1, "<sp> file-name" }, + { "SIZE", SIZE, OSTR, 1, "<sp> path-name" }, + { "MDTM", MDTM, OSTR, 1, "<sp> path-name" }, + + /* extensions from RFC2228 */ + { "AUTH", AUTH, STR1, 1, "<sp> auth-type" }, + { "ADAT", ADAT, STR1, 1, "<sp> auth-data" }, + { "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" }, + { "PROT", PROT, STR1, 1, "<sp> prot-level" }, + { "CCC", CCC, ARGS, 1, "" }, + { "MIC", MIC, STR1, 1, "<sp> integrity command" }, + { "CONF", CONF, STR1, 1, "<sp> confidentiality command" }, + { "ENC", ENC, STR1, 1, "<sp> privacy command" }, + + /* RFC2389 */ + { "FEAT", FEAT, ARGS, 1, "" }, + { "OPTS", OPTS, ARGS, 1, "<sp> command [<sp> options]" }, + + { NULL, 0, 0, 0, 0 } +}; + +struct tab sitetab[] = { + { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" }, + { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" }, + { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" }, + { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" }, + + { "KAUTH", KAUTH, STR1, 1, "<sp> principal [ <sp> ticket ]" }, + { "KLIST", KLIST, ARGS, 1, "(show ticket file)" }, + { "KDESTROY", KDESTROY, ARGS, 1, "(destroy tickets)" }, + { "KRBTKFILE", KRBTKFILE, STR1, 1, "<sp> ticket-file" }, + { "AFSLOG", AFSLOG, OSTR, 1, "[<sp> cell]" }, + + { "LOCATE", LOCATE, STR1, 1, "<sp> globexpr" }, + { "FIND", LOCATE, STR1, 1, "<sp> globexpr" }, + + { "URL", URL, ARGS, 1, "?" }, + + { NULL, 0, 0, 0, 0 } +}; + +static struct tab * +lookup(struct tab *p, char *cmd) +{ + + for (; p->name != NULL; p++) + if (strcmp(cmd, p->name) == 0) + return (p); + return (0); +} + +/* + * ftpd_getline - a hacked up version of fgets to ignore TELNET escape codes. + */ +char * +ftpd_getline(char *s, int n) +{ + int c; + char *cs; + + cs = s; + + /* might still be data within the security MIC/CONF/ENC */ + if(ftp_command){ + strlcpy(s, ftp_command, n); + if (debug) + syslog(LOG_DEBUG, "command: %s", s); + return s; + } + while ((c = getc(stdin)) != EOF) { + c &= 0377; + if (c == IAC) { + if ((c = getc(stdin)) != EOF) { + c &= 0377; + switch (c) { + case WILL: + case WONT: + c = getc(stdin); + printf("%c%c%c", IAC, DONT, 0377&c); + fflush(stdout); + continue; + case DO: + case DONT: + c = getc(stdin); + printf("%c%c%c", IAC, WONT, 0377&c); + fflush(stdout); + continue; + case IAC: + break; + default: + continue; /* ignore command */ + } + } + } + *cs++ = c; + if (--n <= 0 || c == '\n') + break; + } + if (c == EOF && cs == s) + return (NULL); + *cs++ = '\0'; + if (debug) { + if (!guest && strncasecmp("pass ", s, 5) == 0) { + /* Don't syslog passwords */ + syslog(LOG_DEBUG, "command: %.5s ???", s); + } else { + char *cp; + int len; + + /* Don't syslog trailing CR-LF */ + len = strlen(s); + cp = s + len - 1; + while (cp >= s && (*cp == '\n' || *cp == '\r')) { + --cp; + --len; + } + syslog(LOG_DEBUG, "command: %.*s", len, s); + } + } +#ifdef XXX + fprintf(stderr, "%s\n", s); +#endif + return (s); +} + +static RETSIGTYPE +toolong(int signo) +{ + + reply(421, + "Timeout (%d seconds): closing control connection.", + ftpd_timeout); + if (logging) + syslog(LOG_INFO, "User %s timed out after %d seconds", + (pw ? pw -> pw_name : "unknown"), ftpd_timeout); + dologout(1); + SIGRETURN(0); +} + +static int +yylex(void) +{ + static int cpos, state; + char *cp, *cp2; + struct tab *p; + int n; + char c; + + for (;;) { + switch (state) { + + case CMD: + hasyyerrored = 0; + + signal(SIGALRM, toolong); + alarm((unsigned) ftpd_timeout); + if (ftpd_getline(cbuf, sizeof(cbuf)-1) == NULL) { + reply(221, "You could at least say goodbye."); + dologout(0); + } + alarm(0); +#ifdef HAVE_SETPROCTITLE + if (strncasecmp(cbuf, "PASS", 4) != 0) + setproctitle("%s: %s", proctitle, cbuf); +#endif /* HAVE_SETPROCTITLE */ + if ((cp = strchr(cbuf, '\r'))) { + *cp++ = '\n'; + *cp = '\0'; + } + if ((cp = strpbrk(cbuf, " \n"))) + cpos = cp - cbuf; + if (cpos == 0) + cpos = 4; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + strupr(cbuf); + p = lookup(cmdtab, cbuf); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + nack(p->name); + hasyyerrored = 1; + break; + } + state = p->state; + yylval.s = p->name; + return (p->token); + } + break; + + case SITECMD: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + cp = &cbuf[cpos]; + if ((cp2 = strpbrk(cp, " \n"))) + cpos = cp2 - cbuf; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + strupr(cp); + p = lookup(sitetab, cp); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + state = CMD; + nack(p->name); + hasyyerrored = 1; + break; + } + state = p->state; + yylval.s = p->name; + return (p->token); + } + state = CMD; + break; + + case OSTR: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR1: + case ZSTR1: + dostr1: + if (cbuf[cpos] == ' ') { + cpos++; + if(state == OSTR) + state = STR2; + else + state++; + return (SP); + } + break; + + case ZSTR2: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR2: + cp = &cbuf[cpos]; + n = strlen(cp); + cpos += n - 1; + /* + * Make sure the string is nonempty and \n terminated. + */ + if (n > 1 && cbuf[cpos] == '\n') { + cbuf[cpos] = '\0'; + yylval.s = copy(cp); + cbuf[cpos] = '\n'; + state = ARGS; + return (STRING); + } + break; + + case NSTR: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + if (isdigit((unsigned char)cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit((unsigned char)cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval.i = atoi(cp); + cbuf[cpos] = c; + state = STR1; + return (NUMBER); + } + state = STR1; + goto dostr1; + + case ARGS: + if (isdigit((unsigned char)cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit((unsigned char)cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval.i = atoi(cp); + cbuf[cpos] = c; + return (NUMBER); + } + switch (cbuf[cpos++]) { + + case '\n': + state = CMD; + return (CRLF); + + case ' ': + return (SP); + + case ',': + return (COMMA); + + case 'A': + case 'a': + return (A); + + case 'B': + case 'b': + return (B); + + case 'C': + case 'c': + return (C); + + case 'E': + case 'e': + return (E); + + case 'F': + case 'f': + return (F); + + case 'I': + case 'i': + return (I); + + case 'L': + case 'l': + return (L); + + case 'N': + case 'n': + return (N); + + case 'P': + case 'p': + return (P); + + case 'R': + case 'r': + return (R); + + case 'S': + case 's': + return (S); + + case 'T': + case 't': + return (T); + + } + break; + + default: + fatal("Unknown state in scanner."); + } + yyerror(NULL); + state = CMD; + return (0); + } +} + +/* ARGSUSED */ +void +yyerror(char *s) +{ + char *cp; + + if (hasyyerrored) + return; + + if ((cp = strchr(cbuf,'\n'))) + *cp = '\0'; + reply(500, "'%s': command not understood.", cbuf); + hasyyerrored = 1; +} + +static char * +copy(char *s) +{ + char *p; + + p = strdup(s); + if (p == NULL) + fatal("Ran out of memory."); + return p; +} + +static void +help(struct tab *ctab, char *s) +{ + struct tab *c; + int width, NCMDS; + char *t; + char buf[1024]; + + if (ctab == sitetab) + t = "SITE "; + else + t = ""; + width = 0, NCMDS = 0; + for (c = ctab; c->name != NULL; c++) { + int len = strlen(c->name); + + if (len > width) + width = len; + NCMDS++; + } + width = (width + 8) &~ 7; + if (s == 0) { + int i, j, w; + int columns, lines; + + lreply(214, "The following %scommands are recognized %s.", + t, "(* =>'s unimplemented)"); + columns = 76 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + strlcpy (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 ? ' ' : '*'); + if (c + lines >= &ctab[NCMDS]) + break; + w = strlen(c->name) + 1; + while (w < width) { + strlcat (buf, + " ", + sizeof(buf)); + w++; + } + } + lreply(214, "%s", buf); + } + reply(214, "Direct comments to kth-krb-bugs@pdc.kth.se"); + return; + } + strupr(s); + c = lookup(ctab, s); + if (c == (struct tab *)0) { + reply(502, "Unknown command %s.", s); + return; + } + if (c->implemented) + reply(214, "Syntax: %s%s %s", t, c->name, c->help); + else + reply(214, "%s%-*s\t%s; unimplemented.", t, width, + c->name, c->help); +} + +static void +sizecmd(char *filename) +{ + switch (type) { + case TYPE_L: + case TYPE_I: { + struct stat stbuf; + if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) + reply(550, "%s: not a plain file.", filename); + else + reply(213, "%lu", (unsigned long)stbuf.st_size); + break; + } + case TYPE_A: { + FILE *fin; + int c; + size_t count; + struct stat stbuf; + fin = fopen(filename, "r"); + if (fin == NULL) { + perror_reply(550, filename); + return; + } + if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) { + reply(550, "%s: not a plain file.", filename); + fclose(fin); + return; + } + + count = 0; + while((c=getc(fin)) != EOF) { + if (c == '\n') /* will get expanded to \r\n */ + count++; + count++; + } + fclose(fin); + + reply(213, "%lu", (unsigned long)count); + break; + } + default: + reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); + } +} + diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpcmd.y b/crypto/heimdal/appl/ftp/ftpd/ftpcmd.y index 9c5fa4c..963a6a0 100644 --- a/crypto/heimdal/appl/ftp/ftpd/ftpcmd.y +++ b/crypto/heimdal/appl/ftp/ftpd/ftpcmd.y @@ -43,7 +43,7 @@ %{ #include "ftpd_locl.h" -RCSID("$Id: ftpcmd.y,v 1.61.10.2 2004/08/20 15:15:46 lha Exp $"); +RCSID("$Id: ftpcmd.y 15677 2005-07-19 18:33:08Z lha $"); off_t restart_point; @@ -137,30 +137,35 @@ cmd_list ; cmd - : USER SP username CRLF + : USER SP username CRLF check_secure { + if ($5) user($3); - free($3); + free($3); } - | PASS SP password CRLF + | PASS SP password CRLF check_secure { + if ($5) pass($3); - memset ($3, 0, strlen($3)); - free($3); + memset ($3, 0, strlen($3)); + free($3); } - | PORT SP host_port CRLF + | PORT SP host_port CRLF check_secure { + if ($5) { usedefault = 0; if (pdata >= 0) { close(pdata); pdata = -1; } reply(200, "PORT command successful."); + } } - | EPRT SP STRING CRLF + | EPRT SP STRING CRLF check_secure { + if ($5) eprt ($3); - free ($3); + free ($3); } | PASV CRLF check_login { @@ -178,8 +183,9 @@ cmd epsv ($3); free ($3); } - | TYPE SP type_code CRLF + | TYPE SP type_code CRLF check_secure { + if ($5) { switch (cmd_type) { case TYPE_A: @@ -212,9 +218,11 @@ cmd UNIMPLEMENTED for NBBY != 8 #endif /* NBBY == 8 */ } + } } - | STRU SP struct_code CRLF + | STRU SP struct_code CRLF check_secure { + if ($5) { switch ($3) { case STRU_F: @@ -224,9 +232,11 @@ cmd default: reply(504, "Unimplemented STRU type."); } + } } - | MODE SP mode_code CRLF + | MODE SP mode_code CRLF check_secure { + if ($5) { switch ($3) { case MODE_S: @@ -236,14 +246,19 @@ cmd default: reply(502, "Unimplemented MODE type."); } + } } - | ALLO SP NUMBER CRLF + | ALLO SP NUMBER CRLF check_secure { + if ($5) { reply(202, "ALLO command ignored."); + } } - | ALLO SP NUMBER SP R SP NUMBER CRLF + | ALLO SP NUMBER SP R SP NUMBER CRLF check_secure { + if ($9) { reply(202, "ALLO command ignored."); + } } | RETR SP pathname CRLF check_login { @@ -304,10 +319,11 @@ cmd if ($3 != NULL) free($3); } - | sTAT CRLF + | sTAT CRLF check_secure { + if ($3) statcmd(); - } + } | DELE SP pathname CRLF check_login_no_guest { if ($5 && $3 != NULL) @@ -329,8 +345,9 @@ cmd if ($3 != NULL) free($3); } - | ABOR CRLF + | ABOR CRLF check_secure { + if ($3) reply(225, "ABOR command successful."); } | CWD CRLF check_login @@ -345,12 +362,14 @@ cmd if ($3 != NULL) free($3); } - | HELP CRLF + | HELP CRLF check_secure { + if ($3) help(cmdtab, (char *) 0); } - | HELP SP STRING CRLF + | HELP SP STRING CRLF check_secure { + if ($5) { char *cp = $3; if (strncasecmp(cp, "SITE", 4) == 0) { @@ -363,9 +382,11 @@ cmd help(sitetab, (char *) 0); } else help(cmdtab, $3); + } } - | NOOP CRLF + | NOOP CRLF check_secure { + if ($3) reply(200, "NOOP command successful."); } | MKD SP pathname CRLF check_login @@ -392,26 +413,31 @@ cmd if ($3) cwd(".."); } - | FEAT CRLF + | FEAT CRLF check_secure { + if ($3) { lreply(211, "Supported features:"); lreply(0, " MDTM"); lreply(0, " REST STREAM"); lreply(0, " SIZE"); reply(211, "End"); + } } - | OPTS SP STRING CRLF + | OPTS SP STRING CRLF check_secure { - free ($3); + if ($5) reply(501, "Bad options"); + free ($3); } - | SITE SP HELP CRLF + | SITE SP HELP CRLF check_secure { + if ($5) help(sitetab, (char *) 0); } - | SITE SP HELP SP STRING CRLF + | SITE SP HELP SP STRING CRLF check_secure { + if ($7) help(sitetab, $5); } | SITE SP UMASK CRLF check_login @@ -449,14 +475,16 @@ cmd if ($7 != NULL) free($7); } - | SITE SP IDLE CRLF + | SITE SP IDLE CRLF check_secure { + if ($5) reply(200, "Current IDLE time limit is %d seconds; max %d", ftpd_timeout, maxtimeout); } - | SITE SP IDLE SP NUMBER CRLF + | SITE SP IDLE SP NUMBER CRLF check_secure { + if ($7) { if ($5 < 30 || $5 > maxtimeout) { reply(501, "Maximum IDLE time must be between 30 and %d seconds", @@ -468,6 +496,7 @@ cmd "Maximum IDLE time set to %d seconds", ftpd_timeout); } + } } | SITE SP KAUTH SP STRING CRLF check_login @@ -495,12 +524,8 @@ cmd } | SITE SP KLIST CRLF check_login { -#ifdef KRB4 if($5) klist(); -#else - reply(500, "Command not implemented."); -#endif } | SITE SP KDESTROY CRLF check_login { @@ -526,22 +551,22 @@ cmd } | SITE SP AFSLOG CRLF check_login { -#ifdef KRB4 +#if defined(KRB4) || defined(KRB5) if(guest) reply(500, "Can't be done as guest."); else if($5) - afslog(NULL); + afslog(NULL, 0); #else reply(500, "Command not implemented."); #endif } | SITE SP AFSLOG SP STRING CRLF check_login { -#ifdef KRB4 +#if defined(KRB4) || defined(KRB5) if(guest) reply(500, "Can't be done as guest."); else if($7) - afslog($5); + afslog($5, 0); if($5) free($5); #else @@ -555,9 +580,10 @@ cmd if($5 != NULL) free($5); } - | SITE SP URL CRLF + | SITE SP URL CRLF check_secure { - reply(200, "http://www.pdc.kth.se/kth-krb/"); + if ($5) + reply(200, "http://www.pdc.kth.se/heimdal/"); } | STOU SP pathname CRLF check_login { @@ -566,13 +592,15 @@ cmd if ($3 != NULL) free($3); } - | SYST CRLF + | SYST CRLF check_secure { + if ($3) { #if !defined(WIN32) && !defined(__EMX__) && !defined(__OS2__) && !defined(__CYGWIN32__) - reply(215, "UNIX Type: L%d", NBBY); + reply(215, "UNIX Type: L%d", NBBY); #else - reply(215, "UNKNOWN Type: L%d", NBBY); + reply(215, "UNKNOWN Type: L%d", NBBY); #endif + } } /* @@ -627,10 +655,12 @@ cmd if ($3 != NULL) free($3); } - | QUIT CRLF + | QUIT CRLF check_secure { + if ($3) { reply(221, "Goodbye."); dologout(0); + } } | error CRLF { @@ -648,13 +678,15 @@ rcmd } } } - | REST SP byte_size CRLF + | REST SP byte_size CRLF check_secure { + if ($5) { fromname = (char *) 0; restart_point = $3; /* XXX $3 is only "int" */ reply(350, "Restarting at %ld. %s", (long)restart_point, "Send STORE or RETRIEVE to initiate transfer."); + } } | AUTH SP STRING CRLF { @@ -666,16 +698,19 @@ rcmd adat($3); free($3); } - | PBSZ SP NUMBER CRLF + | PBSZ SP NUMBER CRLF check_secure { + if ($5) pbsz($3); } - | PROT SP STRING CRLF + | PROT SP STRING CRLF check_secure { + if ($5) prot($3); } - | CCC CRLF + | CCC CRLF check_secure { + if ($3) ccc(); } | MIC SP STRING CRLF @@ -715,11 +750,11 @@ host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER { - struct sockaddr_in *sin = (struct sockaddr_in *)data_dest; + struct sockaddr_in *sin4 = (struct sockaddr_in *)data_dest; - sin->sin_family = AF_INET; - sin->sin_port = htons($9 * 256 + $11); - sin->sin_addr.s_addr = + sin4->sin_family = AF_INET; + sin4->sin_port = htons($9 * 256 + $11); + sin4->sin_addr.s_addr = htonl(($1 << 24) | ($3 << 16) | ($5 << 8) | $7); } ; @@ -892,7 +927,7 @@ check_login : check_secure check_secure : /* empty */ { $$ = 1; - if(sec_complete && !secure_command()) { + if(sec_complete && !ccc_passed && !secure_command()) { $$ = 0; reply(533, "Command protection level denied " "for paranoid reasons."); @@ -1352,13 +1387,13 @@ help(struct tab *ctab, char *s) { struct tab *c; int width, NCMDS; - char *type; + char *t; char buf[1024]; if (ctab == sitetab) - type = "SITE "; + t = "SITE "; else - type = ""; + t = ""; width = 0, NCMDS = 0; for (c = ctab; c->name != NULL; c++) { int len = strlen(c->name); @@ -1373,7 +1408,7 @@ help(struct tab *ctab, char *s) int columns, lines; lreply(214, "The following %scommands are recognized %s.", - type, "(* =>'s unimplemented)"); + t, "(* =>'s unimplemented)"); columns = 76 / width; if (columns == 0) columns = 1; @@ -1409,9 +1444,9 @@ help(struct tab *ctab, char *s) return; } if (c->implemented) - reply(214, "Syntax: %s%s %s", type, c->name, c->help); + reply(214, "Syntax: %s%s %s", t, c->name, c->help); else - reply(214, "%s%-*s\t%s; unimplemented.", type, width, + reply(214, "%s%-*s\t%s; unimplemented.", t, width, c->name, c->help); } diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpd.8 b/crypto/heimdal/appl/ftp/ftpd/ftpd.8 index b630641..0dfed9f 100644 --- a/crypto/heimdal/appl/ftp/ftpd/ftpd.8 +++ b/crypto/heimdal/appl/ftp/ftpd/ftpd.8 @@ -156,8 +156,8 @@ allowed anonymous upload filename chars .Fl -no-insecure-oob .Xc don't allow insecure out of band. -Heimdal ftp client before 0.7 doesn't support secure oob, so turning -on this options makes them no longer work. +Heimdal ftp clients before 0.6.3 doesn't support secure oob, so turning +on this option makes them no longer work. .El .Pp The file diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpd.c b/crypto/heimdal/appl/ftp/ftpd/ftpd.c index 88bb4a1..2005a4f 100644 --- a/crypto/heimdal/appl/ftp/ftpd/ftpd.c +++ b/crypto/heimdal/appl/ftp/ftpd/ftpd.c @@ -38,7 +38,7 @@ #endif #include "getarg.h" -RCSID("$Id: ftpd.c,v 1.166.2.3 2004/08/20 15:16:37 lha Exp $"); +RCSID("$Id: ftpd.c 21222 2007-06-20 10:11:14Z lha $"); static char version[] = "Version 6.00"; @@ -138,9 +138,9 @@ static int handleoobcmd(void); static int checkuser (char *, char *); static int checkaccess (char *); static FILE *dataconn (const char *, off_t, const char *); -static void dolog (struct sockaddr *sa, int len); +static void dolog (struct sockaddr *, int); static void end_login (void); -static FILE *getdatasock (const char *); +static FILE *getdatasock (const char *, int); static char *gunique (char *); static RETSIGTYPE lostconn (int); static int receive_data (FILE *, FILE *); @@ -280,10 +280,6 @@ main(int argc, char **argv) krb_set_tkt_string(tkfile); #endif } -#if defined(KRB4) || defined(KRB5) - if(k_hasafs()) - k_setpag(); -#endif if(getarg(args, num_args, argc, argv, &optind)) usage(1); @@ -595,14 +591,15 @@ user(char *name) if (logging) strlcpy(curname, name, sizeof(curname)); if(sec_complete) { - if(sec_userok(name) == 0) + if(sec_userok(name) == 0) { do_login(232, name); - else + sec_session(name); + } else reply(530, "User %s access denied.", name); } else { +#ifdef OTP char ss[256]; -#ifdef OTP if (otp_challenge(&otp_ctx, name, ss, sizeof(ss)) == 0) { reply(331, "Password %s for %s required.", ss, name); @@ -613,9 +610,9 @@ user(char *name) reply(331, "Password required for %s.", name); askpasswd = 1; } else { - char *s; - #ifdef OTP + char *s; + if ((s = otp_error (&otp_ctx)) != NULL) lreply(530, "OTP: %s", s); #endif @@ -727,6 +724,10 @@ int do_login(int code, char *passwd) return -1; } initgroups(pw->pw_name, pw->pw_gid); +#if defined(KRB4) || defined(KRB5) + if(k_hasafs()) + k_setpag(); +#endif /* open wtmp before chroot */ ftpd_logwtmp(ttyline, pw->pw_name, remotehost); @@ -835,7 +836,8 @@ static void end_login(void) { - seteuid((uid_t)0); + if (seteuid((uid_t)0) < 0) + fatal("Failed to seteuid"); if (logged_in) ftpd_logwtmp(ttyline, "", ""); pw = NULL; @@ -933,9 +935,8 @@ pass(char *passwd) if (rval) rval = unix_verify_user(pw->pw_name, passwd); } else { - char *s; - #ifdef OTP + char *s; if ((s = otp_error(&otp_ctx)) != NULL) lreply(530, "OTP: %s", s); #endif @@ -1023,9 +1024,10 @@ retrieve(const char *cmd, char *name) *tail = c; if (p->rev_cmd != NULL) { char *ext; + int ret; - asprintf(&ext, "%s%s", name, p->ext); - if (ext != NULL) { + ret = asprintf(&ext, "%s%s", name, p->ext); + if (ret != -1) { if (access(ext, R_OK) == 0) { snprintf (line, sizeof(line), p->rev_cmd, ext); @@ -1107,17 +1109,17 @@ done: int filename_check(char *filename) { - unsigned char *p; + char *p; - p = (unsigned char *)strrchr(filename, '/'); + p = strrchr(filename, '/'); if(p) filename = p + 1; p = filename; - if(isalnum(*p)){ + if(isalnum((unsigned char)*p)){ p++; - while(*p && (isalnum(*p) || strchr(good_chars, *p))) + while(*p && (isalnum((unsigned char)*p) || strchr(good_chars, (unsigned char)*p))) p++; if(*p == '\0') return 0; @@ -1208,14 +1210,15 @@ done: } static FILE * -getdatasock(const char *mode) +getdatasock(const char *mode, int domain) { int s, t, tries; if (data >= 0) return (fdopen(data, mode)); - seteuid(0); - s = socket(ctrl_addr->sa_family, SOCK_STREAM, 0); + if (seteuid(0) < 0) + fatal("Failed to seteuid"); + s = socket(domain, SOCK_STREAM, 0); if (s < 0) goto bad; socket_set_reuseaddr (s, 1); @@ -1232,7 +1235,8 @@ getdatasock(const char *mode) goto bad; sleep(tries); } - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); #ifdef IPTOS_THROUGHPUT socket_set_tos (s, IPTOS_THROUGHPUT); #endif @@ -1240,7 +1244,8 @@ getdatasock(const char *mode) bad: /* Return the real value of errno (close may change it) */ t = errno; - seteuid((uid_t)pw->pw_uid); + if (seteuid((uid_t)pw->pw_uid) < 0) + fatal("Failed to seteuid"); close(s); errno = t; return (NULL); @@ -1271,7 +1276,7 @@ dataconn(const char *name, off_t size, const char *mode) { char sizebuf[32]; FILE *file; - int retry = 0; + int domain, retry = 0; file_size = size; byte_count = 0; @@ -1318,7 +1323,15 @@ dataconn(const char *name, off_t size, const char *mode) if (usedefault) data_dest = his_addr; usedefault = 1; - file = getdatasock(mode); + /* + * Default to using the same socket type as the ctrl address, + * unless we know the type of the data address. + */ + domain = data_dest->sa_family; + if (domain == PF_UNSPEC) + domain = ctrl_addr->sa_family; + + file = getdatasock(mode, domain); if (file == NULL) { char data_addr[256]; @@ -1625,7 +1638,7 @@ statcmd(void) lreply(211, "%s FTP server (%s) status:", hostname, version); printf(" %s\r\n", version); printf(" Connected to %s", remotehost); - if (!isdigit(remotehost[0])) + if (!isdigit((unsigned char)remotehost[0])) printf(" (%s)", inet_ntoa(his_addr.sin_addr)); printf("\r\n"); if (logged_in) { @@ -1889,11 +1902,11 @@ dologout(int status) transflag = 0; urgflag = 0; if (logged_in) { - seteuid((uid_t)0); - ftpd_logwtmp(ttyline, "", ""); -#ifdef KRB4 +#if KRB4 || KRB5 cond_kdestroy(); #endif + seteuid((uid_t)0); /* No need to check, we call exit() below */ + ftpd_logwtmp(ttyline, "", ""); } /* beware of flushing buffers after a SIGPIPE */ #ifdef XXX @@ -2006,12 +2019,15 @@ pasv(void) 0); socket_set_portrange(pdata, restricted_data_ports, pasv_addr->sa_family); - seteuid(0); + if (seteuid(0) < 0) + fatal("Failed to seteuid"); if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) { - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); goto pasv_error; } - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); len = sizeof(pasv_addr_ss); if (getsockname(pdata, pasv_addr, &len) < 0) goto pasv_error; @@ -2050,12 +2066,15 @@ epsv(char *proto) 0); socket_set_portrange(pdata, restricted_data_ports, pasv_addr->sa_family); - seteuid(0); + if (seteuid(0) < 0) + fatal("Failed to seteuid"); if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) { - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid)) + fatal("Failed to seteuid"); goto pasv_error; } - seteuid(pw->pw_uid); + if (seteuid(pw->pw_uid) < 0) + fatal("Failed to seteuid"); len = sizeof(pasv_addr_ss); if (getsockname(pdata, pasv_addr, &len) < 0) goto pasv_error; diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h b/crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h index bb172ac..f5574e9 100644 --- a/crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h +++ b/crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: ftpd_locl.h,v 1.13.2.1 2004/08/20 15:17:07 lha Exp $ */ +/* $Id: ftpd_locl.h 14933 2005-04-24 19:58:14Z lha $ */ #ifndef __ftpd_locl_h__ #define __ftpd_locl_h__ @@ -166,7 +166,7 @@ extern int LIBPREFIX(fclose) (FILE *); int fclose(FILE *stream); -int yyparse(); +int yyparse(void); #ifndef LOG_FTP #define LOG_FTP LOG_DAEMON diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpusers.5 b/crypto/heimdal/appl/ftp/ftpd/ftpusers.5 index ce59df8..85b5f62 100644 --- a/crypto/heimdal/appl/ftp/ftpd/ftpusers.5 +++ b/crypto/heimdal/appl/ftp/ftpd/ftpusers.5 @@ -1,4 +1,4 @@ -.\" $Id: ftpusers.5,v 1.5 2002/08/20 17:07:04 joda Exp $ +.\" $Id: ftpusers.5 11176 2002-08-20 17:07:29Z joda $ .\" .Dd May 7, 1997 .Dt FTPUSERS 5 diff --git a/crypto/heimdal/appl/ftp/ftpd/gss_userok.c b/crypto/heimdal/appl/ftp/ftpd/gss_userok.c index 11a2e75..6fa8f7e 100644 --- a/crypto/heimdal/appl/ftp/ftpd/gss_userok.c +++ b/crypto/heimdal/appl/ftp/ftpd/gss_userok.c @@ -35,90 +35,121 @@ #include <gssapi.h> #include <krb5.h> -RCSID("$Id: gss_userok.c,v 1.10 2003/03/18 13:56:35 lha Exp $"); +RCSID("$Id: gss_userok.c 21222 2007-06-20 10:11:14Z lha $"); /* XXX a bit too much of krb5 dependency here... What is the correct way to do this? */ -extern krb5_context gssapi_krb5_context; +struct gss_krb5_data { + krb5_context context; +}; /* XXX sync with gssapi.c */ struct gss_data { gss_ctx_id_t context_hdl; char *client_name; gss_cred_id_t delegated_cred_handle; + void *mech_data; }; int gss_userok(void*, char*); /* to keep gcc happy */ +int gss_session(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); - if (!ret) { - krb5_free_principal(gssapi_krb5_context, client); - return 1; - } - - ret = 0; + krb5_error_code ret; + krb5_principal client; + struct gss_krb5_data *kdata; + + kdata = calloc(1, sizeof(struct gss_krb5_data)); + if (kdata == NULL) + return 1; + data->mech_data = kdata; + + ret = krb5_init_context(&(kdata->context)); + if (ret) { + free(kdata); + return 1; + } + + ret = krb5_parse_name(kdata->context, data->client_name, &client); + if(ret) { + krb5_free_context(kdata->context); + free(kdata); + return 1; + } + ret = krb5_kuserok(kdata->context, client, username); + if (!ret) { + krb5_free_principal(kdata->context, client); + krb5_free_context(kdata->context); + free(kdata); + return 1; + } - /* more of krb-depend stuff :-( */ - /* gss_add_cred() ? */ - if (data->delegated_cred_handle && - data->delegated_cred_handle->ccache ) { - - krb5_ccache ccache = NULL; - char* ticketfile; - struct passwd *pw; - OM_uint32 minor_status; - - pw = getpwnam(username); - - if (pw == NULL) { - ret = 1; - goto fail; - } + ret = 0; + krb5_free_principal(kdata->context, client); + return ret; +} + +int +gss_session(void *app_data, char *username) +{ + struct gss_data *data = app_data; + krb5_error_code ret; + OM_uint32 minor_status; + struct gss_krb5_data *kdata; + + ret = 0; - asprintf (&ticketfile, "%s%u", KRB5_DEFAULT_CCROOT, - (unsigned)pw->pw_uid); + kdata = (struct gss_krb5_data *)(data->mech_data); - ret = krb5_cc_resolve(gssapi_krb5_context, ticketfile, &ccache); - if (ret) - goto fail; + /* more of krb-depend stuff :-( */ + /* gss_add_cred() ? */ + if (data->delegated_cred_handle != GSS_C_NO_CREDENTIAL) { + krb5_ccache ccache = NULL; + const char* ticketfile; + struct passwd *kpw; - ret = gss_krb5_copy_ccache(&minor_status, - data->delegated_cred_handle, - ccache); - if (ret) - goto fail; - - chown (ticketfile+5, pw->pw_uid, pw->pw_gid); + ret = krb5_cc_gen_new(kdata->context, &krb5_fcc_ops, &ccache); + if (ret) + goto fail; + + ticketfile = krb5_cc_get_name(kdata->context, ccache); + + ret = gss_krb5_copy_ccache(&minor_status, + data->delegated_cred_handle, + ccache); + if (ret) { + ret = 0; + goto fail; + } - if (k_hasafs()) { - krb5_afslog(gssapi_krb5_context, ccache, 0, 0); - } - esetenv ("KRB5CCNAME", ticketfile, 1); + do_destroy_tickets = 1; + + kpw = getpwnam(username); -fail: - if (ccache) - krb5_cc_close(gssapi_krb5_context, ccache); - krb5_cc_destroy(gssapi_krb5_context, - data->delegated_cred_handle->ccache); - data->delegated_cred_handle->ccache = NULL; - free(ticketfile); - } + if (kpw == NULL) { + unlink(ticketfile); + ret = 1; + goto fail; + } + + chown (ticketfile, kpw->pw_uid, kpw->pw_gid); - krb5_free_principal(gssapi_krb5_context, client); - return ret; + if (asprintf(&k5ccname, "FILE:%s", ticketfile) != -1) { + esetenv ("KRB5CCNAME", k5ccname, 1); + } + afslog(NULL, 1); + fail: + if (ccache) + krb5_cc_close(kdata->context, ccache); } - return 1; + + gss_release_cred(&minor_status, &data->delegated_cred_handle); + krb5_free_context(kdata->context); + free(kdata); + return ret; } diff --git a/crypto/heimdal/appl/ftp/ftpd/gssapi.c b/crypto/heimdal/appl/ftp/ftpd/gssapi.c new file mode 100644 index 0000000..9432feb --- /dev/null +++ b/crypto/heimdal/appl/ftp/ftpd/gssapi.c @@ -0,0 +1,528 @@ +/* + * Copyright (c) 1998 - 2005 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. 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> +#include <krb5_err.h> + +RCSID("$Id: gssapi.c 21513 2007-07-12 12:45:25Z lha $"); + +int ftp_do_gss_bindings = 0; +int ftp_do_gss_delegate = 1; + +struct gss_data { + gss_ctx_id_t context_hdl; + char *client_name; + gss_cred_id_t delegated_cred_handle; + void *mech_data; +}; + +static int +gss_init(void *app_data) +{ + struct gss_data *d = app_data; + d->context_hdl = GSS_C_NO_CONTEXT; + d->delegated_cred_handle = GSS_C_NO_CREDENTIAL; +#if defined(FTP_SERVER) + return 0; +#else + /* XXX Check the gss mechanism; with gss_indicate_mechs() ? */ +#ifdef KRB5 + return !use_kerberos; +#else + return 0; +#endif /* KRB5 */ +#endif /* FTP_SERVER */ +} + +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; + size_t ret_len; + + 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); + ret_len = output.length; + gss_release_buffer(&min_stat, &output); + return ret_len; +} + +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; +} + +static void +sockaddr_to_gss_address (struct sockaddr *sa, + OM_uint32 *addr_type, + gss_buffer_desc *gss_addr) +{ + switch (sa->sa_family) { +#ifdef HAVE_IPV6 + case AF_INET6 : { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + + gss_addr->length = 16; + gss_addr->value = &sin6->sin6_addr; + *addr_type = GSS_C_AF_INET6; + break; + } +#endif + case AF_INET : { + struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; + + gss_addr->length = 4; + gss_addr->value = &sin4->sin_addr; + *addr_type = GSS_C_AF_INET; + break; + } + default : + errx (1, "unknown address family %d", sa->sa_family); + + } +} + +/* 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; + + if (ftp_do_gss_bindings) { + bindings = malloc(sizeof(*bindings)); + if (bindings == NULL) + errx(1, "out of memory"); + + sockaddr_to_gss_address (his_addr, + &bindings->initiator_addrtype, + &bindings->initiator_address); + sockaddr_to_gss_address (ctrl_addr, + &bindings->acceptor_addrtype, + &bindings->acceptor_address); + + bindings->application_data.length = 0; + bindings->application_data.value = NULL; + } else + bindings = GSS_C_NO_CHANNEL_BINDINGS; + + 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, + &d->delegated_cred_handle); + + if (bindings != GSS_C_NO_CHANNEL_BINDINGS) + free(bindings); + + if(output_token.length) { + if(base64_encode(output_token.value, output_token.length, &p) < 0) { + reply(535, "Out of memory base64-encoding."); + return -1; + } + gss_release_buffer(&min_stat, &output_token); + } + if(maj_stat == GSS_S_COMPLETE){ + char *name; + gss_buffer_desc export_name; + gss_OID oid; + + maj_stat = gss_display_name(&min_stat, client_name, + &export_name, &oid); + if(maj_stat != 0) { + reply(500, "Error displaying name"); + goto out; + } + /* XXX kerberos */ + if(oid != GSS_KRB5_NT_PRINCIPAL_NAME) { + reply(500, "OID not kerberos principal name"); + gss_release_buffer(&min_stat, &export_name); + goto out; + } + name = malloc(export_name.length + 1); + if(name == NULL) { + reply(500, "Out of memory"); + gss_release_buffer(&min_stat, &export_name); + goto out; + } + memcpy(name, export_name.value, export_name.length); + name[export_name.length] = '\0'; + gss_release_buffer(&min_stat, &export_name); + 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 { + OM_uint32 new_stat; + OM_uint32 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); + syslog(LOG_ERR, "gss_accept_sec_context: %s", + (char*)status_string.value); + gss_release_buffer(&new_stat, &status_string); + reply(431, "Security resource unavailable"); + } + out: + if (client_name) + gss_release_name(&min_stat, &client_name); + free(p); + return 0; +} + +int gss_userok(void*, char*); +int gss_session(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, + gss_session +}; + +#else /* FTP_SERVER */ + +extern struct sockaddr *hisctladdr, *myctladdr; + +static int +import_name(const char *kname, const char *host, gss_name_t *target_name) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc name; + char *str; + + name.length = asprintf(&str, "%s@%s", kname, host); + if (str == NULL) { + printf("Out of memory\n"); + return AUTH_ERROR; + } + name.value = str; + + maj_stat = gss_import_name(&min_stat, + &name, + GSS_C_NT_HOSTBASED_SERVICE, + target_name); + if (GSS_ERROR(maj_stat)) { + OM_uint32 new_stat; + OM_uint32 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 importing name %s: %s\n", + (char *)name.value, + (char *)status_string.value); + free(name.value); + gss_release_buffer(&new_stat, &status_string); + return AUTH_ERROR; + } + free(name.value); + return 0; +} + +static int +gss_auth(void *app_data, char *host) +{ + + OM_uint32 maj_stat, min_stat; + 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; + OM_uint32 mech_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG; + + const char *knames[] = { "ftp", "host", NULL }, **kname = knames; + + + if(import_name(*kname++, host, &target_name)) + return AUTH_ERROR; + + input.length = 0; + input.value = NULL; + + if (ftp_do_gss_bindings) { + bindings = malloc(sizeof(*bindings)); + if (bindings == NULL) + errx(1, "out of memory"); + + sockaddr_to_gss_address (myctladdr, + &bindings->initiator_addrtype, + &bindings->initiator_address); + sockaddr_to_gss_address (hisctladdr, + &bindings->acceptor_addrtype, + &bindings->acceptor_address); + + bindings->application_data.length = 0; + bindings->application_data.value = NULL; + } else + bindings = GSS_C_NO_CHANNEL_BINDINGS; + + if (ftp_do_gss_delegate) + mech_flags |= GSS_C_DELEG_FLAG; + + while(!context_established) { + maj_stat = gss_init_sec_context(&min_stat, + GSS_C_NO_CREDENTIAL, + &d->context_hdl, + target_name, + GSS_C_NO_OID, + mech_flags, + 0, + bindings, + &input, + NULL, + &output_token, + NULL, + NULL); + if (GSS_ERROR(maj_stat)) { + OM_uint32 new_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + + d->context_hdl = GSS_C_NO_CONTEXT; + + gss_release_name(&min_stat, &target_name); + + if(*kname != NULL) { + + if(import_name(*kname++, host, &target_name)) { + if (bindings != GSS_C_NO_CHANNEL_BINDINGS) + free(bindings); + return AUTH_ERROR; + } + continue; + } + + if (bindings != GSS_C_NO_CHANNEL_BINDINGS) + free(bindings); + + 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; + } + + if (input.value) { + free(input.value); + input.value = NULL; + input.length = 0; + } + 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. got: %s\n", + reply_string); + if (bindings != GSS_C_NO_CHANNEL_BINDINGS) + free(bindings); + 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); + if (bindings != GSS_C_NO_CHANNEL_BINDINGS) + free(bindings); + return AUTH_ERROR; + } + context_established = 1; + } + } + + gss_release_name(&min_stat, &target_name); + + if (bindings != GSS_C_NO_CHANNEL_BINDINGS) + free(bindings); + if (input.value) + free(input.value); + + { + gss_name_t targ_name; + + maj_stat = gss_inquire_context(&min_stat, + d->context_hdl, + NULL, + &targ_name, + NULL, + NULL, + NULL, + NULL, + NULL); + if (GSS_ERROR(maj_stat) == 0) { + gss_buffer_desc name; + maj_stat = gss_display_name (&min_stat, + targ_name, + &name, + NULL); + if (GSS_ERROR(maj_stat) == 0) { + printf("Authenticated to <%s>\n", (char *)name.value); + gss_release_buffer(&min_stat, &name); + } + gss_release_name(&min_stat, &targ_name); + } else + printf("Failed to get gss name of peer.\n"); + } + + + 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/heimdal/appl/ftp/ftpd/kauth.c b/crypto/heimdal/appl/ftp/ftpd/kauth.c index dad4de5..0f34092 100644 --- a/crypto/heimdal/appl/ftp/ftpd/kauth.c +++ b/crypto/heimdal/appl/ftp/ftpd/kauth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan + * Copyright (c) 1995 - 1999, 2003 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,16 @@ #include "ftpd_locl.h" -RCSID("$Id: kauth.c,v 1.25 1999/12/02 16:58:31 joda Exp $"); +RCSID("$Id: kauth.c 15666 2005-07-19 17:08:11Z lha $"); + +#if defined(KRB4) || defined(KRB5) + +int do_destroy_tickets = 1; +char *k5ccname; + +#endif + +#ifdef KRB4 static KTEXT_ST cip; static unsigned int lifetime; @@ -41,8 +50,6 @@ static time_t local_time; static krb_principal pr; -static int do_destroy_tickets = 1; - static int save_tkt(const char *user, const char *instance, @@ -237,86 +244,41 @@ short_date(int32_t dp) } void -klist(void) +krbtkfile(const char *tkfile) { - int err; + do_destroy_tickets = 0; + krb_set_tkt_string(tkfile); + reply(200, "Using ticket file %s", tkfile); +} - char *file = tkt_string(); +#endif /* KRB4 */ - krb_principal pr; - - char buf1[128], buf2[128]; - int header = 1; - CREDENTIALS c; +#ifdef KRB5 +static void +dest_cc(void) +{ + krb5_context context; + krb5_error_code ret; + krb5_ccache id; - - err = tf_init(file, R_TKT_FIL); - if(err != KSUCCESS){ - reply(500, "%s", krb_get_err_text(err)); - return; - } - tf_close(); - - /* - * We must find the realm of the ticket file here before calling - * tf_init because since the realm of the ticket file is not - * really stored in the principal section of the file, the - * routine we use must itself call tf_init and tf_close. - */ - err = krb_get_tf_realm(file, pr.realm); - if(err != KSUCCESS){ - reply(500, "%s", krb_get_err_text(err)); - return; - } - - err = tf_init(file, R_TKT_FIL); - if(err != KSUCCESS){ - reply(500, "%s", krb_get_err_text(err)); - return; - } - - err = tf_get_pname(pr.name); - if(err != KSUCCESS){ - reply(500, "%s", krb_get_err_text(err)); - return; - } - err = tf_get_pinst(pr.instance); - if(err != KSUCCESS){ - reply(500, "%s", krb_get_err_text(err)); - return; - } - - /* - * You may think that this is the obvious place to get the - * realm of the ticket file, but it can't be done here as the - * routine to do this must open the ticket file. This is why - * it was done before tf_init. - */ - - lreply(200, "Ticket file: %s", tkt_string()); - - lreply(200, "Principal: %s", krb_unparse_name(&pr)); - while ((err = tf_get_cred(&c)) == KSUCCESS) { - if (header) { - lreply(200, "%-15s %-15s %s", - " Issued", " Expires", " Principal (kvno)"); - header = 0; - } - strlcpy(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) - strlcpy(buf2, short_date(c.issue_date), sizeof(buf2)); + ret = krb5_init_context(&context); + if (ret == 0) { + if (k5ccname) + ret = krb5_cc_resolve(context, k5ccname, &id); else - strlcpy(buf2, ">>> Expired <<< ", sizeof(buf2)); - lreply(200, "%s %s %s (%d)", buf1, buf2, - krb_unparse_name_long(c.service, c.instance, c.realm), c.kvno); + ret = krb5_cc_default (context, &id); + if (ret) + krb5_free_context(context); } - if (header && err == EOF) { - lreply(200, "No tickets in file."); + if (ret == 0) { + krb5_cc_destroy(context, id); + krb5_free_context (context); } - reply(200, " "); } +#endif + +#if defined(KRB4) || defined(KRB5) /* * Only destroy if we created the tickets @@ -325,35 +287,64 @@ klist(void) void cond_kdestroy(void) { - if (do_destroy_tickets) + if (do_destroy_tickets) { +#if KRB4 dest_tkt(); +#endif +#if KRB5 + dest_cc(); +#endif + do_destroy_tickets = 0; + } afsunlog(); } void kdestroy(void) { +#if KRB4 dest_tkt(); +#endif +#if KRB5 + dest_cc(); +#endif 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) +afslog(const char *cell, int quiet) { if(k_hasafs()) { +#ifdef KRB5 + krb5_context context; + krb5_error_code ret; + krb5_ccache id; + + ret = krb5_init_context(&context); + if (ret == 0) { + if (k5ccname) + ret = krb5_cc_resolve(context, k5ccname, &id); + else + ret = krb5_cc_default(context, &id); + if (ret) + krb5_free_context(context); + } + if (ret == 0) { + krb5_afslog(context, id, cell, 0); + krb5_cc_close (context, id); + krb5_free_context (context); + } +#endif +#ifdef KRB4 krb_afslog(cell, 0); - reply(200, "afslog done"); +#endif + if (!quiet) + reply(200, "afslog done"); } else { - reply(200, "no AFS present"); + if (!quiet) + reply(200, "no AFS present"); } } @@ -363,3 +354,7 @@ afsunlog(void) if(k_hasafs()) k_unlog(); } + +#else +int ftpd_afslog_placeholder; +#endif /* KRB4 || KRB5 */ diff --git a/crypto/heimdal/appl/ftp/ftpd/klist.c b/crypto/heimdal/appl/ftp/ftpd/klist.c new file mode 100644 index 0000000..4afa9b8 --- /dev/null +++ b/crypto/heimdal/appl/ftp/ftpd/klist.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1995 - 2005 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. 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" + +#ifdef KRB5 + +static int +print_cred(krb5_context context, krb5_creds *cred) +{ + char t1[128], t2[128], *str; + krb5_error_code ret; + krb5_timestamp sec; + + krb5_timeofday (context, &sec); + + if(cred->times.starttime) + krb5_format_time(context, cred->times.starttime, t1, sizeof(t1), 1); + else + krb5_format_time(context, cred->times.authtime, t1, sizeof(t1), 1); + + if(cred->times.endtime > sec) + krb5_format_time(context, cred->times.endtime, t2, sizeof(t2), 1); + else + strlcpy(t2, ">>>Expired<<<", sizeof(t2)); + + ret = krb5_unparse_name (context, cred->server, &str); + if (ret) { + lreply(500, "krb5_unparse_name: %d", ret); + return 1; + } + + lreply(200, "%-20s %-20s %s", t1, t2, str); + free(str); + return 0; +} + +static int +print_tickets (krb5_context context, + krb5_ccache ccache, + krb5_principal principal) +{ + krb5_error_code ret; + krb5_cc_cursor cursor; + krb5_creds cred; + char *str; + + ret = krb5_unparse_name (context, principal, &str); + if (ret) { + lreply(500, "krb5_unparse_name: %d", ret); + return 500; + } + + lreply(200, "%17s: %s:%s", + "Credentials cache", + krb5_cc_get_type(context, ccache), + krb5_cc_get_name(context, ccache)); + lreply(200, "%17s: %s", "Principal", str); + free (str); + + ret = krb5_cc_start_seq_get (context, ccache, &cursor); + if (ret) { + lreply(500, "krb5_cc_start_seq_get: %d", ret); + return 500; + } + + lreply(200, " Issued Expires Principal"); + + while ((ret = krb5_cc_next_cred (context, + ccache, + &cursor, + &cred)) == 0) { + if (print_cred(context, &cred)) + return 500; + krb5_free_cred_contents (context, &cred); + } + if (ret != KRB5_CC_END) { + lreply(500, "krb5_cc_get_next: %d", ret); + return 500; + } + ret = krb5_cc_end_seq_get (context, ccache, &cursor); + if (ret) { + lreply(500, "krb5_cc_end_seq_get: %d", ret); + return 500; + } + + return 200; +} + +static int +klist5(void) +{ + krb5_error_code ret; + krb5_context context; + krb5_ccache ccache; + krb5_principal principal; + int exit_status = 200; + + ret = krb5_init_context (&context); + if (ret) { + lreply(500, "krb5_init_context failed: %d", ret); + return 500; + } + + if (k5ccname) + ret = krb5_cc_resolve(context, k5ccname, &ccache); + else + ret = krb5_cc_default (context, &ccache); + if (ret) { + lreply(500, "krb5_cc_default: %d", ret); + return 500; + } + + ret = krb5_cc_get_principal (context, ccache, &principal); + if (ret) { + if(ret == ENOENT) + lreply(500, "No ticket file: %s", + krb5_cc_get_name(context, ccache)); + else + lreply(500, "krb5_cc_get_principal: %d", ret); + + return 500; + } + exit_status = print_tickets (context, ccache, principal); + + ret = krb5_cc_close (context, ccache); + if (ret) { + lreply(500, "krb5_cc_close: %d", ret); + exit_status = 500; + } + + krb5_free_principal (context, principal); + krb5_free_context (context); + return exit_status; +} +#endif + +void +klist(void) +{ +#if KRB5 + int res = klist5(); + reply(res, " "); +#else + reply(500, "Command not implemented."); +#endif +} + diff --git a/crypto/heimdal/appl/ftp/ftpd/krb4.c b/crypto/heimdal/appl/ftp/ftpd/krb4.c new file mode 100644 index 0000000..408b7fa --- /dev/null +++ b/crypto/heimdal/appl/ftp/ftpd/krb4.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 1995, 1996, 1997, 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. 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 <krb.h> + +RCSID("$Id: krb4.c 17450 2006-05-05 11:11:43Z lha $"); + +#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 *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 int +krb4_check_prot(void *app_data, int level) +{ + if(level == prot_confidential) + return -1; + return 0; +} + +static int +krb4_decode(void *app_data, void *buf, int len, int level) +{ + MSG_DAT m; + int e; + struct krb4_data *d = app_data; + + if(level == prot_safe) + e = krb_rd_safe(buf, len, &d->key, + (struct sockaddr_in *)REMOTE_ADDR, + (struct sockaddr_in *)LOCAL_ADDR, &m); + else + e = krb_rd_priv(buf, len, d->schedule, &d->key, + (struct sockaddr_in *)REMOTE_ADDR, + (struct sockaddr_in *)LOCAL_ADDR, &m); + if(e){ + syslog(LOG_ERR, "krb4_decode: %s", krb_get_err_text(e)); + return -1; + } + memmove(buf, m.app_data, m.app_length); + return m.app_length; +} + +static int +krb4_overhead(void *app_data, int level, int len) +{ + return 31; +} + +static int +krb4_encode(void *app_data, void *from, int length, int level, void **to) +{ + struct krb4_data *d = app_data; + *to = malloc(length + 31); + if(level == prot_safe) + return krb_mk_safe(from, *to, length, &d->key, + (struct sockaddr_in *)LOCAL_ADDR, + (struct sockaddr_in *)REMOTE_ADDR); + else if(level == prot_private) + return krb_mk_priv(from, *to, length, d->schedule, &d->key, + (struct sockaddr_in *)LOCAL_ADDR, + (struct sockaddr_in *)REMOTE_ADDR); + else + return -1; +} + +#ifdef FTP_SERVER + +static int +krb4_adat(void *app_data, void *buf, size_t len) +{ + KTEXT_ST tkt; + AUTH_DAT auth_dat; + char *p; + int kerror; + uint32_t cs; + char msg[35]; /* size of encrypted block */ + int tmp_len; + struct krb4_data *d = app_data; + char inst[INST_SZ]; + struct sockaddr_in *his_addr_sin = (struct sockaddr_in *)his_addr; + + memcpy(tkt.dat, buf, len); + tkt.length = len; + + k_getsockinst(0, inst, sizeof(inst)); + kerror = krb_rd_req(&tkt, "ftp", inst, + his_addr_sin->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->sin_addr.s_addr, &auth_dat, ""); + } + + if(kerror){ + reply(535, "Error reading request: %s.", krb_get_err_text(kerror)); + return -1; + } + + memcpy(d->key, auth_dat.session, sizeof(d->key)); + des_set_key(&d->key, d->schedule); + + strlcpy(d->name, auth_dat.pname, sizeof(d->name)); + strlcpy(d->instance, auth_dat.pinst, sizeof(d->instance)); + strlcpy(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, + (struct sockaddr_in *)LOCAL_ADDR, + (struct sockaddr_in *)REMOTE_ADDR); + } + if(tmp_len < 0){ + reply(535, "Error creating reply: %s.", strerror(errno)); + return -1; + } + len = tmp_len; + if(base64_encode(msg, len, &p) < 0) { + reply(535, "Out of memory base64-encoding."); + return -1; + } + reply(235, "ADAT=%s", p); + sec_complete = 1; + free(p); + return 0; +} + +static int +krb4_userok(void *app_data, char *user) +{ + struct krb4_data *d = app_data; + return krb_kuserok(d->name, d->instance, d->realm, user); +} + +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 +}; + +#else /* FTP_SERVER */ + +static int +krb4_init(void *app_data) +{ + return !use_kerberos; +} + +static int +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]; + + strlcpy(sname, service, sizeof(sname)); + strlcpy(inst, krb_get_phost(host), sizeof(inst)); + strlcpy(realm, krb_realmofhost(host), sizeof(realm)); + ret = krb_mk_req(adat, sname, inst, realm, checksum); + if(ret) + return ret; + strlcpy(sname, service, sizeof(sname)); + strlcpy(inst, krb_get_phost(host), sizeof(inst)); + strlcpy(realm, krb_realmofhost(host), sizeof(realm)); + ret = krb_get_cred(sname, inst, realm, &cred); + memmove(&d->key, &cred.session, sizeof(des_cblock)); + des_key_sched(&d->key, d->schedule); + memset(&cred, 0, sizeof(cred)); + return ret; +} + +static int +krb4_auth(void *app_data, char *host) +{ + int ret; + char *p; + int len; + KTEXT_ST adat; + MSG_DAT msg_data; + int checksum; + uint32_t cs; + struct krb4_data *d = app_data; + struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR; + struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR; + + checksum = getpid(); + ret = mk_auth(d, &adat, "ftp", host, checksum); + if(ret == KDC_PR_UNKNOWN) + ret = mk_auth(d, &adat, "rcmd", host, checksum); + if(ret){ + printf("%s\n", krb_get_err_text(ret)); + return AUTH_CONTINUE; + } + +#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM + if (krb_get_config_bool("nat_in_use")) { + struct in_addr natAddr; + + if (krb_get_our_ip_for_realm(krb_realmofhost(host), + &natAddr) != KSUCCESS + && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS) + printf("Can't get address for realm %s\n", + krb_realmofhost(host)); + else { + if (natAddr.s_addr != localaddr->sin_addr.s_addr) { + printf("Using NAT IP address (%s) for kerberos 4\n", + inet_ntoa(natAddr)); + localaddr->sin_addr = natAddr; + + /* + * This not the best place to do this, but it + * is here we know that (probably) NAT is in + * use! + */ + + passivemode = 1; + printf("Setting: Passive mode on.\n"); + } + } + } +#endif + + printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr)); + printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr)); + + 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"); + return AUTH_ERROR; + } + + p = strstr(reply_string, "ADAT="); + if(!p){ + printf("Remote host didn't send adat reply.\n"); + return AUTH_ERROR; + } + p += 5; + len = base64_decode(p, adat.dat); + if(len < 0){ + printf("Failed to decode base64 from server.\n"); + return AUTH_ERROR; + } + adat.length = len; + ret = krb_rd_safe(adat.dat, adat.length, &d->key, + (struct sockaddr_in *)hisctladdr, + (struct sockaddr_in *)myctladdr, &msg_data); + if(ret){ + printf("Error reading reply from server: %s.\n", + krb_get_err_text(ret)); + return AUTH_ERROR; + } + krb_get_int(msg_data.app_data, &cs, 4, 0); + if(cs - checksum != 1){ + printf("Bad checksum returned from server.\n"); + return AUTH_ERROR; + } + return AUTH_OK; +} + +struct sec_client_mech krb4_client_mech = { + "KERBEROS_V4", + sizeof(struct krb4_data), + krb4_init, /* init */ + krb4_auth, + NULL, /* end */ + krb4_check_prot, + krb4_overhead, + krb4_encode, + krb4_decode +}; + +#endif /* FTP_SERVER */ diff --git a/crypto/heimdal/appl/ftp/ftpd/logwtmp.c b/crypto/heimdal/appl/ftp/ftpd/logwtmp.c index 51139a8..ebf37e6 100644 --- a/crypto/heimdal/appl/ftp/ftpd/logwtmp.c +++ b/crypto/heimdal/appl/ftp/ftpd/logwtmp.c @@ -33,7 +33,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: logwtmp.c,v 1.15 2000/09/19 13:17:05 assar Exp $"); +RCSID("$Id: logwtmp.c 9079 2000-09-19 13:17:20Z assar $"); #endif #include <stdio.h> diff --git a/crypto/heimdal/appl/ftp/ftpd/ls.c b/crypto/heimdal/appl/ftp/ftpd/ls.c index f8ec4ad..9dcd848 100644 --- a/crypto/heimdal/appl/ftp/ftpd/ls.c +++ b/crypto/heimdal/appl/ftp/ftpd/ls.c @@ -33,7 +33,7 @@ #ifndef TEST #include "ftpd_locl.h" -RCSID("$Id: ls.c,v 1.26 2003/02/25 10:51:30 lha Exp $"); +RCSID("$Id: ls.c 16216 2005-10-22 13:15:43Z lha $"); #else #include <stdio.h> @@ -146,16 +146,16 @@ block_convert(size_t blocks) #endif } -static void +static int make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) { char buf[128]; int file_type = 0; struct stat *st = &file->st; - + file->inode = st->st_ino; file->bsize = block_convert(st->st_blocks); - + if(S_ISDIR(st->st_mode)) { file->mode[0] = 'd'; file_type = '/'; @@ -218,31 +218,51 @@ make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) { struct passwd *pwd; pwd = getpwuid(st->st_uid); - if(pwd == NULL) - asprintf(&file->user, "%u", (unsigned)st->st_uid); - else + if(pwd == NULL) { + if (asprintf(&file->user, "%u", (unsigned)st->st_uid) == -1) + file->user = NULL; + } else file->user = strdup(pwd->pw_name); + if (file->user == NULL) { + syslog(LOG_ERR, "out of memory"); + return -1; + } } { struct group *grp; grp = getgrgid(st->st_gid); - if(grp == NULL) - asprintf(&file->group, "%u", (unsigned)st->st_gid); - else + if(grp == NULL) { + if (asprintf(&file->group, "%u", (unsigned)st->st_gid) == -1) + file->group = NULL; + } else file->group = strdup(grp->gr_name); + if (file->group == NULL) { + syslog(LOG_ERR, "out of memory"); + return -1; + } } if(S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { #if defined(major) && defined(minor) - asprintf(&file->major, "%u", (unsigned)major(st->st_rdev)); - asprintf(&file->minor, "%u", (unsigned)minor(st->st_rdev)); + if (asprintf(&file->major, "%u", (unsigned)major(st->st_rdev)) == -1) + file->major = NULL; + if (asprintf(&file->minor, "%u", (unsigned)minor(st->st_rdev)) == -1) + file->minor = NULL; #else /* Don't want to use the DDI/DKI crap. */ - asprintf(&file->major, "%u", (unsigned)st->st_rdev); - asprintf(&file->minor, "%u", 0); + if (asprintf(&file->major, "%u", (unsigned)st->st_rdev) == -1) + file->major = NULL; + if (asprintf(&file->minor, "%u", 0) == -1) + file->minor = NULL; #endif - } else - asprintf(&file->size, "%lu", (unsigned long)st->st_size); + if (file->major == NULL || file->minor == NULL) { + syslog(LOG_ERR, "out of memory"); + return -1; + } + } else { + if (asprintf(&file->size, "%lu", (unsigned long)st->st_size) == -1) + file->size = NULL; + } { time_t t = time(NULL); @@ -254,6 +274,10 @@ make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) else strftime(buf, sizeof(buf), "%b %e %H:%M", tm); file->date = strdup(buf); + if (file->date == NULL) { + syslog(LOG_ERR, "out of memory"); + return -1; + } } { const char *p = strrchr(filename, '/'); @@ -261,10 +285,15 @@ make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) p++; else p = filename; - if((flags & LS_TYPE) && file_type != 0) - asprintf(&file->filename, "%s%c", p, file_type); - else + if((flags & LS_TYPE) && file_type != 0) { + if (asprintf(&file->filename, "%s%c", p, file_type) == -1) + file->filename = NULL; + } else file->filename = strdup(p); + if (file->filename == NULL) { + syslog(LOG_ERR, "out of memory"); + return -1; + } } if(S_ISLNK(st->st_mode)) { int n; @@ -272,9 +301,14 @@ make_fileinfo(FILE *out, const char *filename, struct fileinfo *file, int flags) if(n >= 0) { buf[n] = '\0'; file->link = strdup(buf); + if (file->link == NULL) { + syslog(LOG_ERR, "out of memory"); + return -1; + } } else sec_fprintf2(out, "readlink(%s): %s", filename, strerror(errno)); } + return 0; } static void @@ -356,7 +390,7 @@ compare_size(struct fileinfo *a, struct fileinfo *b) static int list_dir(FILE*, const char*, int); static int -log10(int num) +find_log10(int num) { int i = 1; while(num > 10) { @@ -508,7 +542,9 @@ list_files(FILE *out, const char **files, int n_files, int flags) include_in_list = 0; } if(include_in_list) { - make_fileinfo(out, files[i], &fi[i], flags); + ret = make_fileinfo(out, files[i], &fi[i], flags); + if (ret) + goto out; n_print++; } } @@ -563,9 +599,9 @@ list_files(FILE *out, const char **files, int n_files, int flags) max_size = max_major + max_minor + 2; else if(max_size - max_minor - 2 > max_major) max_major = max_size - max_minor - 2; - max_inode = log10(max_inode); - max_bsize = log10(max_bsize); - max_n_link = log10(max_n_link); + max_inode = find_log10(max_inode); + max_bsize = find_log10(max_bsize); + max_n_link = find_log10(max_n_link); if(n_print > 0) sec_fprintf2(out, "total %lu\r\n", (unsigned long)total_blocks); @@ -611,8 +647,8 @@ list_files(FILE *out, const char **files, int n_files, int flags) } if(strlen(fi[i].filename) > max_len) max_len = strlen(fi[i].filename); - if(log10(fi[i].bsize) > size_len) - size_len = log10(fi[i].bsize); + if(find_log10(fi[i].bsize) > size_len) + size_len = find_log10(fi[i].bsize); } if(num_files == 0) goto next; @@ -729,6 +765,7 @@ list_dir(FILE *out, const char *directory, int flags) struct dirent *ent; char **files = NULL; int n_files = 0; + int ret; if(d == NULL) { syslog(LOG_ERR, "%s: %m", directory); @@ -747,8 +784,8 @@ list_dir(FILE *out, const char *directory, int flags) return -1; } files = tmp; - asprintf(&files[n_files], "%s/%s", directory, ent->d_name); - if (files[n_files] == NULL) { + ret = asprintf(&files[n_files], "%s/%s", directory, ent->d_name); + if (ret == -1) { syslog(LOG_ERR, "%s: out of memory", directory); free_files (files, n_files); closedir (d); diff --git a/crypto/heimdal/appl/ftp/ftpd/pathnames.h b/crypto/heimdal/appl/ftp/ftpd/pathnames.h index e4f5b44..8849029 100644 --- a/crypto/heimdal/appl/ftp/ftpd/pathnames.h +++ b/crypto/heimdal/appl/ftp/ftpd/pathnames.h @@ -57,5 +57,7 @@ #define _PATH_FTPWELCOME SYSCONFDIR "/ftpwelcome" #define _PATH_FTPLOGINMESG SYSCONFDIR "/motd" +#ifndef _PATH_ISSUE #define _PATH_ISSUE SYSCONFDIR "/issue" +#endif #define _PATH_ISSUE_NET SYSCONFDIR "/issue.net" diff --git a/crypto/heimdal/appl/ftp/ftpd/popen.c b/crypto/heimdal/appl/ftp/ftpd/popen.c index 708cae1..dc75fb4 100644 --- a/crypto/heimdal/appl/ftp/ftpd/popen.c +++ b/crypto/heimdal/appl/ftp/ftpd/popen.c @@ -37,7 +37,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: popen.c,v 1.26 2002/04/02 11:57:39 joda Exp $"); +RCSID("$Id: popen.c 10900 2002-04-02 11:57:39Z joda $"); #endif #include <sys/types.h> diff --git a/crypto/heimdal/appl/ftp/ftpd/security.c b/crypto/heimdal/appl/ftp/ftpd/security.c new file mode 100644 index 0000000..2a4803f --- /dev/null +++ b/crypto/heimdal/appl/ftp/ftpd/security.c @@ -0,0 +1,883 @@ +/* + * Copyright (c) 1998-2002, 2005 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. 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 21225 2007-06-20 10:16:02Z lha $"); + +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 0; + else 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; + int b; + void *tmp; + + b = block_read(fd, &len, sizeof(len)); + if (b == 0) + return 0; + else if (b < 0) + return -1; + len = ntohl(len); + tmp = realloc(buf->data, len); + if (tmp == NULL) + return -1; + buf->data = tmp; + b = block_read(fd, buf->data, len); + if (b == 0) + return 0; + else if (b < 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 *dataptr, size_t len) +{ + len = min(len, buf->size - buf->index); + memcpy(dataptr, (char*)buf->data + buf->index, len); + buf->index += len; + return len; +} + +static size_t +buffer_write(struct buffer *buf, void *dataptr, 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, dataptr, len); + buf->index += len; + return len; +} + +int +sec_read(int fd, void *dataptr, int length) +{ + size_t len; + int rx = 0; + + if(sec_complete == 0 || data_prot == 0) + return read(fd, dataptr, length); + + if(in_buffer.eof_flag){ + in_buffer.eof_flag = 0; + return 0; + } + + len = buffer_read(&in_buffer, dataptr, length); + length -= len; + rx += len; + dataptr = (char*)dataptr + len; + + while(length){ + int ret; + + ret = sec_get_data(fd, &in_buffer, data_prot); + if (ret < 0) + return -1; + if(ret == 0 && in_buffer.size == 0) { + if(rx) + in_buffer.eof_flag = 1; + return rx; + } + len = buffer_read(&in_buffer, dataptr, length); + length -= len; + rx += len; + dataptr = (char*)dataptr + 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 *dataptr, int length) +{ + int len = buffer_size; + int tx = 0; + + if(data_prot == prot_clear) + return write(fd, dataptr, length); + + len -= (*mech->overhead)(app_data, data_prot, len); + while(length){ + if(length < len) + len = length; + sec_send(fd, dataptr, len); + length -= len; + dataptr += len; + tx += len; + } + return tx; +} + +int +sec_vfprintf2(FILE *f, const char *fmt, va_list ap) +{ + char *buf; + int ret; + if(data_prot == prot_clear) + return vfprintf(f, fmt, ap); + else { + int len; + len = vasprintf(&buf, fmt, ap); + if (len == -1) + return len; + ret = buffer_write(&out_buffer, buf, len); + free(buf); + return ret; + } +} + +int +sec_fprintf2(FILE *f, const char *fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = sec_vfprintf2(f, fmt, ap); + va_end(ap); + return ret; +} + +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 return_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] == '-') + return_code = 0; + else + sscanf(buf, "%d", &return_code); + if(buf[len-1] == '\n') + buf[len-1] = '\0'; + strcpy(s, buf); + free(buf); + return 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); + + if (vasprintf(&buf, fmt, ap) == -1) { + printf("Failed to allocate command.\n"); + return -1; + } + 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){ + free(enc); + printf("Out of memory base64-encoding.\n"); + return -1; + } + free(enc); +#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 + +int ccc_passed; + +void +auth(char *auth_name) +{ + int i; + void *tmp; + + for(i = 0; (mech = mechs[i]) != NULL; i++){ + if(!strcasecmp(auth_name, mech->name)){ + tmp = realloc(app_data, mech->size); + if (tmp == NULL) { + reply(431, "Unable to accept %s at this time", mech->name); + return; + } + app_data = tmp; + + 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); + app_data = NULL; + 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; + ccc_passed = 1; + } 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, buf_size; + if(!sec_complete) { + reply(503, "Incomplete security data exchange."); + return; + } + buf_size = strlen(msg) + 2; + buf = malloc(buf_size); + 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) + strlcat((char*)buf, "\r\n", buf_size); + new_ftp_command(buf); +} + +/* ------------------------------------------------------------ */ + +int +sec_userok(char *userstr) +{ + if(sec_complete) + return (*mech->userok)(app_data, userstr); + return 0; +} + +int +sec_session(char *user) +{ + if(sec_complete && mech->session) + return (*mech->session)(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; +} + +enum protection_level +get_command_prot(void) +{ + return command_prot; +} + +#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; +} + +enum protection_level +set_command_prot(enum protection_level level) +{ + int ret; + enum protection_level old = command_prot; + if(level != command_prot && level == prot_clear) { + ret = command("CCC"); + if(ret != COMPLETE) { + printf("Failed to clear command channel.\n"); + return -1; + } + } + command_prot = level; + return old; +} + +void +sec_prot(int argc, char **argv) +{ + int level = -1; + + if(argc > 3) + goto usage; + + if(argc == 1) { + sec_status(); + return; + } + if(!sec_complete) { + printf("No security data exchange has taken place.\n"); + code = -1; + return; + } + level = name_to_level(argv[argc - 1]); + + if(level == -1) + goto usage; + + 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(argc == 2 || strncasecmp(argv[1], "data", strlen(argv[1])) == 0) { + if(sec_prot_internal(level) < 0){ + code = -1; + return; + } + } else if(strncasecmp(argv[1], "command", strlen(argv[1])) == 0) { + if(set_command_prot(level) < 0) { + code = -1; + return; + } + } else + goto usage; + code = 0; + return; + usage: + printf("usage: %s [command|data] [clear|safe|confidential|private]\n", + argv[0]); + code = -1; +} + +void +sec_prot_command(int argc, char **argv) +{ + int level; + + if(argc > 2) + goto usage; + + if(!sec_complete) { + printf("No security data exchange has taken place.\n"); + code = -1; + return; + } + + if(argc == 1) { + sec_status(); + } else { + level = name_to_level(argv[1]); + if(level == -1) + goto usage; + + 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(set_command_prot(level) < 0) { + code = -1; + return; + } + } + code = 0; + return; + usage: + printf("usage: %s [clear|safe|confidential|private]\n", + argv[0]); + code = -1; +} + +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++) { + void *tmp; + + tmp = realloc(app_data, (*m)->size); + if (tmp == NULL) { + warnx ("realloc %lu failed", (unsigned long)(*m)->size); + return -1; + } + app_data = tmp; + + 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; + if(doencrypt) { + command_prot = prot_private; + request_data_prot = prot_private; + } else { + 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); + if (app_data != NULL) { + memset(app_data, 0, mech->size); + free(app_data); + app_data = NULL; + } + } + sec_complete = 0; + data_prot = (enum protection_level)0; +} + +#endif /* FTP_SERVER */ + |