[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd
From: |
Beau Kuiper |
Subject: |
[Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd |
Date: |
Tue, 04 Nov 2003 10:41:23 -0500 |
Module name: muddleftpd
Branch: dev-rugger-nat
Changes by: Beau Kuiper <address@hidden> 03/11/04 10:41:22
Reply-to: address@hidden
CVSROOT: /cvsroot/muddleftpd
Module name: muddleftpd
Branch: dev-rugger-nat
Changes by: Beau Kuiper <address@hidden> 03/11/04 10:41:22
Modified files:
. : ChangeLog Makefile.defs NEWS
src : auth.c cfloader.c checkip.c ftp.c ftpd.h
proxy.c
Log message:
Added NAT and passive port range support, so passive connections work
behind firewalls and NAT.
Fixed a couple of bugs along the way
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/ChangeLog.diff?only_with_tag=dev-rugger-nat&tr1=1.9&tr2=1.9.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/Makefile.defs.diff?only_with_tag=dev-rugger-nat&tr1=1.1&tr2=1.1.12.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/NEWS.diff?only_with_tag=dev-rugger-nat&tr1=1.4&tr2=1.4.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/src/auth.c.diff?only_with_tag=dev-rugger-nat&tr1=1.2&tr2=1.2.4.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/src/cfloader.c.diff?only_with_tag=dev-rugger-nat&tr1=1.1&tr2=1.1.12.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/src/checkip.c.diff?only_with_tag=dev-rugger-nat&tr1=1.1&tr2=1.1.8.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/src/ftp.c.diff?only_with_tag=dev-rugger-nat&tr1=1.1&tr2=1.1.8.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/src/ftpd.h.diff?only_with_tag=dev-rugger-nat&tr1=1.2&tr2=1.2.4.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/muddleftpd/muddleftpd/src/proxy.c.diff?only_with_tag=dev-rugger-nat&tr1=1.1&tr2=1.1.8.1&r1=text&r2=text
Patches:
Index: muddleftpd/ChangeLog
diff -c /dev/null muddleftpd/ChangeLog:1.9.2.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/ChangeLog Tue Nov 4 10:41:21 2003
***************
*** 0 ****
--- 1,294 ----
+ 2003-11-04 Beau Kuiper <address@hidden>
+
+ * checkip.c: made the IPACLLIST structure/code more general, so it
+ can be used to store/decode information used to determine for NAT
+ support whether a host is on the local network or on the internet.
+
+ * auth.c: updated to use new ipacllist interface.
+
+ * cfloader.c: added code to load and check configuration for
+ passive port ranges and NAT external IP settings. Fixed 2 minor
+ error path bugs in existing code. Updated to use the new ipacllist
+ interface.
+
+ * ftp.c: created the new function ftp_passive_do() that encapsulates
+ the functions of limiting port ranges and doing NAT IP translation for
+ passive FTP connections. Modified the passive code to use it.
+
+ * ftpd.h: updated the IPACLLIST structure and ipacllist prototypes
+ for the more general code. Added pasvport_start, pasvport_last,
+ ipnat, ip_localips for NAT and passive port range support.
+
+ * proxy.c: updated to use new ipacllist interface. Also added code
+ to initalise the pseudo-random number generator after fork() has
+ occured, so each thread has its own properly initalised PRNG.
+
+ 2003-11-03 Joerg Jaspert <address@hidden>
+
+ * modules/auth/authlibsmb/smbval/Makefile.in: Added CFLAGS and
+ -fPIC so this thing compiles on 64bit architectures too.
+
+ * modules/auth: authlibexample/Makefile.in,
+ authlibmud/Makefile.in, authlibsmb/Makefile.in,
+ authlibmysql/Makefile.in, authlibmsql/Makefile.in: Added -fPIC so
+ it actually compiles on different platforms.
+
+ 2003-11-02 Joerg Jaspert <address@hidden>
+
+ * configure.ac, modules/auth/authlibmysql/configure.ac: Changed
+ way we look for mysql. Thats easier for users now.
+
+ * modules/auth/: authlibmsql/auth.h, authlibmysql/auth.h,
+ authlibsmb/auth.h, authlibmud/auth.h, authlibexample/auth.h:
+ Changed include from varargs.h to stdarg.h as gcc no longer
+ includes varargs.h
+
+ * modules/auth/: authlibmsql/README, authlibmysql/README,
+ authlibsmb/README, authlibmud/README, authlibexample/README:
+ Changed documentation to be in sync with new configure/makefile
+ things.
+
+ * modules/auth: authlibmsql/Makefile.in,
+ authlibmysql/Makefile.in, authlibexample/Makefile.in,
+ authlibsmb/Makefile.in, authlibmud/Makefile.in: Change Install
+ Target from TODO to something useful. Install the autlibfile in
+ libdir/muddleftpd set by configure run.
+ Also install the READMEs as README.auth$MODULE in the
+ documentation dir (see below).
+
+ * doc/Makefile.in: Added things to install txt documentation in
+ prefix/share/doc/muddleftpd/*
+
+ 2003-11-02 Beau Kuiper <address@hidden>
+
+ * src/ftpd.h: removed headers for string.h since they are in
+ string.h. Updated prototype for safe_vsnprintf().
+
+ * src/string.c: fixed double use of varargs in string_catvprintf().
+ This fixed muddleftpd problems on PPC and possibly other archs.
+
+ * src/string.h: updated prototype for string_catvprintf()
+
+ * src/ftpout.c: modified ftp_write to use fixed string_catvprintf()
+
+ * src/logger.c: modified debuglog() to use fixed safe_vsnprint()
+
+ * src/utils.c: fixed possible double use of varargs in safe_vsnprintf()
+ Fixed safe_snprintf() so it does not use safe_vsnprintf() to prevent
+ performance degredation due to new design.
+
+ * Configure.ac: Added a check for stdarg.h, since the replacement
+ snprintf code needs it.
+
+ 2003-04-15 Beau Kuiper <address@hidden>
+
+ * src/main.c: mainprog(): added code to close all file descriptors.
+ After the server is started, it will also close the terminal file
+ desciptors, so ssh sessions are not stalled at logout.
+
+ * src/utils.c: fd_closeall_nonterminal(): determines the max file
+ descriptors number and attempts to close all open fds. The terminal
+ file descriptors are left untouched.
+
+ 2002-11-20 Beau Kuiper <address@hidden>
+
+ * src/acl.c: transfer_config(): Added code that allows the server
+ to retrieve the gid a user will operate as from the password file.
+ Just put "!" in front of the gid parameter. (eg gid !anuser) will
+ give the user the gid of the user anuser.
+
+ 2002-10-29 Beau Kuiper <address@hidden>
+
+ * src/string.c: string_filterbadchars(): Added code to only allow
+ /r and /n characters if and only if they are together as a TELNET
+ newline (/r/n). This fixes the bug of muddleftpd accepting input
+ with those characters in it and then mucking the log files up with
+ it.
+
+ * src/logger.c: Removed code that replaces /r and /n with spaces.
+ It doesn't need it anymore, since I have cured the original bug.
+
+ 2002-10-21 Joerg Jaspert <address@hidden>
+
+ * modules/auth/authlibexample/COPYING: Added back. This license
+ is different (a public domain one) and not GPL as I blindly
+ assumed from the name. Sorry Beau.
+
+ 2002-10-20 Joerg Jaspert <address@hidden>
+
+ * NEWS: Added. Contains summaries of changes between releases.
+
+ * CHANGES: Removed, that is now in NEWS.
+
+ * modules/auth/: authlibmsql/README, authlibmysql/README,
+ authlibsmb/README: No need to mention that it depends
+ on muddleftpd. Of course it does, it is distributed with it. :)
+
+ * tools/muddlestats.0.3.0/: AUTHORS, COPYING: Removed.
+ AUTHORS integrated into the main AUTHORS, license is the same as
+ Muddleftpd, GPL.
+
+ * AUTHORS: Rewrote so it reflects current state of the Art.
+
+ * modules/auth/: authlibmysql/AUTHORS, authlibmysql/COPYING,
+ authlibsmb/AUTHORS, authlibsmb/COPYING,
+ authlibexample/AUTHORS, authlibexample/COPYING,
+ authlibmsql/AUTHORS, authlibmsql/COPYING,
+ authlibmud/AUTHORS, authlibmud/COPYING: Removed.
+ Authors is now integrated into the main AUTHORS file and license is
+ same as Muddleftpd.
+
+ 2002-10-20 Joerg Jaspert <address@hidden>
+
+ * Developer.txt: Added Section about Changelogs/Commit
+ Messages. Changed (C) for new Files to be for the Muddleftpd team.
+
+ 2002-10-20 Beau Kuiper <address@hidden>
+
+ * modules/auth/: authlibexample/AUTHORS,
+ authlibexample/CHANGES, authlibexample/COPYING,
+ authlibexample/Makefile.in, authlibexample/README,
+ authlibexample/auth.h, authlibexample/authunix.c,
+ authlibexample/configure.ac, authlibmsql/AUTHORS,
+ authlibmsql/CHANGES, authlibmsql/COPYING,
+ authlibmsql/Makefile.in, authlibmsql/README,
+ authlibmsql/auth.h, authlibmsql/authmsql.c,
+ authlibmsql/configure.ac, authlibmud/AUTHORS,
+ authlibmud/CHANGES, authlibmud/COPYING,
+ authlibmud/Makefile.in, authlibmud/README,
+ authlibmud/auth.h, authlibmud/authmud.c,
+ authlibmud/configure.ac, authlibmysql/AUTHORS,
+ authlibmysql/CHANGES, authlibmysql/COPYING,
+ authlibmysql/Makefile.in, authlibmysql/README,
+ authlibmysql/auth.h, authlibmysql/authmysql.c,
+ authlibmysql/configure.ac, authlibsmb/AUTHORS,
+ authlibsmb/CHANGES, authlibsmb/COPYING,
+ authlibsmb/Makefile.in, authlibsmb/README,
+ authlibsmb/auth.h, authlibsmb/authsmb.c,
+ authlibsmb/configure.ac, authlibsmb/valid.h,
+ authlibsmb/smbval/Makefile.in, authlibsmb/smbval/byteorder.h,
+ authlibsmb/smbval/md4.c,
+ authlibsmb/smbval/rfcnb-common.h,
+ authlibsmb/smbval/rfcnb-error.h, authlibsmb/smbval/rfcnb-io.c,
+ authlibsmb/smbval/rfcnb-io.h,
+ authlibsmb/smbval/rfcnb-priv.h,
+ authlibsmb/smbval/rfcnb-util.c,
+ authlibsmb/smbval/rfcnb-util.h, authlibsmb/smbval/rfcnb.h,
+ authlibsmb/smbval/session.c,
+ authlibsmb/smbval/smbdes.c, authlibsmb/smbval/smbencrypt.c,
+ authlibsmb/smbval/smblib-common.h,
+ authlibsmb/smbval/smblib-priv.h,
+ authlibsmb/smbval/smblib-util.c, authlibsmb/smbval/smblib.c,
+ authlibsmb/smbval/smblib.h,
+ authlibsmb/smbval/std-defines.h,
+ authlibsmb/smbval/std-includes.h, authlibsmb/smbval/valid.c,
+ authlibsmb/smbval/valid.h: Finally added module code
+ into CVS
+
+ 2002-10-20 Beau Kuiper <address@hidden>
+
+ * Makefile.in, autogen.sh, configure.ac,
+ defaults.h, defaults.h.in, install-sh: Imported
+ authentication modules into build system.
+
+ Install does not work properly for modules, and there are still
+ some more tweaks to do
+
+ 2002-10-20 Joerg Jaspert <address@hidden>
+
+ * Developer.txt: Added suggestions from Beau
+
+ 2002-10-19 Joerg Jaspert <address@hidden>
+
+ * Developer.txt: First version of Guidelines for People
+ working on Muddleftpd
+
+ 2002-10-17 Beau Kuiper <address@hidden>
+
+ * Makefile.in, config.h.in, src/version.c:
+ updated to autoconf 2.54
+
+ 2002-10-17 Beau Kuiper <address@hidden>
+
+ * Makefile.in, configure, configure.ac,
+ configure.in: updated to autoconf 2.54
+
+ 2002-10-16 Beau Kuiper <address@hidden>
+
+ * src/logger.c: Logger patch was broken
+
+ Character constants are in ', not in " And character 20 is not a
+ space, while 0x20 is
+
+ 2002-09-28 Joerg Jaspert <address@hidden>
+
+ * src/util/seteguid.c~: Well, it exists in the original
+ tarball, but its a backup file -> delete it :)
+
+ 2002-09-28 Joerg Jaspert <address@hidden>
+
+ * src/util/: pwgrent.c, seteguid.c, seteguid.c~,
+ snprintf.c, strerror.c, strerror.h: Uhh, looks
+ like i missed to add them into CVS
+
+ 2002-09-26 Joerg Jaspert <address@hidden>
+
+ * defaults.h: Ok, devel version is odd, stable is even.
+
+ 2002-09-26 Joerg Jaspert <address@hidden>
+
+ * defaults.h: This is now 1.3.12 and no longer 1.3.11-devel
+
+ 2002-09-26 Joerg Jaspert <address@hidden>
+
+ * src/logger.c: Remove \r and \n before output to logfile
+
+ 2002-09-26 Joerg Jaspert <address@hidden>
+
+ * AUTHORS: Changed debian maintainer
+
+ 2002-09-26 Joerg Jaspert <address@hidden>
+
+ * AUTHORS, CHANGES, COPYING, INSTALL,
+ Makefile.defs, Makefile.in, README, TESTING,
+ TODO, config.h.in, configure, configure.in,
+ defaults.h, doc/Makefile.in, doc/cookie.txt,
+ doc/ftpcmds.txt, doc/muddleftpd.txt,
+ doc/mudlogd.txt, doc/mudpasswd.txt, doc/reference.txt,
+ doc/info/muddleftpd.info, doc/info/muddleftpd.texi,
+ doc/man/ftpwho.1, doc/man/muddleftpd.1,
+ doc/man/mudpasswd.1, examples/README,
+ examples/anon-only.conf, examples/anon-reigon.conf,
+ examples/mudlogd.conf, examples/ratios.conf,
+ examples/standard.conf, examples/vserver-host.conf,
+ examples/vserver.conf, examples/vserverbig.conf,
+ src/Makefile.in, src/acl.c, src/acl.h, src/auth.c,
+ src/auth.h, src/authanon.c, src/authdisable.c,
+ src/authint.c, src/authpam.c, src/authunix.c,
+ src/bufread.c, src/cfloader.c, src/checkip.c,
+ src/cmd.c, src/config.c, src/configfile.h,
+ src/datasock.c, src/dir.c, src/file.c, src/ftp.c,
+ src/ftpcmd.h, src/ftpd.h, src/ftplist.c,
+ src/ftpout.c, src/ftpsite.c, src/ftpstat.c,
+ src/ftpstate.c, src/ftptrans.c, src/ftpwho.c,
+ src/init.c, src/logger.c, src/main.c,
+ src/malloc.c, src/mudlogd.c, src/mudpasswd.c,
+ src/myglob.c, src/myglob.h, src/newfile.c,
+ src/pnums.h, src/procnum.c, src/proxy.c,
+ src/ratio.c, src/ratio.h, src/ratiotool.c,
+ src/reply.h, src/select.c, src/shmem.c,
+ src/socket.c, src/string.c, src/string.h,
+ src/tokset.h, src/utils.c, src/version.c,
+ tools/muddlestats.0.3.0/AUTHORS,
+ tools/muddlestats.0.3.0/COPYING,
+ tools/muddlestats.0.3.0/INSTALL,
+ tools/muddlestats.0.3.0/README, tools/muddlestats.0.3.0/TODO,
+ tools/muddlestats.0.3.0/muddleftpd.logrotate,
+ tools/muddlestats.0.3.0/muddlestats-gather.py,
+ tools/muddlestats.0.3.0/muddlestats.lsm,
+ tools/muddlestats.0.3.0/muddlestats.py: Imported muddleftpd
+
+
+ Copyright (C) 2002 Muddleftpd Team, http://www.nongnu.org/muddleftpd/
+ Copying and distribution of this file, with or without modification, are
+ permitted provided the copyright notice and this notice are preserved.
Index: muddleftpd/Makefile.defs
diff -c /dev/null muddleftpd/Makefile.defs:1.1.12.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/Makefile.defs Tue Nov 4 10:41:21 2003
***************
*** 0 ****
--- 1,31 ----
+ # Copyright (C) 1999 Beau Kuiper
+
+ # 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ # **** THINGS YOU CAN CHANGE!
+
+ # Use the new malloc implementation. Disable to use the system malloc
+ NEWMALLOC = 1
+
+ # Build a debug version. Don't use for production
+ DEBUG = 1
+
+ # Destination filenames
+ MUDOUTPROG = muddleftpd
+ WHOPROG = ftpwho
+ MUDPASSWDPROG = mudpasswd
+ RATIOTOOLPROG = ratiotool
+ MUDLOGD = mudlogd
+
Index: muddleftpd/NEWS
diff -c /dev/null muddleftpd/NEWS:1.4.2.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/NEWS Tue Nov 4 10:41:21 2003
***************
*** 0 ****
--- 1,978 ----
+
+ Version 1.3.13-dev-nat:
+
+ 1) Bug Fix: Fixed checking of ftp ports to allow ports > 32768 to be
+ used as the control port.
+ 2) Bug Fix: Fixed vserverdefault undefined error message.
+ 3) Change: Added port range configuration for Passive connections.
+ This allows passive connections to work in firewalled or
+ NAT environments.
+ 4) Change: Added support for NAT. Added option ipnat for the user to
+ specify their real external IP address, and the option
+ nat_netclass to allow users to specify what IP's will see
+ the servers internal addresses and what IP's will see
+ the servers external address specified by ipnat option.
+
+ Version 1.3.13:
+
+ 1) Change: Revamped build system to use new build tools.
+ 2) Change: Included authentication modules into build system.
+ They are installed (if selected at configure time) into
+ the libdir from configure. Normally prefix/lib
+ (/usr/local/lib if not specified).
+ 3) Bug Fix: Properly fixed bug in 1.3.12.1, so muddleftpd does not
+ accept /r or /n from user input unless it is the form of
+ a TELNET newline.
+ 4) Bug Fix: Scrambled output on PPC systems fixed. (possibly other
+ systems too)
+ 5) Change: Install .txt documentation in prefix/share/doc/muddleftpd/*.
+
+ Version 1.3.12.1:
+
+ 1) Bug Fix: Fixed logging of /r and /n so they are converted to
+ spaces.
+
+ Version 1.3.12:
+
+ 1) Bug Fix: Linux does not like custom PASV replies with ip-masq.
+ Using reply recommended (but not mandatory) in RFC959.
+ (Beau Kuiper)
+ 2) Change: Included support for large files (> 2 gig) on 32bit
+ systems.
+ 3) Change: Removed QUIET compile option, replaced by verbose
+ parameter.
+ 4) Change: Added support for HP-UX 11.00
+ 5) Bug Fix: fixed warnings with GCC 3.X compiler
+
+ Version 1.3.11:
+
+ 1) Change: Updated mudlogd. now sighup will reload config file.
+ (Beau Kuiper)
+ 2) Bug Fix: Overflowing port value allowed sending data to ports
+ below 1024 dispite restrictions. (Beau Kuiper)
+ 3) Bug Fix: Fixed storing files so they are truncated to the
+ start position, like other ftpds. (Beau Kuiper)
+ 4) Bug Fix: Removed races in the STOR and STOU commands.
+ (Beau Kuiper)
+ 5) Bug Fix: Removed race in STOU unique filename generator.
+ (Beau Kuiper)
+ 6) Change: Minor optimizations, less malloc frobbing in some common
+ code paths.
+
+ Version 1.3.10:
+
+ 1) Bug Fix: Fixed warnings from gcc. (Beau Kuiper)
+ 2) Change: Added %(x,*)d format for cookies. (Beau Kuiper)
+ 3) Bug Fix: Fixed gid/uid handling, corrected casting,
+ mainly useful for older machines with 16bit uid and gid
+ (Beau Kuiper)
+ 4) Bug Fix: Fixed manual page installation to put .1 at the end.
+ (Decklen Foster)
+ 5) Bug Fix: Fixed makefile problems. (Beau Kuiper)
+ 6) Bug Fix: Fixed freeing of null pointers when specified configuration
+ file is a directory. (Beau Kuiper)
+ 7) Bug Fix: Fixed gid/uid handling so NIS works. (Beau Kuiper)
+ 8) Change: Now using new malloc library. It is much better than
+ most other mallocs, including GNU's (Beau Kuiper)
+ 9) Change: Added the package Muddlestats. It seems very good and
+ has a promising future. (McRee)
+ 10) Bug Fix: Fixed uploads on IBM AIX systems. This bug has existed
+ a long time. (Beau Kuiper, helped by Sergey Novoselov)
+ 11) Bug Fix: Fixed recursive directory listings again (Beau Kuiper,
+ helped by Nik Soggia)
+ 12) Documentation: Minor changes to example configs. (Beau Kuiper)
+ 13) Documentation: Added mudlogd documentation. (Beau Kuiper)
+ 14) Change: Added the mudlogd program, which works separatly from
+ muddleftpd to allow simple log rotation. (Beau Kuiper)
+
+ Version 1.3.9:
+
+ 1) Bug Fix: Connection rejections if DNS broken fixed. (Beau Kuiper)
+ 2) Documentation: added mudpasswd manual page. (Decklen Foster)
+ 3) Bug Fix: Better error reporting in ftpwho (Decklen Foster)
+ 4) Documentation: Minor change to info page. (Decklen Foster)
+ 5) Bug Fix: made forking into background a command line
+ parameter instead of a #define (Beau Kuiper)
+ 6) Change: added separate upload/download speed limiters for people
+ with differing upload and download speeds, eg cable modem
+ and ASDL. (Beau Kuiper)
+ 7) Change: changed source tree directory structure, separating source
+ files into thier own directory. (Beau Kuiper)
+ 8) Bug Fix: Fixed directory listing again, so even simpler and
+ better. (Beau Kuiper)
+ 9) Bug Fix: Small memory leak in listing code fixed. (Beau Kuiper)
+ 10) Bug Fix: Finally fixed date parsing in list code so year is
+ displayed if last modified was a different year.
+ (Beau Kuiper)
+ 11) Bug Fix: String length checking fixes for config files.
+ (Tomas Ogren)
+ 12) Bug Fix: Memory alignment issues fixed in configuration
+ include sections (Tomas Ogren)
+ 13) Bug Fix: Some libc's don't like being told to vsnprintf
+ without a buffer. Fixed autoconf script to
+ check for this and use replacement if true.
+ (reported by Tomas Ogren, fixed by Beau Kuiper)
+ 14) Bug Fix: Moved HOST reply strings to reply.h (Beau Kuiper)
+ 15) Change: added EPSV and EPRT commands, to support IPV6 at
+ a later date. (Beau Kuiper)
+ 16) Change: added busydumpdata directive option for main and
+ virtual server sections. Now the server won't blindly
+ disconnect if too many users connect at the same
+ time. (Idea by Tomas Ogren, done by Beau Kuiper)
+ 17) Bug Fix: Fixed makefiles to use configure specified manpage
+ and info directories. (Decklin Foster)
+ 18) Bug Fix: Fixed ABOR to forget any data port information.
+ (Beau Kuoper)
+ 19) Bug Fix: Fixed default data port handling, with server using
+ the wrong IP address. (Beau Kuiper)
+ 20) Bug Fix: Fixed SITE error message with no parameters.
+ (Beau Kuiper)
+
+ Version 1.3.8:
+
+ 1) Bug Fix: Fixed bug in ratio record creation
+ 2) Change: Added HOST support as outlined in the draft I have
+ written.
+ 3) Bug Fix: Minor fix for errorous exit. Now exits with 1 if an
+ error occurs. Suggested by Decklin Foster
+ 4) Bug Fix: More descriptive error messages for when the server
+ has too many users.
+ 5) Bug Fix: Recursive listing crashed muddleftpd if the last dir
+ scanned but the recurse algorithm is empty.
+ 6) Bug Fix: substantial fix to be more compatible with /bin/ls for
+ recursive lists. Should fix mirror.pl
+ 7) Bug Fix: upload resume using STOR command fixed. A very simple
+ mistake that existed in the whole (1.3.X) series.
+ 8) Bug Fix: Fixed free NULL pointer error when no ipacls specified.
+
+ Version 1.3.7:
+
+ 1) Bug Fix: Listing ACL's did not work correctly.
+ 2) Bug Fix: Major bug in freeing children caused major problems
+ after server maxusers had logged in and out.
+ 3) Bug Fix: Bind errors were being displayed when using runasuser
+ directive. They are now ignored (they are harmless)
+ 4) Bug Fix: SIGHUP is now not acted upon if runasuser is active.
+
+ Version 1.3.6:
+
+ 1) Bug Fix: Fixed serious DOS bug when the new maxipconnect
+ directive is used.
+
+ Version 1.3.5:
+
+ 1) Change: Pam module now accepts option pam_user, to force
+ the username it will read from the password file and
+ return the credentials for.
+ 2) Bug Fix: better logging of some failed calls.
+ 3) Change: Now quitdump, cddump and welcome do not need to be
+ specified specially for chroot mode.
+ 4) Bug Fix: string.c changed for easier porting. Was GCC dependant.
+ 5) Bug Fix: memcpy bug while resolving hostnames.
+ 6) Bug Fix: Improper handling of uid, gid in authentication.
+ 7) Bug Fix: Warnings repaired, prototypes rebuilt using scribe.
+ 8) Change: Ftp list code now supports recursive listing. The listing
+ code is very fast/memory efficient.
+ 9) Bug Fix: Fixed memory leak while authenticating user.
+ 10) Change: Added funtions to retrieve hostname/ip from
+ authentication modules.
+ 11) Change: I am using my own glob routines now, sorts correctly for
+ machines without glob.
+ 12) Change: The fnmatch code I wrote is now being used regardless of
+ whether the library has its own one.
+ 13) Bug Fix: fnaccess and pfnaccess have been repaired, and can be
+ used.
+ 14) Change: Listing now shows total directory sizes like the real
+ ls.
+ 15) Bug Fix: Dumping relative files when changing directories caused
+ the file for the last directory to be dumped
+ 16) Bug Fix: ratiotool failed to set correct file permissions on
+ a newly created ratio file.
+ 17) Bug Fix: compile fixes for IRIX.
+ 18) Bug Fix: Macros broken in ftpd.h
+ 19) Bug Fix: Ips were shown backwards in ftpwho if reverse hostname
+ was not found.
+ 20) Change: Added option maxconnectperip. This limits the number of
+ connections from a single IP address.
+ 21) Bug Fix: Fix when user operation is more than 120 characters.
+ This lead to ftpwho printing the hostname after the
+ operation.
+ 22) Bug Fix: cookies in access directives were not being applied
+ correctly.
+ 23) Bug Fix: Signals must be blocked while reloading config, or
+ deleting users, or bad things happen
+
+ Version 1.3.4:
+
+ 1) Bug Fix: The internal password module was feeding the config
+ error function the wrong variable.
+ 2) Bug Fix: Fixed a bug in include handling that would prevent
+ use in 64bit environments.
+ 3) Bug Fix: Include looping is now checked before config file is
+ loaded.
+ 4) Change: Removed authparams option. Auth modules get to fend for
+ themselves (this provides more functionality, and better
+ directive names)
+ 5) Bug Fix: Help was not being shown correctly.
+ 6) Documentation: Updated some documentation.
+ 7) Bug Fix: Possible to free NULL pointers in config.c
+ 8) Change: Changed a few error messages to be more understandable.
+ 9) Change: A temporary change that will lock up muddleftpd if it
+ tries to free a NULL pointer. It locks muddleftpd up
+ so a debugger can get a clean backtrace of the program.
+ 10) Bug Fix: Fix for attempting to rotate logs while in droproot
+ mode.
+ 11) Bug Fix: Usernames are more rigourously checked because
+ regular expression characters in accepted usernames
+ may provide more access than intended.
+ 12) Change: The anonymous authentication module now returns the uid
+ and gid of nobody instead of the ftp user. This is
+ more consistent with other ftp servers.
+ 13) Change: Listing of devices is more accurate, showing the
+ major and minor device numbers like real ls.
+ 14) Change: Muddleftpd now uses the real hostname as the default
+ hostname of the host and virtual servers.
+ 15) Change: Ipacl for hostnames must be in brackets. Without
+ brackets, it is always checked against the IP
+ 16) Bug Fix: got rid of any use of inet_ntoa, since I wasn't
+ using it right.
+ 17) Change: Set default logstrength to log everything.
+ 18) Documentation: Documented all server directives.
+
+ Version 1.3.3:
+
+ 1) Change: Can now use %v in group config to get current virtual
+ server section name and %V to get current virtual server
+ host name. Ratio %v and %V are now %a and %A
+ 2) Change: Can now use tokens in greeting line.
+ 3) Bug Fix: Fix for bug where directories with % in them did weird
+ things (see version 1.2.10)
+ 4) Change: New config option droproot. This option will drop all
+ root prividges when a user logs. It also will use
+ capibilities so it can still use low numbered ports on
+ linux 2.2 or better if libcap is installed.
+ 5) Change: reply.h now contains macros to the replys the server
+ generates, It allows replies for foriegn languages or
+ other ftp servers to be used, basicly changing the
+ persona of the ftp server.
+ 6) Bug Fix: muddleftpd was not correctly enforcing the one command
+ at a time requirement of FTP.
+ 7) Bug Fix: muddleftpd was not updateing upload/download byte
+ counter.
+
+ Version 1.3.2:
+
+ 1) Bug Fix: Muddleftpd is much more careful now about the
+ configuration file it listens to. The config file now
+ must be owned by the user/group who runs it, and must
+ not be world or group writable. This fixes a security
+ vulnerability in ftpwho if it is setuid. Same for
+ internal password files.
+ 2) Change: Added the -n option to display IP's instead of hostnames
+ in ftpwho.
+ 3) Bug Fix: Fix for truncated replys where length of reply was more
+ than 1024 characters.
+ 4) Change: Implemented new directive include, which allows you to
+ include another section in the current section. Good for
+ creating templates.
+ 5) Change: Changed how config errors were handled, improving error
+ reporting and detection
+ 6) Change: By default, muddleftpd is built to be quiet on startup.
+ 7) Change: ratios now get data from groups section rather than a
+ separate section. Use include to have ratio directives in
+ other sections.
+ 8) Change: Sending SIGUSR1 to the server process will make it reopen
+ the log file and instruct the children servers to do the
+ same. Note that chrooted server children will not be able
+ to reopen the log file.
+ 9) Change: added fnmatch pattern based access controls, including
+ controls to explicitly match slashes.
+ 10) Bug Fix: Maximum process limit setting was broken, fixed.
+ 11) Bug Fix: Symbolic links were always assumed readable in the
+ listing code. Does not work because the /proc
+ filesystem actually has non-world readable symbolic
+ links.
+
+ Version 1.3.1:
+
+ 1) Change: Minor changes to how the scratchfile is used.
+ 2) Change: Muddleftpd now uses proper unix style arguments. It
+ has a usage screen and a version option.
+ 3) Change: PORT command more verbose, repling where it will connect
+ to.
+ 4) Change: root privliges are given for connecting to low number
+ ports. This is for RFC951 complience.
+ 5) Bug Fix: Fixed code so muddleftpd runs of FreeBSD. Borrowed :-)
+ some code from proftpd (for functions fgetpwent and
+ fgetgrent)
+ 6) Bug Fix: snprintf replacement code has a bug causing very bad
+ problems.
+ 7) Bug Fix: removed TCP_CORK code since it only slows data transfers
+ down.
+ 8) Bug Fix: Fixed a few compile bugs.
+ 9) Change: Changed log format and how log was written
+ 10) Change: Added support of dlopen modules for authentication
+ modules
+ 11) Change: Minor updates to authentication module interfaces.
+ 12) Change: Passwords used by anonymous users are now logged.
+ 13) Bug Fix: Fixed %N cookie for user count.
+ 14) Change: Got rid of pidfile support, now ftpwho -p will return
+ the pid of the running standalone muddleftpd.
+ 15) Change: Now scratchfile is used for locking in both inetd and
+ standalone modes. This means the server doesn't need to
+ lock against the config file and it could be changed
+ without problems.
+ 16) Change: ftpwho program rewritten and much more useful now :-)
+ 17) Bug Fix: A couple of missing returns fixed. Should have caused
+ problems already :-)
+ 18) Bug Fix: A bug in acl.c fixed where segfault would occur if no
+ ACLs were specified for a user
+ 19) Change: Authentication modules can now cancel authentication of
+ a user if a serious error occurs.
+ 20) Change: Authentication is now cancelled if an authentication
+ module cannot be found.
+ 21) Change: If muddleftpd cannot bind to a port when it starts up,
+ then it will exit. If it cannot bind to a port when
+ you issue a SIGHUP, then it will log it and continue.
+ 22) Change: Commands can now be disabled per group within the config
+ file.
+ 23) Bug Fix: Data corruption bug after SIGHUP removes a virtual
+ server fixed.
+ 24) Change: When a user connects, muddleftpd will fail to recognize
+ all but a few commands needed to login.
+ 25) Change: ftpwho reports vservers using their section names.
+ 26) Change: Now download speed limits can be specified per group
+ These are highly accurate and reasonably smooth.
+ 27) Bug Fix: Porting fixes for weirder unixes including simple-glob
+ fixes.
+ 28) Bug Fix: Small bug parsing gid lists caused crashes with long
+ suplemental gid lists.
+ 29) Change: Speed limits now also apply to file lists and uploads.
+ 30) Bug Fix: New listing code would possibly break when a partial write
+ occured.
+ 31) Change: Finished logindumpdata support.
+
+ Version 1.3.0:
+
+ 1) Bug Fix: for large maxusers, the default settings would cause
+ muddleftpd to croak. Fixed.
+ 2) Bug Fix: for long usernames and non-default constant values, a
+ possible problem with setting username has been fixed
+ 3) Change: PAM module now does more logging to aid debugging.
+ 4) Change: shared memory is more compact now, only storing thread
+ users.
+ 5) Change: EXPERIMENTAL INETD SUPPORT!!!!
+ 6) Bug Fix: on systems that need -ldl for pam support, it would
+ cause pam support not to compile. Fixed.
+ 7) Bug Fix: if muddleftpd is running inetd mode, now errormessages
+ go to the system log.
+ 8) Change: Log message now emmitted if non-existant auth method
+ used.
+ 9) Change: Better debug logging system now in place. Can work
+ even with inetd
+ 10) Bug Fix: Fix to MDTM. This broke netscape quite convincingly
+ 11) Bug Fix: Fix for netscape race and maybe other clients.
+ 12) Change: All configuration is in single file now! This improves
+ performace muchly esp under load.
+ 13) Documentation: Examples updated for new code!
+ 14) Bug Fix: Fix to logging where SITE commands were logged twice.
+ 15) Bug Fix: Listing bug fixed where files were being used as
+ regular expressions.
+ 16) Chnage: Replaced ACL code. New code also recognises mkdir and
+ rmdir, chmod and chdir. Add only applies to files now.
+ 17) Change: Now ip's can be denied as well as allowed with the new
+ ipacl directive. Note that the order ipacl's are
+ specified in is very important.
+ 18) Change: Now log messages are generated when a user logs out
+ of the server.
+ 19) Bug Fix: User cannot specify PORT command with data port < 1024
+ 20) Bug Fix: Total file size is now given when doing binary
+ downloads, regardless of starting position. Other
+ ftp servers act this way, and some client expect it.
+ 21) Bug Fix: Maximum timeout was not correctly set.
+ 22) Change: Writing to control port now has timeout, so it cannot
+ lock up.
+ 23) Change: Continuation messages have new format that look nicer.
+ 24) Change: New group system is working, It now traverses a list
+ of groups in the user file to determine what group a
+ user is. It needs more work ATM.
+ 25) Change: added IP and name access lists to make group system
+ very, very, very configurable.
+ 26) Bug Fix: For systems which uses non-DES encryption, muddleftpd
+ used crypt correctly.
+ 27) Change: added hostname based matching and hostnames in logs.
+ 28) Change: reverse dns timout setting added
+ 29) Change: Alternate long reply format option added, allows for bad
+ proxys and stuff.
+ 30) Change: VIRTUAL SERVER SUPPORT ADDED. Not yet completed or
+ optimised for file descriptor usage.
+ 31) Bug Fix: Fixed several small bugs found in 1.2.2.
+ 32) Bug Fix: A minor bug working with parameters fixed.
+ 33) Bug Fix: A bug when parsing config files caused tabs to be
+ misinterpreted.
+ 34) Change: Smart binding. This allow muddleftpd to minimize the
+ number of file descriptors used when binding files.
+ 35) Change: Zero binding. When used with smart binding above, allows
+ virtual servers to be used on all servers. This basicly
+ makes sure all binds are performed on address 0.0.0.0
+ 36) Change: Using rlimits instead of manually checking memory size
+ for determining overuse of memory.
+ 37) Change: Made single configuration file loading to be less memory
+ intensive.
+ 38) Change: Server will now reload config file with a HUP signal.
+ 39) Change: Server now lets you specify if you want to real chroot
+ to the rootdir instead of doing a pretend chroot. It is
+ ignored if root access isn't avaliable. This provides
+ extreme security for paranoid system administrators
+ (like me!)
+ 40) Change: When a user logs in, the uid/gid is switched to that
+ user instead of being left as root. This reduces code
+ size and improves security. I also seem to learn things
+ the hard way (I should have had this ages ago)
+ 41) Change: Ratio support. An external binary file is used for this,
+ and users are added to it as they log in. Ratio's are
+ implimented so multiple sessions are no problem. Ratios
+ apply to both files and bytes, and can be persistant or
+ non-persistant.
+ 42) Change: Config changes. Now parameters are easier to specify,
+ and including spaces is easy.
+ 43) Change: By default, muddleftpd now doesn't allow access to non
+ regular files (eg device files). To re-enable use
+ devaccess in group sections.
+ 44) Change: Full group support, include supplementry group lists.
+ 45) Change: Added a ratio changing program, ratiotool. It can add,
+ edit and psudo-delete ratio file entries. It is safe to
+ use while the server is running.
+ 46) Bug fix: Fixed a small bug that always put an extra / at the
+ beginning of a filename in the log if rootdir is /
+ 47) Change: If rootdir contains symlinks, they are now dereferenced
+ as the user logs in.
+ 48) Change: Added a realdir option. This will automaticly report the
+ real directory name, with all symlinks dereferenced,
+ instead of the internal construction.
+ 49) Change: Added code to detect broken snprintf, and to work out
+ which syntax it uses and use that syntax.
+ 50) Change: Detects if double ints work correctly and disables
+ ratios if they don't
+ 51) Change: Added fxpallow option, so server-server transfers may
+ work on a per-group basis.
+ 52) Change: Implemented output buffer to make sure long replies are
+ sent effeciently.
+ 53) Change: Input from dumped files and user is now put through a
+ filter that removes non-printable characters.
+ 54) Change: Implemented options to specify long replies directly in
+ the config file
+ 55) Change: Data port handling rewritten, should be a little faster
+ now.
+ 56) Change: Sendfile() support implemented. This should improve
+ performace slightly, but linux needs a better sendfile :(
+ 57) Change: Groups and vserver limits are handled in a much better
+ way now. Faster for standalone operation, correct for
+ inetd operation.
+ 58) Change: Log now contains thread id so it is easier to trace what
+ a specific user is doing
+
+ Version 1.2.10:
+
+ 1) Bug Fix: Bug where % in pathname would cause weird errors when
+ current directory was displayed. It was caused by using
+ the output of one printf (with user supplied data)
+ as the format string in the next. Fixed by removing all
+ (except where it is obviously safe) non-constant format
+ strings in the source. Entire source was checked for the
+ problem.
+
+ Version 1.2.9:
+
+ 1) Bug Fix: Mudpasswd backported from 1.3.X. Fixes problems with
+ mudpasswd segfaulting.
+ 2) Change: Included an init file for system V init scripts
+ 3) Chnage: Added a spec file for rpm generation. Havn't tested it
+ yet.
+
+ Version 1.2.8:
+
+ 1) Bug Fix: Another config file reading bug fixed. If you used tabs
+ at the end of a value, they would not be discarded by
+ the ftp server.
+ 2) Bug Fix: Repaired the README file.
+
+ Version 1.2.7:
+
+ 1) Bug Fix: Rename bug fixed. Ops :-) Occured because errno wasn't
+ reset correctly.
+
+ Version 1.2.6:
+
+ 1) Bug Fix: Fixed bug where garbage was printed if null password
+ was supplied.
+
+ Version 1.2.5:
+
+ 1) Bug Fix: snprintf madness fixed. Server now works for all known
+ snprintf types.
+ 2) Bug Fix: fixed the provided snprintf so it reports -1 if result
+ is too long.
+ 3) Bug Fix: ftpwho would segfault in certain denied access cases.
+
+ Version 1.2.4:
+
+ 1) Bug Fix: Parsing problems with tab separating name and value
+ pairs fixed.
+ 2) Change: Ftpwho program revamped. It can now do reverse IP lookups
+ for hostnames and supports regular options. Run ftpwho -h
+ to see options.
+ 3) Bug Fix: Problems with zero length strings on ftp commands fixed.
+ No real problems, just zero length parameters need to
+ be detected and reported as missing parameters.
+ 2) Bug Fix: A secuity problem with cddump relative files has been
+ fixed. If the user could create a symlink as the name
+ of a relative cddump file, the user could view any file
+ on the system over the control connection.
+
+ Version 1.2.3 (was 1.1.1c)
+
+ 1) Bug Fix: Active data connections now bind to specific interface.
+ Old method seemed to fail when used with strict ip
+ filewalls.
+ 2) Bug Fix: If an error occured accepting a control connection, the
+ server would bad.
+ 3) Bug Fix: If the PASV command couldn't bind to a port, it wouldn't
+ cleanly report the error.
+ 4) Bug Fix: An extra close was hiding the real cause of data port
+ connection failure.
+ 5) Bug Fix: Some calls to create sockets were not checked correctly.
+ 6) Bug Fix: No error was displayed if passive port connection
+ accept fails
+ 7) Bug Fix: Slight change in Makefile so that CFLAGS is recognised.
+
+ Version 1.1.1b (now 1.2.2):
+
+ 1) Bug Fix: if you didn't set authmethod in the config file, the
+ server process would crash.
+ 2) Bug Fix: if you use a non-DES crypt function, muddleftpd would
+ not authenticate properly. This bugfix fixes for a least
+ slackware 7.0.
+ 3) Change: New versioning system. Now I copy the linux versioning
+ system since I cannot get it right myself.
+ 4) Bug Fix: if a list failed due that was not the fault of glob,
+ then server would crash tring to free a non-existant
+ variable:
+ 5) Change: You can use group/usernames for uid/gid specification now
+ in user config files and authentication modules.
+
+ Version 1.1.1a (now 1.2.1):
+
+ 1) Bug Fix: Long usernames would cause the server to crash. Not an
+ exploitable bug, but not very nice looking.
+ 2) Bug Fix: files dumped over control connection were not logged
+ correctly.
+
+ Version 1.1.1 (now 1.2.0):
+
+ 1) Bug Fix: A minor memory leak was sealed.
+ 2) Bug Fix: Changed ACL error code to EACCES instead of
+ EPERM.
+ 3) Documentation: Added the info file back.
+ 4) Change: log entry generated when a user logs out of the ftp
+ server
+ 5) Bug Fix: Server will not allow client to specify a data port
+ less than 1024.
+ 6) Bug Fix: Changed byte count when starting download to total size
+ of file regardless of restart position. Other ftp
+ servers act this way, and some clients use this info.
+ 7) Change: When authenticating users, the server will change to
+ the configuration directory. This will improve
+ robustness of marginally defined configurations.
+ 8) Bug Fix: Maximum timeout was not set correctly when logging user
+ in.
+ 9) Bug Fix: Minor fixes for platform independance in mudpasswd.
+
+ Version 1.1.1beta3:
+
+ 1) Bug Fix: invalid rootdir message didn't show root dir.
+ 2) Bug Fix: fix for site commands being logged twice.
+ 3) Documentation: info files removed for now since maintainer
+ hasn't reponded to email.
+ 4) Bug Fix: Directory listing problems solved.
+
+ Version 1.1.1beta2:
+
+ 1) Bug Fix: Pam support didn't compile on system with dynamic linking
+ in a library
+ 2) Bug Fix: Small change to code to prevent problems if username
+ length constants get changed.
+ 3) Bug Fix: Fix to MDTM command, broke netscape access quite well :)
+ 4) Bug Fix: Fix for netscape race and maybe other clients.
+
+ Version 1.1.1beta1:
+
+ 1) Change: Changed the error message management system. Now much
+ better.
+ 2) Change: Help now contains descriptions for each command.
+ 3) Change: Full shadow password support with account expiry.
+ 4) Change: User now gets message as to why login fails.
+ 5) Bug Fix: strerror was compiled even if it already existed!
+ 6) Change: PAM support has been added!
+ 7) Bug Fix: now all root logins get demoted to user nobody like they
+ should
+ 8) Bug Fix: now user nobody from the password file is used to
+ determine what user nobody is. Any system without a user
+ nobody is in SERIOUS TROUBLE!
+ 9) Change: Added the disabled user authentication which will disable
+ a user.
+ 10) Bug Fix: Added a copy of the usleep function for older computers.
+ 11) Documentation: Fixed documentation for new features.
+ 12) Bug Fix: Put limits on maximum generated string lengths to
+ prevent users from filling virtual memory.
+ 13) Change: Added SITE IDLE command.
+
+ Version 1.1.1beta0:
+
+ 1) Change: Log message emitted when user cannot login due to bad
+ root dir
+ 2) Change: Error messages for socket connection are better handled.
+ 3) Change: added -d option to list a directory instead of its
+ contents.
+ 4) Change: Major refit of auth code. Now all auth code is modularied
+ into the different sources. Makes adding new auth schemes
+ easily.
+ 5) Change: new unix auth module can autodetect shadow passwords!
+ 6) Change: config files can handle windows style files.
+ 7) Change: added an internal password file support module.
+ 8) Change: added runasuser option in main config file.
+ 9) Change: removed runasuid and runasgid from main config file.
+ 10) Change: created a simple mudpasswd program to modify internal
+ password files.
+ 11) Change: Minor server reply tweeks.
+ 12) Documentation: Fixed examples for new code.
+ 13) Change: Added the badauthwait option to the main config file to
+ cause the server to wait a specifed number of milliseconds
+ if the user doesn't provide the correct password.
+ 14) Change: Added the userjail option to user files so when the user
+ logs in, he/she will not be able to log into a new user.
+ Good for anonymous accounts.
+ 15) Change: Added the logintrys option to the main config file. This
+ tells the server how many attempts a connection has to
+ login before the server refuses to log the user in.
+
+ Version 1.1:
+
+ 1) Documentation: Added man page and info pages. Thanks to
+ Jonas Oberg <address@hidden> for this.
+ 2) Bug Fix: Spelling mistake in init.c fixed. Thanks to
+ Jonas Oberg <address@hidden> for noticing my mistake.
+ 3) Change: Server will now detect if it needs root access to bind to a
+ port and gives a message to the user if it is so.
+
+ Version 1.1.beta3: Final beta if no bugs are found!
+
+ 1) Bug Fix: Fixed Makefile so QUIET=1 option is recognised.
+ 2) Bug Fix: Fixed spelling mistake in init.c (already instead of
+ aleady)
+ 3) Documentation: Added some documentation on how to build and install
+ muddleftpd (muddleftpd.txt)
+ 4) Documentation: Updated README and INSTALL.
+ 5) Bug Fix: If unixuser is specified and that specified user doesn't
+ exist, login will fail automaticly.
+ 6) Bug Fix: If it can't load a user's config file, it will now
+ output a log message.
+ 7) Bug Fix: Checks on files and directories now done in user auth
+ files.
+ 8) Change: Minor optimisations to improve processing of file
+ dumping, streamlines code.
+ 9) Bug Fix: busydump was crashing, due to incorrect working
+ directory value, fixed!
+ 10) Bug Fix: the username in the shared memory structure is properly
+ updated at the correct time. Allows a user with
+ maxconnect 1, to relogin.
+ 11) Documentation: Added documentation for user configuration files.
+ 12) Bug Fix: now mud authenication stuff is not compiled by default.
+ 13) Documentation: Added documentation for cookies in user config
+ files.
+ 14) Documentation: Added documentation for accepted ftp commands.
+ 15) Documentation: Gave up on HTML documentation!
+
+ Version 1.1.beta2:
+
+ 1) Change: Failed magic cookie tranformations are logged so that the
+ admin can find if cookies fail. (I decided that this
+ change is minor enough and important enough to be added
+ before version 1.1)
+ 2) Bug Fix: Download statistics were not correctly tallyed.
+ 3) Documentation: Added documentation for dumped file magic cookies
+ (cookies.txt)
+ 4) Documentation: Added documentation for ftpwho. (ftpwho.txt)
+ 5) Documentation: changed user.other so that if the example config
+ is directly used, it won't open gaping holes in the
+ system.
+ 6) Bug Fix: Server dies improperly on startup if shared memory isn't
+ initalized
+ 7) Bug Fix: Commented out error message about shadow passwords not
+ working as root. Change 1 should produce a log entry if
+ the user tries to use shadow passwords without root
+ access.
+ 8) Documentation: Created a new set of examples, that are more secure,
+ and better for creating a full configuration.
+ 9) Bug Fix: Updated socket.c, now if the server fails binding data
+ connections for any reason, it lets the computer choose
+ the port.
+
+ Version 1.1.beta1: Thanks to Mike Javorski <address@hidden> for the
+ first 3 fixes.
+
+ 1) Bug Fix: Removed SO_SNDLOWAT and SO_RCVLOWAT log messages because
+ they are unimportant and seem to be annoying people :)
+ The feature is still there, it will just fail quietly on
+ systems that have problems with it.
+ 2) Bug Fix: Manual page installation fixed (but commented out becuase
+ the manual page is yet to be written.
+ 3) Bug Fix: Fixed ftpwho.c for ANSI C complience. Now main returns
+ an int.
+ 4) Bug Fix: Defined prototypes for listing functions and found a bug
+ where they wern't supplied correct parameters.
+ 5) Bug Fix: Server now checks if you are already logged in before
+ accepting a password command.
+ 6) Bug Fix: Ops, I must have been on drugs to not have noticed this
+ bug before now (and write the broken code). SIZE in ascii
+ mode was badly broken.
+ 7) Bug Fix: SITE CHMOD was broken and logged out the client
+ 8) Bug Fix: HELP missed the first command when printing out a
+ command list.
+ 9) Bug Fix: When using runasuid/runasgid, the parent terminal holder
+ would not get killed due to the process not having
+ permission after changing uid.
+ 10) Bug Fix: When using runasuid/runasgid, and listening on ports
+ less than 1024, muddleftpd would fail to create data
+ ports because it couldn't bind to the port.
+ 11) Bug Fix: prototypes in ftpd.h for procnum.c fixed.
+ 12) Bug Fix: ftpwho.c now includes <unistd.h> as required.
+ 13) Bug Fix: fixed compiler warning compiling sglob.c on systems
+ without glob.
+ 14) Bug Fix: Prototype for strerror if the system hasn't got an
+ strerror
+ 15) Bug Fix: Fixed problems about double defining crypt
+ 16) Bug Fix: -lsocket and -lnsl should work for machines that need
+ them now.
+
+ Version 1.1.beta0:
+
+ 1) Bug Fix: forkwrapper is declared int instead of pid_t in ftpd.h
+ fixed.
+ 2) Bug Fix: On systems that don't support GLOB_PERIOD, compile will
+ fail, fixed.
+ 3) Documentation: Added some documentation for the main config file,
+ in doc/config.txt
+ 4) Bug Fix: Compile warning fixed for ftp.c
+ 5) Bug Fix: Fixed race condition in starting up program where tty
+ could hang if the parent recieved the signal to
+ give it back too soon.
+ 6) Documentation: Added some HTML documentation (just a quick
+ conversion of doc/config.txt)
+
+ Version 1.1.alpha5: Imposing a feature freeze for Version 1.1. Only bugfixes
+ and documentation from here.
+
+ 1) Change: Magic cookies when authing clients is now handled more
+ gracefully. No user side changes. This allows Change 6.
+ 2) Bug Fix: Empty listing caused memory leak. Fixed.
+ 3) Change: Server now holds the terminal until after the startup
+ messages so the prompt occurs after it.
+ 4) Change: Startup message fixed for correctness.
+ 5) Bug Fix: pids are now type pid_t, gids are now type gid_t, and
+ uids are now type uid_t in my program. They were ints
+ before!.
+ 6) Change: Now magic cookies work in dumped files (eg welcome file)
+ so you can give info out. The cookies are similar to the
+ real wu.ftpd cookies.
+ 7) Change: Added email option in config file for magic cookie %E.
+ 8) Change: Now you can bind to a port to a specific interface by
+ using port/ip as a parameter to ftpport. eg to bind
+ port 21 on the loopback device use "ftpport 21/127.0.0.1"
+ in the config file.
+
+ Version 1.1.alpha4:
+
+ 1) Change: SITE command now operates similarly to normal command. No
+ user visible changes.
+ 2) Change: Messages have changed so that the code is more general.
+ 3) Change: STAT ACCESS has been moved over the SITE ACCESS.
+ 4) Change: help routine is more generalized, giving better results,
+ less code and more maintainablity.
+ 5) Change: Now I use config.h instead of lots of compile options.
+ Thanks to Decklin Foster <address@hidden> for the
+ patch.
+ 6) Change: The pidfile is used to check if muddleftpd is still
+ running. If it is, muddleftpd refuses to start. Note, you
+ can still have multiple instances of muddleftpd if they
+ run with different config files.
+ 7) Bug Fix: config file name was not initalized properly.
+ 8) Change: Added a new user config option (quitdump) that prints a
+ file when the user quits.
+
+ Version 1.1.alpha3:
+
+ 1) Bug Fix: New parameter bug where process will segfault if it
+ cannot correctly substitue a %(a,b)h parameter.
+ 2) Change: Ftp listing is better now, it recognises the -a option
+ and displays all files. This improves interpolability
+ with misbehaving clients.
+ 3) Change: I removed the status reporting option and the code that
+ does it.
+ 4) Change: Shared memory used by muddleftpd can now be externally
+ accessed. (for things like ftpwho)
+ 5) Change: Added a simple ftpwho program that actually works
+ without races by accessing the shared memory.
+ 6) Change: The default config file is now specified in config.h
+
+ Version 1.1.alpha2:
+
+ 1) Change: Changed the status reporting so it now dumps info into a
+ file that can be read by other programs.
+ 3) Change: The admin now has the option to create a pidfile as
+ muddleftpd starts.
+ 2) Change: Changed the way parameters are processed. Now you can
+ select a range of characters to include. eg %(10,12)h
+ means to substitute characters 10 through 12 into the
+ string. The old %h still works.
+
+ Version 1.1.alpha1:
+
+ 1) Change: Added simple shadow password support
+ 2) Change: Changed the way listing works. Simpler, easier
+ 3) Change: now STAT <filename> works.
+ 4) Change: A list cannot be longer than MAXLISTSIZE
+ 5) Bug Fix: A long running LIST -n ./ bug has been fixed. It caused
+ an embarrasing infinite loop. Been in there for ages.
+ A big thanks to Richard(address@hidden) for the
+ tipoff.
+ 6) Bug Fix: Resume position should not be allowed to be negative.
+
+ Version 1.1.alpha0: * means ported back to 1.0
+
+ 1)*Bug Fix: Rename fixed again to check if RNFR was run before RNTO
+ 2) Change: The main routine now uses the select.c services.
+ 3) Change: The server can bind to many ports, and serve ftp over
+ them
+ 4)*Bug Fix: Memory leak in displaying symbolic links in listing.
+ 5) Change: Internal list function now displays setuid/setgid and
+ sticky bit. Rewrote to be much smaller.
+ 6)*Bug Fix: Fixed ENOTDIR error to becone MYERR_NODIR instead of
+ MYERR_NOFILE in file.c
+ 7)*Bug Fix: Minor changes to error descriptions in ftp.c
+ 8) Change: ~ works for going to your home directory.
+ 9) Change: Download/Upload now don't memmove buffer.
+ 10) Change: make a substitute glob using old BSD re_comp calls
+ for very old systems.
+ 11)*Bug Fix: Uid/Gid cache full causes problems.
+ 12) Change: for passive downloads, makes sure the host that connects
+ to the dataport is also the host that the control port
+ is connected to
+ 13)*Bug Fix: Obscure bug in ftplist.c fixed!
+ 14) Change: The server sets the high and low water marks for the
+ sockets on opening a data connection to improve
+ performace.
+ 15) Change: Added the STOU command!
+ 16) Change: Added the ability to type a file before the user logs in
+ 17) Change: Added the ability to type a file when the user enters a
+ directory.
+ 18) Change: The welcome file is now an absolute filename instead of
+ relative to rootdir
+ 19)*Bug Fix: Timeout didn't get updated properly when user logged on.
+ 20) Change: Added timeout to STAT command.
+ 21) Change: Added the APPE command!
+ 22) Change: Added the ALLO command. Does nothing.
+ 23) Change: Added the ACCT command. Does nothing.
+ 24)*Bug Fix: The server didn't kill children ftpd processes. Now it
+ does.
+ 25)*Bug Fix: If you didn't specify a groupname in a user file, the
+ server would crash.
+ 26) Change: Changed maxthreads directive to maxusers.
+ 27) Change: Cleaned up reading of commands.
+ 28) Change: Started to use assertions to debug code.
+ 29) Bug Fix: Server full log message not logged correctly.
+ 30) Change: select.c adjusted to work better.
+ 31) Bug Fix: server made 2 replys on logout.
+ 32) Bug FIx: server can handle lots of dataconnections now.
+ 33) Change: now too many login message is configurable per user
+ using the busydump directive.
+ 34) Change: ASCII upload resume disabled. It is not actually
+ possible to this safely. Use the APPE command instead.
+ 35) Change: Changed data collection to use shared memory rather than
+ pipes. Faster, easier to access and allows future
+ changes.
+ 36) Change: Error messages now output the filename and line the
+ error occured on.
+ 37) Change: I am starting to use assersions to test features, find
+ bugs.
+ 38) Bug Fix: Server exits if it can't write to the log file, i.e
+ disk full or other fatal error.
+ 39) Change: Passive is handled better througth the main select
+ handler.
+ 40) Change: A simple strerror replacement has been thrown in for
+ unlucky systems that don't have it.
+ 41) Bug Fix: High and low water marks are only set if the constants
+ for them exist. See 14.
+ 42) Bug Fix: --prefix parameter in configure works as expected.
+
+ Version 1.0: These fixed are ported back from version 1.1.alpha0.
+
+ 1) Bug Fix: very obscure and rare bug fixed in ftplist.c
+ 2) Bug Fix: Memory leak fixed in listing symbolic links.
+ 3) Bug Fix: Rename fixed to check if the command RNFR was
+ run first.
+ 4) Bug Fix: Fixed ENOTDIR to become MYERR_NODIR instead of
+ MYERR_NOFILE in file.c
+ 5) Bug Fix: Modified error descriptions in error.c
+ 6) Bug Fix: Fixed problems with full UID/GID caches.
+ 7) Bug FIx: Timeout wasn't updated when user logged in.
+ 8) Bug Fix: children processes are now automaticly killed when
+ you kill the parent.
+ 9) Change: Changed maxthreads to maxusers in the config file
+ 10) Bug Fix: If you don't specify a groupname in the user config
+ file, then the server will crash.
+
+ Version 1.0.beta3:
+
+ 1) Bug Fix: Buffers in acl.c fixed. Checked the rest of the code for
+ possible buffer problems.
+ 2) Bug Fix: stats.c buffers fixed. (not really a problem)
+ 3) Bug Fix: pnums.c buffers fixed. (not really a problem)
+ 4) Bug Fix: ftplist.c buffers fixed. (not really a problem)
+ 5) Bug Fix: Rename properly fixed. For some reason it worked with
+ the bug, and that worries me a little!
+ 6) Change: reentrant.c (old name for original threaded version)
+ cleaned up a little.
+
+ Version 1.0.beta2:
+
+ 1) Bug Fix: QUIT stopped working on 1.0.beta1, now fixed.
+ 2) Bug Fix: Buffers in auth.c fixed completely.
+ 3) Bug Fix: newfile.c has a realloc bug in it. ie it used a
+ pointer to the buffer after remalloc was run, and since
+ realloc may move the data to a new location, it was
+ unstable but difficult to debug!
+ 4) Bug Fix: a couple of memory over-freeing bugs fixed.
+ 5) Change: Symbolic links listed properly.
+
+ Version 1.0.beta1:
+
+ 1) Bug Fix: unimplemented type would print response code twice.
+ 2) Bug Fix: %U wasn't recognized unless unixuser was specified.
+ 3) Bug Fix: Permanent group changes specified in config file would
+ not work.
+
+ 4) Change: FTP server now runs data transfers (almost) completely
+ non-blocking. Timeout and ABOR work properly. ASCII
+ resume works now too.
+ 5) Change: Most of the code has been rewritten to use dynamic
+ buffers, removing most problems with fixed buffer code.
+ 6) Change: cdup, pwd, and cwd all use the same code now, thus all
+ return the current directory
+ 7) Change: mkdir now uses the 257 return code.
+ 8) Change: all commands now give better error messages based on
+ the real error, not the most likely error.
+
+ Version 1.0.beta0:
+
+ 1) First Version with CHANGES file.
Index: muddleftpd/src/auth.c
diff -c /dev/null muddleftpd/src/auth.c:1.2.4.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/src/auth.c Tue Nov 4 10:41:21 2003
***************
*** 0 ****
--- 1,642 ----
+ /* auth.c Handle user authentication and setup of user options
+
+ Copyright (C) 1999 Beau Kuiper
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "ftpd.h"
+ #include "auth.h"
+
+ extern FTPCMD mainftpcmd[];
+ extern FTPCMD siteftpcmd[];
+
+ PERMINFO authtypes[] = {
+ { "unix", &unixauth_commands },
+ { "anonymous", &anonauth_commands },
+ { "internal", &internalauth_commands },
+ { "disabled", &disableauth_commands },
+ #ifdef HAVE_PAM_START
+ { "pam", &pamauth_commands },
+ #endif
+ { NULL, NULL },
+ };
+
+ /* this converts a config file string to discribe a multiline response to a
+ real string. This does not need a new string to copy it to */
+
+ void converttorealstr(char *strbuf)
+ {
+ char *pos1, *pos2;
+
+ pos1 = pos2 = strbuf;
+
+ while(*pos1 != 0)
+ {
+ if (*pos1 == '/')
+ {
+ pos1++;
+ switch(*pos1)
+ {
+ case 'n':
+ *pos2 = '\n';
+ pos2++;
+ break;
+ case 's':
+ *pos2 = ' ';
+ pos2++;
+ break;
+ case 't':
+ *pos2 = '\t';
+ pos2++;
+ break;
+ case '/':
+ *pos2 = '/';
+ pos2++;
+ break;
+ default:
+ *pos2 = '/';
+ pos2++;
+ pos1--;
+ break;
+ }
+ }
+ else
+ {
+ *pos2 = *pos1;
+ pos2++;
+ }
+ pos1++;
+ }
+ *pos2 = 0;
+ }
+
+ /* check an encrypted password against a plain text password */
+
+ int chkpassword(char *encrypass, char *password)
+ {
+ char *pass2;
+ int result = FALSE;
+
+ pass2 = crypt(password, encrypass);
+ if (strcmp(pass2, encrypass) == 0)
+ result = TRUE;
+
+ /* destroy the passwords so it cannot be seen if muddleftpd crashes! */
+ memset(password, 0, strlen(password));
+ memset(pass2, 0, strlen(pass2));
+
+ return(result);
+ }
+
+ /* Make sure the user isn't trying to exploit the nature of the ftp server */
+
+ int checkexploits(FTPSTATE *peer)
+ {
+ int count;
+ int namelen = strlen(peer->username);
+
+ if (strlen(peer->username) > MAXNAMELEN)
+ return(TRUE);
+ for(count = 0; count < namelen; count++)
+ {
+ switch ((peer->username)[count])
+ {
+ case '?':
+ case '*':
+ case '/':
+ case '[':
+ case ']':
+ case '\\':
+ case '!':
+ case ':':
+ case '^':
+ return(TRUE);
+ }
+ }
+ return(FALSE);
+ }
+
+ int authlogmsg(char *directive, char *groupname)
+ {
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("directive %s is not
correct in group %s", directive, groupname));
+ return(FALSE);
+ }
+
+ int checkabsdir(char *dir)
+ {
+ if (dir == NULL)
+ return(TRUE);
+ return(dir[0] == '/');
+ }
+
+ void clearauth(FTPSTATE *peer)
+ {
+ freeifnotnull(peer->pwd);
+ peer->pwd = NULL;
+ freeifnotnull(peer->homedir);
+ freeifnotnull(peer->basedir);
+ if (peer->passiveport) select_delfd(peer->sel, peer->passiveport);
+ peer->passiveport = 0;
+ freeifnotnull(peer->renameoldname);
+ peer->renameoldname = NULL;
+ peer->restartpos = 0;
+ peer->binary = TRUE;
+ peer->remoteport = peer->connport - 1;
+ freeifnotnull(peer->logindump);
+ freeifnotnull(peer->cwddump);
+ freeifnotnull(peer->busydump);
+ freeifnotnull(peer->quitdump);
+ freeifnotnull(peer->logindumpdata);
+ freeifnotnull(peer->cwddumpdata);
+ freeifnotnull(peer->busydumpdata);
+ freeifnotnull(peer->quitdumpdata);
+ freeifnotnull(peer->cmddisableset);
+ freeifnotnull(peer->sitedisableset);
+ peer->sitedisableset = disableset_create();
+ peer->cmddisableset = disableset_create();
+ peer->umask = peer->vserver->umask;
+ if (peer->acldata) acllist_dest(peer->acldata);
+ peer->gidt_asgid = config->gidt_nobodygid;
+ peer->uidt_asuid = config->uidt_nobodyuid;
+ peer->maxusers = peer->vserver->maxusers;
+ peer->maxtimeout = peer->vserver->timeout;
+ peer->timeout = peer->vserver->timeout;
+ peer->chmodable = FALSE;
+ peer->jailenabled = FALSE;
+ peer->droproot = FALSE;
+ peer->fakemode = -1;
+ peer->accessdevices = FALSE;
+ peer->fxpallow = FALSE;
+ peer->maxtranspd = 0;
+ freeifnotnull(peer->fakename);
+ freeifnotnull(peer->fakegroup);
+ if (peer->ratioinfo) ratio_finish(peer->ratioinfo);
+ freeifnotnull(peer->supgids);
+ }
+
+ char *mkconfrealstr(int sectionid, char *item, char *defaul)
+ {
+ char *setting;
+
+ loadstrfromconfig(config->configfile, sectionid, item, &(setting),
defaul);
+ if (setting == NULL)
+ return(NULL);
+
+ setting = strdupwrapper(setting);
+
+ converttorealstr(setting);
+ return(setting);
+
+ return(setting);
+ }
+
+ char *mktokconfstr(TOKENSET *tset, int sectionid, char *item, char *defaul)
+ {
+ char *setting;
+
+ loadstrfromconfig(config->configfile, sectionid, item, &(setting),
defaul);
+ if (setting == NULL)
+ return(NULL);
+
+ setting = strdupwrapper(setting);
+ setting = tokenset_apply(tset, setting, FALSE);
+ return(setting);
+ }
+
+ int mktokconfint(TOKENSET *tset, int sectionid, char *item, char *format,
+ char *defaultstr, int defaultint)
+ {
+ char *setting;
+ int ret;
+
+ loadstrfromconfig(config->configfile, sectionid, item, &(setting),
defaultstr);
+ if (setting == NULL)
+ return(defaultint);
+ setting = strdupwrapper(setting);
+ setting = tokenset_apply(tset, setting, FALSE);
+ if (sscanf(setting, format, &ret) != 1)
+ ret = defaultint;
+ freewrapper(setting);
+ return(ret);
+ }
+
+ void buildtokset(TOKENSET *tset, PERMSTRUCT *s, void *a)
+ {
+ gid_t *list;
+ uid_t inuid;
+ gid_t ingid;
+ int result;
+ char *str;
+
+ if (s->getuseruid)
+ {
+ inuid = s->getuseruid(a);
+ result = (int)inuid;
+ str = safe_snprintf("%d", result);
+ tokenset_settoken(tset, 'u', str);
+ }
+
+ if (s->getusergid)
+ {
+ ingid = s->getusergid(a);
+ result = (int)ingid;
+ str = safe_snprintf("%d", result);
+ tokenset_settoken(tset, 'g', str);
+ }
+
+ if (s->gethomedir)
+ tokenset_settoken(tset, 'h', strdupwrapper(s->gethomedir(a)));
+ if (s->getrootdir)
+ tokenset_settoken(tset, 'r', strdupwrapper(s->getrootdir(a)));
+ if (s->getusersupgid)
+ {
+ list = s->getusersupgid(a);
+ tokenset_settoken(tset, 'G', makegidliststr(list));
+ freewrapper(list);
+ }
+ }
+
+ void setupacls(FTPSTATE *peer, TOKENSET *tset, int section, char *funcname,
int aclfunc)
+ {
+ char *data;
+ int occur = 1;
+ int escapetoks = (aclfunc != 0);
+
+ while((data = getconfigdata(config->configfile, section, funcname,
occur)))
+ {
+ char *pos;
+
+ data = tokenset_apply(tset, strdupwrapper(data), escapetoks);
+ if ((pos = strrchr(data, ':')) != NULL)
+ {
+ /* this will temporaryly damage config data. But
+ I fix it afterwards :) */
+ *pos = 0;
+ acllist_add(peer->acldata, data, pos + 1, aclfunc);
+ }
+
+ freewrapper(data);
+
+ occur++;
+ }
+ }
+
+ int transferconfig(FTPSTATE *peer, TOKENSET *tset, int section)
+ {
+ int occur, result = TRUE;
+ char *data;
+ int intdata;
+
+ peer->timeout = mktokconfint(tset, section, "timeout", "%d", NULL,
peer->vserver->timeout);
+ peer->maxtimeout = peer->timeout;
+
+ /* get uid setting */
+ loadstrfromconfig(config->configfile, section, "uid", &(data), "%u");
+ data = strdupwrapper(data);
+ data = tokenset_apply(tset, data, FALSE);
+ if (sscanf(data, "%d", &intdata) != 1)
+ {
+ /* try for username then */
+ struct passwd *pwdent;
+ pwdent = getpwnam(data);
+ if (pwdent)
+ peer->uidt_asuid = pwdent->pw_uid;
+ else
+ peer->uidt_asuid = config->uidt_nobodyuid;
+ }
+ else
+ {
+ peer->uidt_asuid = (uid_t)intdata;
+ }
+ freewrapper(data);
+
+ /* get gid setting */
+ loadstrfromconfig(config->configfile, section, "gid", &(data), "%g");
+ data = strdupwrapper(data);
+ data = tokenset_apply(tset, data, FALSE);
+
+ if (sscanf(data, "%d", &intdata) != 1)
+ {
+ /* if it starts with a "!" mark, get gid of username */
+ if (data[0] == '!')
+ {
+ struct passwd *pwdent;
+ pwdent = getpwnam(data+1);
+ if (pwdent)
+ peer->gidt_asgid = pwdent->pw_gid;
+ else
+ peer->gidt_asgid = config->gidt_nobodygid;
+ }
+ else
+ {
+ /* try for groupname then */
+ struct group *grent;
+ grent = getgrnam(data);
+ if (grent)
+ peer->gidt_asgid = grent->gr_gid;
+ else
+ peer->gidt_asgid = config->gidt_nobodygid;
+ }
+ }
+ else
+ {
+ peer->gidt_asgid = (gid_t)intdata;
+ }
+
+ freewrapper(data);
+
+ if ((int)peer->uidt_asuid == 0)
+ peer->uidt_asuid = config->uidt_nobodyuid;
+ if ((int)peer->gidt_asgid == 0)
+ peer->gidt_asgid = config->gidt_nobodygid;
+
+ peer->homedir = mktokconfstr(tset, section, "homedir", "%h");
+ if (!checkabsdir(peer->homedir))
+ result = authlogmsg("homedir", peer->groupname);
+
+ peer->basedir = mktokconfstr(tset, section, "rootdir", "%r");
+ if (!checkabsdir(peer->basedir))
+ result = authlogmsg("rootdir", peer->groupname);
+
+
+ peer->umask = mktokconfint(tset, section, "umask", "%o", NULL,
peer->vserver->umask) & 0777;
+ peer->chmodable = mktokconfint(tset, section, "chmoding", "%d", NULL,
0);
+ peer->jailenabled = mktokconfint(tset, section, "userjail", "%d", NULL,
0);
+ peer->maxusers = mktokconfint(tset, section, "maxusers", "%d", NULL,
config->defaults->maxusers);
+ peer->maxtranspd = mktokconfint(tset, section, "maxspeed", "%d", NULL,
0);
+ peer->maxtranspd_down = mktokconfint(tset, section, "maxspeeddown",
"%d", NULL, 0);
+ peer->maxtranspd_up = mktokconfint(tset, section, "maxspeedup", "%d",
NULL, 0);
+ peer->chroot = mktokconfint(tset, section, "chroot", "%d", NULL, FALSE);
+ peer->droproot = mktokconfint(tset, section, "droproot", "%d", NULL,
FALSE);
+
+ peer->nicevalue = mktokconfint(tset, section, "nice", "%d", NULL, 0);
+ peer->accessdevices = mktokconfint(tset, section, "devaccess", "%d",
NULL, FALSE);
+ peer->realdir = mktokconfint(tset, section, "realdir", "%d", NULL,
FALSE);
+ peer->fxpallow = mktokconfint(tset, section, "fxpallow", "%d", NULL,
FALSE);
+
+ peer->fakemode = mktokconfint(tset, section, "fakemode", "%o", NULL,
-1);
+ peer->fakename = mktokconfstr(tset, section, "fakename", NULL);
+ peer->fakegroup = mktokconfstr(tset, section, "fakegroup", NULL);
+
+ peer->cwddumpdata = mkconfrealstr(section, "cddumpdata", NULL);
+ peer->logindumpdata = mkconfrealstr(section, "welcomedumpdata", NULL);
+ peer->quitdumpdata = mkconfrealstr(section, "quitdumpdata", NULL);
+ peer->busydumpdata = mkconfrealstr(section, "busydumpdata", NULL);
+
+ if (!peer->cwddumpdata)
+ peer->cwddump = mktokconfstr(tset, section, "cddump", NULL);
+
+ if (!peer->logindumpdata)
+ {
+ peer->logindump = mktokconfstr(tset, section, "welcome", NULL);
+ if (!checkabsdir(peer->logindump))
+ result = authlogmsg("welcome", peer->groupname);
+ }
+
+ if (!peer->quitdumpdata)
+ {
+ peer->quitdump = mktokconfstr(tset, section, "quitdump", NULL);
+ if (!checkabsdir(peer->quitdump))
+ result = authlogmsg("quitdump", peer->groupname);
+ }
+
+ if (!peer->busydumpdata)
+ {
+ peer->busydump = mktokconfstr(tset, section, "busydump", NULL);
+ if (!checkabsdir(peer->busydump))
+ result = authlogmsg("busydump", peer->groupname);
+ }
+
+ peer->acldata = acllist_create();
+
+ setupacls(peer, tset, section, "fnaccess", 1);
+ setupacls(peer, tset, section, "pfnaccess", 2);
+ setupacls(peer, tset, section, "access", 0);
+
+ occur = 1;
+ while((data = getconfigdata(config->configfile, section, "cmdoff",
occur++)))
+ disableset_disablecmd(peer->cmddisableset, mainftpcmd, data);
+ occur = 1;
+ while((data = getconfigdata(config->configfile, section, "sitecmdoff",
occur++)))
+ disableset_disablecmd(peer->sitedisableset, siteftpcmd, data);
+
+ if (mktokconfint(tset, section, "ratios", "%d", NULL, FALSE))
+ peer->ratioinfo = ratio_loaduser(peer->username, section);
+ else
+ peer->ratioinfo = NULL;
+
+ data = mktokconfstr(tset, section, "supgid", "%G");
+ peer->supgids = parsegidlist(data);
+ freewrapper(data);
+
+ return(result);
+ }
+
+ int auth_getcursectionid(FTPSTATE *peer)
+ {
+ return(getsectionid(config->configfile, peer->groupname));
+ }
+
+ void *auth_getconfigcache(void)
+ {
+ return(config->configfile);
+ }
+
+ char *auth_getremotename(FTPSTATE *peer)
+ {
+ return(peer->hostname);
+ }
+
+ unsigned int *auth_getremoteip(FTPSTATE *peer)
+ {
+ return(&(peer->remoteip));
+ }
+
+
+ PERMSTRUCT *configauthmethod(char *group, char *authmethod)
+ {
+ int count = 0;
+ static PERMSTRUCT dp;
+
+ #ifdef HAVE_DLOPEN
+ if (authmethod[0] == '/')
+ {
+ /* assume it is a libary module */
+ #ifndef RTLD_NOW
+ dp.handle = dlopen(authmethod, 1);
+ #else
+ dp.handle = dlopen(authmethod, RTLD_NOW);
+ #endif
+ if (dp.handle == NULL)
+ {
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("could
not open or link '%s', reason: %s", authmethod, dlerror()));
+ return(NULL);
+ }
+ dp.gethandle = dlsym(dp.handle, "gethandle");
+ dp.freehandle = dlsym(dp.handle, "freehandle");
+ dp.chkpasswd = dlsym(dp.handle, "chkpasswd");
+ dp.gethomedir = dlsym(dp.handle, "gethomedir");
+ dp.getrootdir = dlsym(dp.handle, "getrootdir");
+ dp.getuseruid = dlsym(dp.handle, "getuseruid");
+ dp.getusergid = dlsym(dp.handle, "getusergid");
+ dp.getusersupgid = dlsym(dp.handle, "getusersupgid");
+
+ /* make sure the required functions exist and are defined. */
+ if (!dp.gethandle || !dp.freehandle || !dp.chkpasswd)
+ {
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("linked
module '%s' incomplete", authmethod));
+ dlclose(dp.handle);
+ return(NULL);
+ }
+ return(&dp);
+ }
+ #endif
+ while(authtypes[count].authname != NULL)
+ {
+ if (strcasecmp(authmethod, authtypes[count].authname) == 0)
+ return(authtypes[count].authstruct);
+ count++;
+ }
+
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("authmethod '%s' does not
exist, used by group %s", authmethod, group));
+ return(NULL);
+ }
+
+ /* this finds the section the user belongs to */
+
+ char *auth_getgroup(FTPSTATE *peer, TOKENSET *tset, int *section, PERMSTRUCT
**rprog, void **rinf)
+ {
+ int count = 0;
+ int sectionid, result;
+ char *mode, *authuser;
+ char **grouplist = peer->vserver->grouplist;
+ PERMSTRUCT *am = NULL;
+ void *handle = NULL;
+
+ while(grouplist[count] != NULL)
+ {
+ sectionid = getsectionid(config->configfile, grouplist[count]);
+ if (sectionid == -1)
+ {
+ /* stop authenticating if error occurs */
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("group %s
does not exist", grouplist[count]));
+ return(NULL);
+ }
+ else
+ {
+ authuser = mktokconfstr(tset, sectionid, "authuser",
peer->username);
+ mode = getconfigdata(config->configfile, sectionid,
"authmethod", 1);
+ if (mode)
+ am = configauthmethod(grouplist[count], mode);
+ if (am)
+ {
+ /* Check ip */
+ IPACLLIST *clist;
+
+ clist = ipacllist_new(config->configfile,
sectionid, "ipacl", 'A', FALSE);
+ if (!ipacllist_query(clist, peer->remoteip,
peer->hostname))
+ am = NULL;
+ ipacllist_destroy(clist);
+ }
+ else
+ return(NULL);
+ if (am)
+ /* Check username */
+ if (!checknamelist(config->configfile,
sectionid, peer->username))
+ am = NULL;
+ if (am)
+ {
+ /* now see if valid user */
+ peer->groupname = grouplist[count];
+ handle = am->gethandle(peer, tset, authuser,
&result);
+ /* if the authentication module returns ERROR,
return now! */
+ if (result == AUTH_ERROR)
+ {
+ freewrapper(authuser);
+ return(NULL);
+ }
+ }
+
+ if (handle)
+ {
+ *section = sectionid;
+ *rprog = (void *)am;
+ *rinf = handle;
+ freewrapper(authuser);
+ return(grouplist[count]);
+ }
+ freewrapper(authuser);
+ }
+ count++;
+ }
+ return(NULL);
+ }
+
+ char *setuseropts(FTPSTATE *peer, char *password)
+ {
+ int section;
+ void *authhandle = NULL;
+ char *errstr = NULL;
+ PERMSTRUCT *authcmd;
+ TOKENSET *tset = tokenset_new();
+
+ /* Check possible exploits here! */
+ if (checkexploits(peer))
+ goto authend;
+
+ peer->loggedin = FALSE;
+ tokenset_settoken(tset, 'U', strdupwrapper(peer->username));
+ tokenset_settoken(tset, 'v', strdupwrapper(peer->vserver->sectionname));
+ tokenset_settoken(tset, 'V', strdupwrapper(peer->vserver->vhostname));
+
+ peer->groupname = auth_getgroup(peer, tset, §ion, &authcmd,
&authhandle);
+
+ if (peer->groupname == NULL)
+ goto authend;
+
+ if (!authcmd->chkpasswd(authhandle, password, &errstr))
+ goto authend;
+
+ clearauth(peer);
+ buildtokset(tset, authcmd, authhandle);
+
+ if (!transferconfig(peer, tset, section))
+ goto authend;
+
+ peer->loggedin = TRUE;
+
+ authend:
+ tokenset_finish(tset);
+ if (authhandle)
+ {
+ authcmd->freehandle(authhandle);
+ #ifdef HAVE_DLOPEN
+ if (authcmd->handle)
+ dlclose(authcmd->handle);
+ #endif
+ }
+
+ if (peer->loggedin)
+ {
+ freeifnotnull(errstr);
+ return(NULL);
+ }
+ else
+ {
+ if (!errstr)
+ errstr = strdupwrapper("Bad password");
+ return(errstr);
+ }
+ }
Index: muddleftpd/src/cfloader.c
diff -c /dev/null muddleftpd/src/cfloader.c:1.1.12.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/src/cfloader.c Tue Nov 4 10:41:22 2003
***************
*** 0 ****
--- 1,629 ----
+ /* cfloader.c Configuration loader
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "ftpd.h"
+ #include "reply.h"
+
+ VSERVER serverdefaults =
+ {
+ NULL,
+ MAXUSERS,
+ LOGSTRENGTH,
+ TIMEOUT,
+ LOGFILE,
+ EMAIL,
+ LOGINTRIES,
+ BADAUTHWAIT,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ IPACL nat_locallist[] =
+ {
+ /* 127.0.0.0 Local interface */
+ { 0x7F000000, 0xFF000000, NULL, 2, TRUE },
+ /* 192.168.0.0/16 Private address space */
+ { 0xC0A80000, 0xFFFF0000, NULL, 2, TRUE },
+ /* 10.0.0.0/8 Private address space */
+ { 0x0A000000, 0xFF000000, NULL, 2, TRUE },
+ /* 172.16.0.0/12 Private address space */
+ { 0xAC100000, 0xFFF00000, NULL, 2, TRUE },
+ };
+
+ IPACLLIST nat_localdefault =
+ {
+ 4, /* count */
+ 0, /* defualt is notlocal */
+ nat_locallist
+ };
+
+ char *gethostname2(void)
+ {
+ char *hostname;
+ int size = 32;
+ struct hostent *h;
+
+ hostname = mallocwrapper(size);
+ while(gethostname(hostname, size-1) == -1)
+ {
+ size *= 2;
+ reallocwrapper(size, (void **)&hostname);
+ }
+
+ h = gethostbyname(hostname);
+ freewrapper(hostname);
+ if (!h)
+ return(NULL);
+ hostname = strdupwrapper(h->h_name);
+
+ return(hostname);
+ }
+
+ /* generates a busy string from config file data */
+
+ char *makebusystring(char *input, int alt)
+ {
+ char *r, *n;
+
+ r = mallocwrapper(strlen(input) + ((strchrcount(input, '/') + 1) * 6)
+ + strlen(REPLY_SERVERBUSY) + 2);
+
+ strcpy(r, input);
+
+ /* do / translation */
+ converttorealstr(r);
+
+ /* insert inital 421 */
+ memmove(r + 4, r, strlen(r) + 1);
+ memcpy(r, "421-", 4);
+
+ /* insert further 421 for each line */
+ n = r;
+ while((n = strchr(n, '\n')) != NULL)
+ {
+ int len = strlen(n);
+ memmove(n + 5, n, len + 1);
+ if(alt)
+ memcpy(n, "\r\n421-", 6);
+ else
+ memcpy(n, "\r\n ", 6);
+ n = n + 2;
+ }
+
+ /* insert server message */
+ strcpy(r + strlen(r), "\r\n");
+ strcpy(r + strlen(r), REPLY_SERVERBUSY);
+
+ return(r);
+ }
+
+ void configerror(char *str)
+ {
+ switch(logerrors)
+ {
+ case SYSLOG:
+ syslog(LOG_ERR, PROGNAME":%s", str);
+ break;
+ case TERMINAL:
+ fprintf(stderr, "CONFIG: %s\n", str);
+ break;
+ case MUDLOG:
+ log_addentry(MYLOG_INFO, NULL, str);
+ }
+ freewrapper(str);
+ }
+
+ void vserver_kill(VSERVER *c)
+ {
+ if (c->ipaccess)
+ ipacllist_destroy(c->ipaccess);
+ freeifnotnull(c->prelogindumpdata);
+ freeifnotnull(c->grouplist);
+ freeifnotnull(c->toobusy);
+ freewrapper(c);
+ }
+
+ VSERVER *vserver_load(CONFIGDATA *cf, char *sectionname, VSERVER *def,
VSERVERCONN ***vp)
+ {
+ int section, occur;
+ char *setting;
+ VSERVER *newvs = mallocwrapper(sizeof(VSERVER));
+ VSERVER *dvs = def;
+
+ if (!dvs)
+ dvs = &serverdefaults;
+ newvs->grouplist = NULL;
+ newvs->ipaccess = NULL;
+ newvs->sectionname = sectionname;
+
+ section = getsectionid(cf->configfile, sectionname);
+ if (section == -1)
+ {
+ configerror(safe_snprintf("Cannot get %s section in config
file!", sectionname));
+ vserver_kill(newvs);
+ return(NULL);
+ }
+
+ loadintfromconfig(cf->configfile, section, "maxusers",
+ &(newvs->maxusers), dvs->maxusers);
+ loadintfromconfig(cf->configfile, section, "logstrength",
+ &(newvs->loglevel), dvs->loglevel);
+ loadintfromconfig(cf->configfile, section, "logintries",
+ &(newvs->logincount), dvs->logincount);
+ loadintfromconfig(cf->configfile, section, "timeout",
+ &(newvs->timeout), dvs->timeout);
+ loadintfromconfig(cf->configfile, section, "umask",
+ &(newvs->umask), dvs->umask);
+ loadintfromconfig(cf->configfile, section, "maxconnectperip",
+ &(newvs->maxperip), dvs->maxperip);
+
+ if (newvs->logincount == 0)
+ newvs->logincount = -1;
+ loadintfromconfig(cf->configfile, section, "badauthwait",
+ &(newvs->authwait), dvs->authwait / 1000);
+ newvs->authwait *= 1000;
+
+ loadstrfromconfig(cf->configfile, section, "logfile",
+ &(newvs->logfile), dvs->logfile);
+ loadstrfromconfig(cf->configfile, section, "busydumpdata",
+ &setting, NULL);
+ if (setting)
+ newvs->toobusy = makebusystring(setting, cf->altlongreplies);
+ else if (dvs->toobusy)
+ newvs->toobusy = strdupwrapper(dvs->toobusy);
+ else
+ newvs->toobusy = NULL;
+
+ loadstrfromconfig(cf->configfile, section, "email",
+ &(newvs->email), dvs->email);
+ loadstrfromconfig(cf->configfile, section, "greeting",
+ &(newvs->greetline), dvs->greetline);
+ loadstrfromconfig(cf->configfile, section, "hostname",
+ &(newvs->vhostname), dvs->vhostname);
+ if (newvs->vhostname == NULL)
+ newvs->vhostname = cf->hostname;
+ loadstrfromconfig(cf->configfile, section, "logindump",
+ &(newvs->prelogindump), dvs->prelogindump);
+
+ loadstrfromconfig(cf->configfile, section, "logindumpdata",
+ &(newvs->prelogindumpdata), dvs->prelogindumpdata);
+
+ /* if prelogindumpdata is there, allocate it by itself and then
+ convert it to a displayable string */
+ if (newvs->prelogindumpdata)
+ {
+ newvs->prelogindumpdata =
strdupwrapper(newvs->prelogindumpdata);
+ converttorealstr(newvs->prelogindumpdata);
+ }
+ newvs->grouplist = makeconfiglist(cf->configfile, sectionname, "group");
+ newvs->ipaccess = ipacllist_new(cf->configfile, section, "ipacl", 'A',
FALSE);
+
+ if (vp == NULL)
+ return(newvs);
+
+ occur = 1;
+ while((setting = getconfigdata(cf->configfile, section, "ftpport",
occur)) != NULL)
+ {
+ char *bindip = strchr(setting, '/');
+ **vp = mallocwrapper(sizeof(VSERVERCONN));
+
+ if (bindip == NULL)
+ getnetworkint("0.0.0.0", &((**vp)->ip));
+ else
+ {
+ *bindip = 0;
+ getnetworkint(++bindip, &((**vp)->ip));
+ }
+
+ sscanf(setting, "%d", &((**vp)->port));
+ (**vp)->fd = 0;
+ (**vp)->vptr = newvs;
+ *vp = &((**vp)->next);
+ occur++;
+ }
+
+ return(newvs);
+ }
+
+ void ftpd_killconfig(CONFIGDATA *dc)
+ {
+ if (dc->configfile)
+ freeconfigcache(dc->configfile);
+ freeifnotnull(dc->vserverlist);
+ freeifnotnull(dc->hostname);
+ if (dc->vservers)
+ {
+ VSERVER *c = dc->vservers;
+ while(c != NULL)
+ {
+ VSERVER *d = c->next;
+ vserver_kill(c);
+
+ c = d;
+ }
+ }
+ if (dc->inports)
+ {
+ VSERVERCONN *c = dc->inports;
+ while (c != NULL)
+ {
+ VSERVERCONN *d = c->next;
+ freewrapper(c);
+ c = d;
+ }
+ }
+ if (dc->defaults)
+ vserver_kill(dc->defaults);
+ if (dc->nat_localips)
+ if (dc->nat_localips != &nat_localdefault)
+ ipacllist_destroy(dc->nat_localips);
+ freewrapper(dc);
+ }
+
+ /* this loads the configuration into a new configdata structure. Checking does
+ not need to be done at this point. Do not mess with the current config
+ because this can be called due to a signal while the FTP server is live
+ */
+
+ CONFIGDATA *ftpd_loadconfig(char *inidata, int as_inetd, int use_umask)
+ {
+ CONFIGDATA *newconfig = mallocwrapper(sizeof(CONFIGDATA));
+ int section, occur, line, error;
+ struct passwd *userinfo;
+ char *setting;
+ VSERVERCONN **vscpos;
+ VSERVER **vspos, *vpos;
+
+ newconfig->configfile = NULL;
+ newconfig->vserverlist = NULL;
+ newconfig->vservers = NULL;
+ newconfig->inports = NULL;
+
+ newconfig->inetd = as_inetd;
+ newconfig->parentpid = getpid();
+ newconfig->defaults = NULL;
+ newconfig->defaulthost = 0;
+ newconfig->nat_localips = NULL;
+
+ userinfo = getpwnam("nobody");
+ if (userinfo == NULL)
+ {
+ ftpd_killconfig(newconfig);
+ configerror(strdupwrapper("Cannot find uid/gid for user
nobody!"));
+ return(NULL);
+ }
+
+ newconfig->hostname = gethostname2();
+ if (!(newconfig->hostname))
+ {
+ ftpd_killconfig(newconfig);
+ configerror(strdupwrapper("Could not resolve hostname for local
machine."));
+ return(NULL);
+ }
+
+ newconfig->gidt_nobodygid = userinfo->pw_gid;
+ newconfig->uidt_nobodyuid = userinfo->pw_uid;
+
+ newconfig->configfile = loadconfigcache(inidata, &line, &error);
+
+ if (!(newconfig->configfile))
+ {
+ configerror(safe_snprintf("Error on line %d, %s", line,
config_errorstr(error)));
+ configerror(safe_snprintf("Cannot open config file %s",
inidata));
+ ftpd_killconfig(newconfig);
+ return(NULL);
+ }
+
+ section = getsectionid(newconfig->configfile, "main");
+ if (section == -1)
+ {
+ ftpd_killconfig(newconfig);
+ configerror(strdupwrapper("Cannot get main section in config
file!"));
+ return(NULL);
+ }
+
+ loadintfromconfig(newconfig->configfile, section, "altlongreplies",
+ &(newconfig->altlongreplies), ALTLONGREPLIES);
+ loadintfromconfig(newconfig->configfile, section, "smartbind",
+ &(newconfig->smartbind), SMARTBIND);
+ loadintfromconfig(newconfig->configfile, section, "zerobind",
+ &(newconfig->zerobind), ZEROBIND);
+ loadintfromconfig(newconfig->configfile, section, "vserverhost",
+ &(newconfig->hostvservers), 0);
+ loadintfromconfig(newconfig->configfile, section, "rdnstimeout",
+ &(newconfig->dnstimeout), RDNSTIMEOUT);
+ if (newconfig->dnstimeout == 0)
+ newconfig->dnstimeout = -1;
+
+ if (!(setting = getconfigdata(newconfig->configfile, section,
"runasuser", 1)))
+ {
+ newconfig->gidt_asgid = getgid();
+ newconfig->uidt_asuid = getuid();
+ newconfig->username = NULL;
+ }
+ else
+ {
+ userinfo = getpwnam(setting);
+ if (userinfo == NULL)
+ {
+ configerror(safe_snprintf("runasuser: username '%s'
doesn't exist!", setting));
+ ftpd_killconfig(newconfig);
+ return(NULL);
+ }
+ newconfig->gidt_asgid = userinfo->pw_gid;
+ newconfig->uidt_asuid = userinfo->pw_uid;
+ newconfig->username = setting;
+ }
+
+ vscpos = &(newconfig->inports);
+ newconfig->vserverlist = makeconfiglist(newconfig->configfile, "main",
"vserver");
+ if (newconfig->vserverlist[0] == NULL)
+ {
+ /* we don't have vservers, so we create one vserver
+ using the main section. This has the major advantage
+ of not needing lots of code for non-vserver setups */
+ newconfig->defaults = vserver_load(newconfig, "main", NULL,
&(vscpos));
+ newconfig->defaults->umask = use_umask;
+ newconfig->vservers = NULL;
+ }
+ else
+ {
+ if (newconfig->hostvservers)
+ newconfig->defaults = vserver_load(newconfig, "main",
NULL, &(vscpos));
+ else
+ newconfig->defaults = vserver_load(newconfig, "main",
NULL, NULL);
+ newconfig->defaults->umask = use_umask;
+ occur = 0;
+ vspos = &(newconfig->vservers);
+ while(newconfig->vserverlist[occur] != NULL)
+ {
+ if (strlen(newconfig->vserverlist[occur]) >=
MAXSECTIONLEN)
+ {
+ configerror(safe_snprintf("vserver '%s', name
too long. Must be less than %d characters long.",
newconfig->vserverlist[occur], MAXSECTIONLEN));
+ ftpd_killconfig(newconfig);
+ return(NULL);
+ }
+ *vspos = vserver_load(newconfig,
newconfig->vserverlist[occur], newconfig->defaults, &(vscpos));
+ if (*vspos == NULL)
+ {
+ ftpd_killconfig(newconfig);
+ return(NULL);
+ }
+ vspos = &((*vspos)->next);
+ occur++;
+ }
+ *vspos = NULL;
+ }
+
+ *vscpos = NULL;
+ newconfig->rootmode = ((int)newconfig->uidt_asuid == 0);
+
+ loadstrfromconfig(newconfig->configfile, section, "vserverdefault",
+ &setting, NULL);
+ if ((setting) && (newconfig->vservers) && (newconfig->hostvservers))
+ {
+ vpos = newconfig->vservers;
+ while((vpos != NULL) && (strcmp(vpos->sectionname, setting) !=
0))
+ vpos = vpos->next;
+
+ if (vpos == NULL)
+ {
+ configerror(safe_snprintf("vserverdefault section '%s'
is not defined.", setting));
+ ftpd_killconfig(newconfig);
+ return(NULL);
+ }
+ newconfig->defaulthost = vpos;
+ }
+
+ /* process pasvrange */
+
+ if (!(setting = getconfigdata(newconfig->configfile, section,
"pasvrange", 1)))
+ {
+ newconfig->pasvport_first = 0;
+ newconfig->pasvport_last = 0;
+ }
+ else
+ {
+ char *rsetting = strdupwrapper(setting);
+ char a;
+
+ strtrimspace(rsetting);
+ if (sscanf(rsetting, "%u-%u%c", &(newconfig->pasvport_first),
&(newconfig->pasvport_last), &a) != 2)
+ {
+ freewrapper(rsetting);
+ configerror(strdupwrapper("pasvrange requires parameter
in the form of x-y (eg 1500-2000)"));
+ ftpd_killconfig(newconfig);
+ return(NULL);
+ }
+ }
+
+ /* process natip */
+
+ if (!(setting = getconfigdata(newconfig->configfile, section, "natip",
1)))
+ {
+ newconfig->natip = 0;
+ }
+ else
+ {
+ if (getnetworkint(setting, &(newconfig->natip)) == -1)
+ {
+ configerror(safe_snprintf("natip '%s' does not resolve
to an IP address", setting));
+ ftpd_killconfig(newconfig);
+ return(NULL);
+ }
+ }
+
+ /* process nat_netclass */
+
+ if (newconfig->natip != 0)
+ {
+ newconfig->nat_localips = ipacllist_new(newconfig->configfile,
section, "nat_netclass", 'L', FALSE);
+ if (newconfig->nat_localips->count == 0)
+ {
+ ipacllist_destroy(newconfig->nat_localips);
+ newconfig->nat_localips = &nat_localdefault;
+ }
+ }
+
+ return(newconfig);
+ }
+
+ int ftpd_checkvserver(CONFIGDATA *cdat, VSERVER *vs)
+ {
+ int result = TRUE;
+ int count = 0;
+
+ if (vs->maxusers <= 0)
+ {
+ configerror(safe_snprintf("section '%s': must has maxusers more
than zero.", vs->sectionname));
+ result = FALSE;
+ }
+ if ((vs->loglevel > 127) || (vs->loglevel < 0))
+ {
+ configerror(safe_snprintf("section '%s': Logstrength must be
between 0 and 127", vs->sectionname));
+ result = FALSE;
+ }
+ if (vs->logfile)
+ if (vs->logfile[0] != '/')
+ {
+ configerror(safe_snprintf("section '%s': logfile is not
an absolute filename", vs->sectionname));
+ result = FALSE;
+ }
+
+ if (vs->prelogindump)
+ if (vs->prelogindump[0] != '/')
+ {
+ configerror(safe_snprintf("section '%s': logindump is
not an absolute filename.", vs->sectionname));
+ result = FALSE;
+ }
+
+ if ((vs->logincount == 0) || (vs->logincount < -1))
+ {
+ configerror(safe_snprintf("section '%s': logintries must be
more than 0 or set to -1.", vs->sectionname));
+ result = FALSE;
+ }
+
+ if (vs->authwait < 0)
+ {
+ configerror(safe_snprintf("section '%s': badauthwait must be 0
or more milliseconds.", vs->sectionname));
+ result = FALSE;
+ }
+
+ while(vs->grouplist[count] != NULL)
+ {
+ if (strlen(vs->grouplist[count]) >= MAXSECTIONLEN)
+ {
+ configerror(safe_snprintf("section '%s': group '%s',
name too long. Must be less than %d characters long", vs->sectionname,
vs->grouplist[count], MAXSECTIONLEN));
+ result = FALSE;
+ }
+ else if (getsectionid(cdat->configfile, vs->grouplist[count])
== -1)
+ {
+ configerror(safe_snprintf("section '%s': group '%s'
does not have a section in the config file.", vs->sectionname,
vs->grouplist[count]));
+ result = FALSE;
+ }
+ count++;
+ }
+
+ return(result);
+ }
+
+ int ftpd_checkconfig(CONFIGDATA *cdat)
+ {
+ int result = TRUE;
+ VSERVERCONN *vsc, *vsc2;
+ VSERVER *vs;
+
+ if (cdat->dnstimeout < -1)
+ {
+ result = FALSE;
+ configerror(strdupwrapper("dnstimeout must be zero or more
seconds"));
+ }
+ /* search for duplicate binds! */
+
+ vsc = cdat->inports;
+ if (vsc == NULL)
+ {
+ result = FALSE;
+ configerror(strdupwrapper("there are no ports to bind to."));
+ }
+
+ while ((vsc != NULL) && result)
+ {
+ vsc2 = vsc->next;
+ if ((vsc->port <= 0) || (vsc->port > 65535))
+ {
+ result = FALSE;
+ configerror(strdupwrapper("port to bind is not valid"));
+ }
+
+ while ((vsc2 != NULL) && result)
+ {
+ if ((vsc2->port) == (vsc->port))
+ if ((vsc2->ip == 0) ||
+ (vsc2->ip == vsc->ip))
+ {
+ result = FALSE;
+ configerror(strdupwrapper("Overlapping
port binds found!"));
+ }
+ vsc2 = vsc2->next;
+ }
+ vsc = vsc->next;
+ }
+
+ /* now check pasvrange */
+
+ if (cdat->pasvport_first || cdat->pasvport_last)
+ {
+ if ((cdat->pasvport_first < 1024) || (cdat->pasvport_last >
65535)
+ || (cdat->pasvport_first > cdat->pasvport_last))
+ {
+ result = FALSE;
+ configerror(strdupwrapper("pasvrange is not valid!"));
+ }
+ }
+
+ /* now check all the vservers */
+
+ vs = cdat->vservers;
+ while ((vs != NULL) && result)
+ {
+ result = ftpd_checkvserver(cdat, vs);
+ vs = vs->next;
+ }
+
+ if (result)
+ result = ftpd_checkvserver(cdat, cdat->defaults);
+
+ /* now check the config file, and open attempt to open it */
+
+ if (result) /* if everything is ok still */
+ {
+ cdat->logout = log_initcontext(cdat->defaults->logfile);
+ if (cdat->logout == -1)
+ {
+ result = FALSE;
+ configerror(safe_snprintf("Couldn't open logfile '%s'",
cdat->defaults->logfile));
+ }
+ }
+
+ return(result);
+ }
Index: muddleftpd/src/checkip.c
diff -c /dev/null muddleftpd/src/checkip.c:1.1.8.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/src/checkip.c Tue Nov 4 10:41:22 2003
***************
*** 0 ****
--- 1,151 ----
+ /* Copyright (C) 1999 Beau Kuiper
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "ftpd.h"
+
+ int checknamelist(CONFIGFILECACHE *cf, int section, char *username)
+ {
+ int occur;
+ char *setting;
+
+ occur = 1;
+ while ((setting = getconfigdata(cf, section,
+ "nameacl", occur)))
+ {
+ char *name = strchr(setting, ':');
+
+ if (name)
+ {
+ name++;
+ if (my_fnmatch(name, username, 0) == 0)
+ return((*setting == 'A') || (*setting == 'a'));
+ }
+ occur++;
+ }
+ return(FALSE);
+ }
+
+ /* TODO: ... don't just press on if syntax is not good ... */
+
+ IPACLLIST *ipacllist_new(CONFIGFILECACHE *cf, int section, char *name, char
acceptchar, int defaultret)
+ {
+ int occur;
+ char *setting;
+ IPACLLIST *new = mallocwrapper(sizeof(IPACLLIST));
+
+ occur = 1;
+ new->count = 0;
+ new->defaultret = defaultret;
+ new->list = NULL;
+
+ while ((setting = getconfigdata(cf, section, name,
+ occur)))
+ {
+ char *settingt = strdupwrapper(setting);
+ char *netmask, *ipaddr;
+
+ strtrimspace(settingt);
+ ipaddr = strchr(settingt, ':');
+
+ if (ipaddr)
+ {
+ ipaddr++;
+ netmask = strchr(ipaddr, '/');
+ reallocwrapper(sizeof(IPACL) * (new->count + 1),
+ (void *)&(new->list));
+ new->list[new->count].accept = (*settingt ==
acceptchar) ||
+ (*settingt ==
(char)tolower((int)acceptchar));
+
+ if ((*ipaddr == '(') && (ipaddr[strlen(ipaddr)-1] ==
')'))
+ {
+ /* hostname-pattern type IPACL */
+ memmove(settingt, ipaddr + 1, strlen(ipaddr));
+ settingt[strlen(settingt)-1] = 0;
+ new->list[new->count].fnstr = settingt;
+ new->list[new->count].type = 0;
+ }
+ else if (!netmask)
+ {
+ /* IP-pattern type IPACL */
+ memmove(settingt, ipaddr, strlen(ipaddr)+1);
+ new->list[new->count].fnstr = settingt;
+ new->list[new->count].type = 1;
+ }
+ else
+ {
+ *netmask = 0;
+ netmask++;
+ getnetworkint(ipaddr,
&(new->list[new->count].ipaddr));
+ getnetworkint(netmask,
&(new->list[new->count].netmask));
+ new->list[new->count].fnstr = NULL;
+ freewrapper(settingt);
+ new->list[new->count].type = 2;
+ }
+ new->count++;
+ }
+ else
+ {
+ log_addentry(MYLOG_INFO, NULL, "Error decoding ipacl
directive, data missing ':'. Skipping entry.");
+ freewrapper(settingt);
+ }
+
+ occur++;
+ }
+ return(new);
+ }
+
+ void ipacllist_destroy(IPACLLIST *list)
+ {
+ int count;
+
+ if (list->count > 0)
+ {
+ for (count = 0; count < list->count; count++)
+ freeifnotnull(list->list[count].fnstr);
+ freewrapper(list->list);
+ }
+
+ freewrapper(list);
+ }
+
+ int ipacllist_query(IPACLLIST *list, int ip, char *hostname)
+ {
+ int pos = 0;
+ int mip, mip2;
+ char *ipstr = (char *)getipstr(ip);
+
+ for (pos = 0; pos < list->count; pos++)
+ {
+ switch(list->list[pos].type)
+ {
+ case 0:
+ if (my_fnmatch(list->list[pos].fnstr, hostname,
0) == 0)
+ return(list->list[pos].accept);
+ break;
+ case 1:
+ if (my_fnmatch(list->list[pos].fnstr, ipstr, 0)
== 0)
+ return(list->list[pos].accept);
+ break;
+ case 2:
+ mip = ip & list->list[pos].netmask;
+ mip2 = list->list[pos].ipaddr &
list->list[pos].netmask;
+ if (mip == mip2)
+ return(list->list[pos].accept);
+ break;
+ }
+ }
+ return(list->defaultret);
+ }
Index: muddleftpd/src/ftp.c
diff -c /dev/null muddleftpd/src/ftp.c:1.1.8.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/src/ftp.c Tue Nov 4 10:41:22 2003
***************
*** 0 ****
--- 1,1070 ----
+ /* Copyright (C) 1999 Beau Kuiper
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "ftpd.h"
+ #include "ftpcmd.h"
+ #include "reply.h"
+
+ extern FTPCMD mainftpcmd[];
+
+ /* This will print a NICE! error to the user */
+
+ void reporterror(FTPSTATE *peer, char *filename, int errorno)
+ {
+ ftp_write(peer, FALSE, 550, "'%s': %s", filename, strerror(errorno));
+ }
+
+ int readipstr(char *data, int *port, unsigned int *ip)
+ {
+ int a1,a2,a3,a4,a5,a6, result;
+
+ result = sscanf(data, "%d,%d,%d,%d,%d,%d",&a1, &a2, &a3, &a4, &a5, &a6);
+ if (result != 6)
+ return(FALSE);
+
+ *ip = (a1 << 24) | (a2 << 16) | (a3 << 8) | (a4);
+ *port = (a5 * 256) + a6;
+ return(TRUE);
+ }
+
+ int readeipstr(char *ip, unsigned int *outip)
+ {
+ int a1, a2, a3, a4, result;
+
+ result = sscanf(ip, "%d.%d.%d.%d", &a1, &a2, &a3, &a4);
+ if (result != 4)
+ return(FALSE);
+
+ *outip = (a1 << 24) | (a2 << 16) | (a3 << 8) | (a4);
+ return(TRUE);
+ }
+
+ int ftp_dele(FTPSTATE *peer, char *filename)
+ {
+ if (file_unlink(peer, filename) == 0)
+ ftp_write(peer, FALSE, 250, REPLY_DELETE(filename));
+ else
+ reporterror(peer, filename, errno);
+
+ return(FALSE);
+ }
+
+ int ftp_chmod(FTPSTATE *peer, char *filename, int mode)
+ {
+ if (file_chmod(peer, filename, mode) == 0)
+ ftp_write(peer, FALSE, 250, REPLY_CHMOD(filename, mode));
+ else
+ reporterror(peer, filename, errno);
+
+ return(FALSE);
+ }
+
+ int ftp_size(FTPSTATE *peer, char *filename)
+ {
+ int filefd;
+ off_t size = 0;
+ int asize;
+ struct stat statdata;
+
+ if (peer->binary)
+ {
+ filefd = file_stat(peer, filename, &statdata);
+ if (filefd == 0)
+ size = statdata.st_size;
+ }
+ else
+ {
+ char *rname;
+ size = 0;
+ filefd = file_readopen(peer, filename, &rname);
+ freewrapper(rname);
+
+ if (filefd > 0)
+ {
+ char *chin, buffer[BUFFERSIZE];
+
+ asize = read(filefd, buffer, BUFFERSIZE-1);
+ while (asize > 0)
+ {
+ buffer[asize] = 0;
+ size += asize;
+ chin = buffer;
+ while ((chin = strchr(chin, 10)) != NULL)
+ {
+ chin++;
+ size++;
+ }
+ asize = read(filefd, buffer, BUFFERSIZE-1);
+ }
+ close(filefd);
+ }
+ }
+
+ if (filefd >= 0)
+ ftp_write(peer, FALSE, 213, "%s", offt_tostr(size));
+ else
+ reporterror(peer, filename, errno);
+
+ return(FALSE);
+ }
+
+ int ftp_mdtm(FTPSTATE *peer, char *filename)
+ {
+ struct stat statdata;
+
+ if (file_stat(peer, filename, &statdata) == 0)
+ {
+ char timestr[20];
+ struct tm *resulttm = gmtime(&statdata.st_mtime);
+
+ strftime(timestr, 20, "%Y%m%d%H%M%S", resulttm);
+
+ ftp_write(peer, FALSE, 213, timestr);
+ }
+ else
+ reporterror(peer, filename, errno);
+
+ return(FALSE);
+ }
+
+ void setdumptokens(FTPSTATE *peer, TOKENSET *ts)
+ {
+ char *outstr;
+ time_t mytime = time(NULL);
+
+ outstr = ctime(&mytime);
+ outstr[strlen(outstr) - 1] = 0;
+ tokenset_settoken(ts, 'T', strdupwrapper(outstr));
+ tokenset_settoken(ts, 'U', strdupwrapper(peer->username));
+ if (peer->pwd)
+ tokenset_settoken(ts, 'C', strdupwrapper(dir_getvirtual(peer,
peer->pwd)));
+ tokenset_settoken(ts, 'E', strdupwrapper(peer->vserver->email));
+ tokenset_settoken(ts, 'M', safe_snprintf("%d", peer->maxusers));
+ if (peer->loggedin)
+ tokenset_settoken(ts, 'N', safe_snprintf("%d",
peer->usercount));
+ tokenset_settoken(ts, 'R', strdupwrapper(peer->hostname));
+ tokenset_settoken(ts, 'L', strdupwrapper(peer->vserver->vhostname));
+ tokenset_settoken(ts, 'f', safe_snprintf("%d", peer->downloadedfiles));
+ tokenset_settoken(ts, 'F', safe_snprintf("%d", peer->uploadedfiles));
+ tokenset_settoken(ts, 'b', safe_snprintf("%s",
offt_tostr(peer->downloadedfilebytes)));
+ tokenset_settoken(ts, 'B', safe_snprintf("%s",
offt_tostr(peer->uploadedfilebytes)));
+ tokenset_settoken(ts, 'I', safe_snprintf("%s",
offt_tostr(peer->listdownloadedbytes)));
+ tokenset_settoken(ts, 'i', safe_snprintf("%d", peer->listconns));
+ tokenset_settoken(ts, 'D', safe_snprintf("%s",
offt_tostr(peer->listdownloadedbytes + peer->downloadedfilebytes)));
+ tokenset_settoken(ts, 't', safe_snprintf("%s",
offt_tostr(peer->listdownloadedbytes + peer->downloadedfilebytes +
peer->uploadedfilebytes)));
+ tokenset_settoken(ts, 'c', safe_snprintf("%d", peer->listconns +
peer->downloadedfiles + peer->uploadedfiles));
+ tokenset_settoken(ts, 'd', safe_snprintf("%d", peer->listconns +
peer->downloadedfiles));
+ if (peer->ratioinfo)
+ ratio_settokens(peer->ratioinfo, ts);
+ tokenset_settoken(ts, 'v', strdupwrapper(peer->vserver->sectionname));
+ }
+
+ int ftp_dumper(FTPSTATE *peer, NEWFILE *infile, int number, char *fmessage,
int dotokens, int endtokens)
+ {
+ TOKENSET *ts = NULL;
+ char *inp, *tfmessage;
+ int first;
+
+ if (dotokens)
+ if ((infile != NULL) || (endtokens))
+ {
+ ts = tokenset_new();
+ setdumptokens(peer, ts);
+ }
+
+ if (infile != NULL)
+ {
+ first = TRUE;
+ while ((inp = nfgetcs(infile, '\n')) != NULL)
+ {
+ if (inp[strlen(inp)-1] == '\n')
+ inp[strlen(inp)-1] = 0;
+
+ if (dotokens)
+ inp = tokenset_apply(ts, inp, FALSE);
+
+ if (first || config->altlongreplies)
+ {
+ ftp_write(peer, TRUE, 0, "%d-%s", number, inp);
+ first = FALSE;
+ }
+ else
+ ftp_write(peer, TRUE, 0, " %s", inp);
+
+ freewrapper(inp);
+ }
+
+ nfclose(infile);
+ }
+
+ if (endtokens)
+ {
+ tfmessage = tokenset_apply(ts, strdupwrapper(fmessage), FALSE);
+ ftp_write(peer, FALSE, number, "%s", tfmessage);
+ freewrapper(tfmessage);
+ }
+ else
+ ftp_write(peer, FALSE, number, "%s", fmessage);
+
+ if (ts)
+ tokenset_finish(ts);
+
+ return(FALSE);
+ }
+
+ int ftp_dumpstr(FTPSTATE *peer, char *dumpstr, int number, char *fmessage,
int endtokens)
+ {
+ TOKENSET *ts = NULL;
+ char *oldinp = dumpstr;
+ char *inp = dumpstr;
+ char *datline, *tfmessage;
+ int first;
+
+ ts = tokenset_new();
+ setdumptokens(peer, ts);
+
+ first = TRUE;
+ while (oldinp != NULL)
+ {
+ inp = strchr(inp, '\n');
+ if (inp != NULL)
+ *inp = 0;
+
+ datline = strdupwrapper(oldinp);
+ if (inp != NULL)
+ {
+ *inp = '\n';
+ inp++;
+ }
+ oldinp = inp;
+ datline = tokenset_apply(ts, datline, FALSE);
+
+ if (first || config->altlongreplies)
+ {
+ ftp_write(peer, TRUE, 0, "%d-%s", number, datline);
+ first = FALSE;
+ }
+ else
+ ftp_write(peer, TRUE, 0, " %s", datline);
+ freewrapper(datline);
+
+ }
+
+ if (endtokens)
+ {
+ tfmessage = tokenset_apply(ts, strdupwrapper(fmessage), FALSE);
+ ftp_write(peer, FALSE, number, "%s", tfmessage);
+ freewrapper(tfmessage);
+ }
+ else
+ ftp_write(peer, FALSE, number, "%s", fmessage);
+
+ tokenset_finish(ts);
+ return(FALSE);
+ }
+
+ VSERVER *find_vserver_byname(char *name)
+ {
+ VSERVER *v = config->vservers;
+
+ while((v != NULL) && (strcasecmp(v->vhostname, name) != 0))
+ v = v->next;
+
+ return(v);
+ }
+
+ int host_isip(char *name)
+ {
+ while(((*name >= '0') && (*name <= '9')) || (*name == '.'))
+ name++;
+ return(*name == 0);
+ }
+
+ int ftp_host(FTPSTATE *peer, char *params)
+ {
+ VSERVER *v;
+ /* if there are no vservers, or hostname vservers are not defined,
+ return with not implemented */
+ if ((!config->vservers) || (!config->hostvservers))
+ return(ftp_write(peer, FALSE, 502, REPLY_NOHOSTS));
+
+ /* if a vserver has already been selected, return 530 */
+ if (peer->vserver != config->defaults)
+ return(ftp_write(peer, FALSE, 530, REPLY_HOSTSELECTED));
+
+ if (config->defaulthost && (host_isip(params)))
+ v = config->defaulthost;
+ else
+ v = find_vserver_byname(params);
+
+ if (!v)
+ return(ftp_write(peer, FALSE, 533,
REPLY_HOSTNOTFOUND(params)));
+
+ switch(vserver_select(peer, v))
+ {
+ case 1:
+ return(ftp_write(peer, FALSE, 533,
REPLY_HOSTMISCONF(params)));
+ case 2:
+ return(ftp_write(peer, FALSE, 533,
REPLY_HOSTNOTFOUND(params)));
+ case 3:
+ ftp_write(peer, FALSE, 421, REPLY_HOSTTOOBUSY(params));
+ return(TRUE);
+ }
+
+ ftp_write(peer, FALSE, 202, REPLY_HOSTSEL(v->vhostname));
+
+ return(3);
+ }
+
+ int ftp_rnto(FTPSTATE *peer, char *filename)
+ {
+ char *badfile;
+ char *oldname;
+
+ if (!peer->renameoldname)
+ return(ftp_write(peer, FALSE, 503, REPLY_RENAMENOSOURCE));
+
+ oldname = dir_getvirtual(peer, peer->renameoldname);
+
+ if ((badfile = file_rename(peer, oldname, filename)) == NULL)
+ ftp_write(peer, FALSE, 250, REPLY_RENAME(oldname, filename));
+ else
+ reporterror(peer, badfile, errno);
+
+ freewrapper(peer->renameoldname);
+ peer->renameoldname = NULL;
+
+ return(FALSE);
+ }
+
+ int ftp_mkd(FTPSTATE *peer, char *filename)
+ {
+ if (file_mkdir(peer, filename) == 0)
+ {
+ char *newfile = file_expand(peer, filename);
+ ftp_write(peer, FALSE, 257, REPLY_MKDIR(dir_getvirtual(peer,
newfile)));
+ freewrapper(newfile);
+ }
+ else
+ reporterror(peer, filename, errno);
+
+ return(FALSE);
+ }
+
+ int ftp_rmd(FTPSTATE *peer, char *filename)
+ {
+ if (file_rmdir(peer, filename) == 0)
+ ftp_write(peer, FALSE, 250, REPLY_RMDIR(filename));
+ else
+ reporterror(peer, filename, errno);
+
+ return(FALSE);
+ }
+
+ int ftp_cwddo(FTPSTATE *peer, char *newdir, int dump)
+ {
+ char *tmp = strdupwrapper(peer->pwd);
+
+ dir_combine(peer, &tmp, newdir);
+
+ if (!checkchdir(peer, tmp))
+ {
+ freewrapper(tmp);
+ reporterror(peer, newdir, errno);
+ return(FALSE);
+ }
+ chdir(tmp);
+
+ if (peer->realdir)
+ {
+ char *nt;
+ /* this relies on the side effect of checkchdir where
+ the server changes dir to check */
+ nt = (char *)dir_getreal(peer);
+ if (nt != NULL)
+ {
+ freewrapper(tmp);
+ tmp = nt;
+ }
+ }
+
+
+ {
+ NEWFILE *nfile = NULL;
+ char *outstr;
+ int ret = 257;
+ /* If we need to print a file, then open it */
+ /* Oh bugger, crap, and other things, I left a big
+ security hole here! :-(, now fixed */
+ if (dump)
+ ret = 250;
+ freewrapper(peer->pwd);
+ peer->pwd = tmp;
+ if ((dump) && (peer->cwddump) && (!peer->cwddumpdata))
+ {
+ if (peer->cwddump[0] == '/')
+ /* if it is an absolute file, don't worry
+ about permissions accessing file */
+ nfile = nfopen(peer->cwddump);
+ else
+ /* worry like hell and pass request via
+ both ACL's and file permissions! */
+ nfile = file_nfopen(peer, peer->cwddump);
+ }
+ outstr = safe_snprintf(REPLY_PWD(dir_getvirtual(peer,
peer->pwd)));
+
+ if ((dump) && (peer->cwddumpdata))
+ ftp_dumpstr(peer, peer->cwddumpdata, ret, outstr,
FALSE);
+ else
+ ftp_dumper(peer, nfile, ret, outstr, TRUE, FALSE);
+ freewrapper(outstr);
+ }
+
+ return(FALSE);
+ }
+
+ int ftp_cwd(FTPSTATE *peer, char *newdir)
+ {
+ return(ftp_cwddo(peer, newdir, TRUE));
+ }
+
+ int ftp_run(FTPSTATE *peer, INPUTLINE *cmd, char *token)
+ {
+ if ((cmd->command->ftpfunc) == NULL)
+ return(ftp_write(peer, FALSE, 500, REPLY_CMDNOTKNOWN(token)));
+
+ if (cmd->command->paramnum)
+ {
+ if (cmd->parameters == NULL)
+ return(ftp_write(peer, FALSE, 500,
REPLY_NOPARAM(token)));
+ else if (cmd->parameters[0] == 0)
+ return(ftp_write(peer, FALSE, 500,
REPLY_NOPARAM(token)));
+ }
+
+ if ((cmd->command->needslogin) && (peer->loggedin != TRUE))
+ return(ftp_write(peer, FALSE, 530, REPLY_NOLOGIN));
+
+ if ((!cmd->command->dataportok) && (peer->dport))
+ return(ftp_write(peer, FALSE, 520,
REPLY_DATACONNINVALID(token)));
+ else
+ return(cmd->command->ftpfunc(peer, cmd->parameters));
+ }
+
+ int ftp_quit(FTPSTATE *peer, char *param)
+ {
+ if (peer->quitdump)
+ {
+ NEWFILE *nfile = nfopen(peer->quitdump);
+ ftp_dumper(peer, nfile, 221, REPLY_QUIT, TRUE, FALSE);
+ }
+ else if (peer->quitdumpdata)
+ ftp_dumpstr(peer, peer->quitdumpdata, 221, REPLY_QUIT, FALSE);
+ else
+ ftp_write(peer, FALSE, 221, REPLY_QUIT);
+ return(TRUE);
+ }
+
+ int ftp_user(FTPSTATE *peer, char *param)
+ {
+ if (peer->jailenabled)
+ return(ftp_write(peer, FALSE, 530, REPLY_JAILUSER));
+ if (peer->loginsleft == 0)
+ return(ftp_write(peer, FALSE, 530, REPLY_NOCREDITS));
+ if (peer->loggedin)
+ shinfo_delusergroup(peer->groupname);
+
+ shinfo_changeuser(param);
+ peer->loggedin = 0;
+
+ freewrapper(peer->username);
+ peer->username = strdupwrapper(param);
+
+ return(ftp_write(peer, FALSE, 331, REPLY_USER(peer->username)));
+ }
+
+ int ftp_host_compat(FTPSTATE *peer)
+ {
+ VSERVER *v;
+ char *name;
+ /* if there are no vservers, or hostname vservers are not defined,
+ return with not implemented */
+ if ((!config->vservers) || (!config->hostvservers))
+ return(1);
+
+ /* if a vserver has already been selected, return 530 */
+ if (peer->vserver != config->defaults)
+ return(1);
+
+ name = strchr(peer->username, '%');
+
+ if (!name)
+ v = config->defaulthost;
+ else
+ {
+ *name = 0;
+ name++;
+
+ if (config->defaulthost && (host_isip(name)))
+ v = config->defaulthost;
+ else
+ v = find_vserver_byname(name);
+ }
+
+ if (!v)
+ return(0);
+
+ switch(vserver_select(peer, v))
+ {
+ case 1:
+ case 2:
+ return(0);
+ case 3:
+ return(2);
+ }
+
+ return(1);
+ }
+
+ int ftp_pass(FTPSTATE *peer, char *param)
+ {
+ int result = FALSE;
+ int loginok, oldnice = peer->nicevalue;
+ int toomany = FALSE;
+ char *errmsg = NULL;
+
+ switch(ftp_host_compat(peer))
+ {
+ case 0:
+ return(ftp_write(peer, FALSE, 530,
REPLY_LOGINFAIL(peer->username, "Bad password")));
+ case 2:
+ ftp_write(peer, FALSE, 421, REPLY_TOOMANYUSERS);
+ return(TRUE);
+ }
+
+ if (peer->loggedin)
+ return(ftp_write(peer, FALSE, 530, REPLY_ALREADYLOGGEDIN));
+
+ if (strcmp(peer->username, "<unknown>") == 0)
+ return(ftp_write(peer, FALSE, 503, REPLY_USEUSERFIRST));
+
+ loginok = (param != NULL);
+
+ if (loginok)
+ {
+ file_becomeroot(peer);
+ setgroups(0, NULL);
+ errmsg = setuseropts(peer, param);
+ loginok = (errmsg == NULL);
+ }
+
+ /* check some stuff, set basedir to real pathname */
+ if (loginok)
+ {
+ file_becomeuser(peer);
+ if (chdir(peer->basedir) == -1)
+ {
+ loginok = FALSE;
+ log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("rootdir(%s) for user '%s' is not accessable. Check rootdir and
rootdir permissions", peer->basedir, peer->username));
+ }
+ else
+ {
+ char *curdir = getcwd2();
+ if (strcmp(curdir, peer->basedir) != 0)
+ {
+ log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("rootdir changed from '%s' to '%s', symbolic links resolved for
user '%s'", peer->basedir, curdir, peer->username));
+ freewrapper(peer->basedir);
+ peer->basedir = curdir;
+ }
+ else
+ freewrapper(curdir);
+ }
+ file_becomeroot(peer);
+ }
+
+ if (loginok)
+ {
+ peer->usercount = toomany =
shinfo_addusergroup(peer->groupname, peer->maxusers);
+ toomany = (toomany == -1);
+ if (toomany)
+ loginok = FALSE;
+ }
+
+ if (loginok)
+ {
+ char *outstr;
+ NEWFILE *nfile;
+
+ log_addentry(MYLOG_LOGIN, peer, "Login successful.");
+ outstr = safe_snprintf(REPLY_PASSOK(peer->username));
+
+ /* perform chroot if needed */
+ if (peer->chroot)
+ dochroot(peer);
+
+ if (nice(peer->nicevalue + (-oldnice)) == -1)
+ {
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("nice(%d)
gave error %s", peer->nicevalue + (-oldnice), strerror(errno)));
+ peer->nicevalue = oldnice;
+ }
+
+ if (config->rootmode)
+ setgroups(peer->supgids[0], peer->supgids + 1);
+
+ /* see if rootdir == "/", change to "" */
+ if (peer->basedir[1] == 0)
+ peer->basedir[0] = 0;
+
+ if ((peer->droproot) && (config->rootmode))
+ {
+ if (giveuproot(peer->uidt_asuid, peer->gidt_asgid))
+ log_addentry(MYLOG_INFO, peer, "Failed to set
capabilities!");
+ peer->jailenabled = TRUE;
+ /* we are not root anymore and can never be root
+ again! */
+ config->rootmode = FALSE;
+ }
+
+ file_becomeuser(peer);
+
+ nfile = nfopen(peer->logindump);
+ peer->pwd = strdupwrapper(peer->basedir);
+ dir_combine(peer, &(peer->pwd), peer->homedir);
+
+ if (peer->logindumpdata)
+ result = ftp_dumpstr(peer, peer->logindumpdata, 230,
outstr, FALSE);
+ else
+ result = ftp_dumper(peer, nfile, 230, outstr, TRUE,
FALSE);
+ freewrapper(outstr);
+ }
+ else
+ {
+ peer->loggedin = FALSE;
+ log_addentry(MYLOG_LOGIN, peer, "Login failed");
+ peer->timeout = peer->vserver->timeout;
+ if (toomany)
+ {
+ NEWFILE *nfile = nfopen(peer->busydump);
+ logfullmessage(GROUPFULL, peer->remoteip);
+ if (peer->busydumpdata)
+ ftp_dumpstr(peer, peer->busydumpdata, 421,
REPLY_TOOMANYUSERS, FALSE);
+ else
+ ftp_dumper(peer, nfile, 421,
REPLY_TOOMANYUSERS, TRUE, FALSE);
+ }
+ else
+ {
+ usleep(peer->vserver->authwait);
+ if (errmsg == NULL)
+ errmsg = strdupwrapper("Bad password");
+ result = ftp_write(peer, FALSE, 530,
REPLY_LOGINFAIL(peer->username, errmsg));
+ if (peer->loginsleft > 0)
+ peer->loginsleft--;
+ freewrapper(errmsg);
+ }
+ freewrapper(peer->username);
+ peer->username = strdupwrapper("<unknown>");
+ }
+ if (toomany)
+ return(TRUE); /* quit */
+ return(3); /* make sure timeout gets updated */
+ }
+
+ int ftp_rest(FTPSTATE *peer, char *param)
+ {
+ off_t newpos;
+ int res;
+
+ res = strto_offt(param, &newpos);
+
+ if ((res != 0) || (newpos < 0))
+ return(ftp_write(peer, FALSE, 501, REPLY_INVALIDREST));
+ else
+ {
+ peer->restartpos = newpos;
+ return(ftp_write(peer, FALSE, 350,
REPLY_RESTOK(peer->restartpos)));
+ }
+ }
+
+ int ftp_syst(FTPSTATE *peer, char *param)
+ {
+ return(ftp_write(peer, FALSE, 215, "UNIX Type: L8"));
+ }
+
+ int ftp_port(FTPSTATE *peer, char *param)
+ {
+ if (peer->epsv_forced)
+ return(ftp_write(peer, FALSE, 500, REPLY_EPSVSET));
+
+ /* reset remoteport */
+ peer->remoteport = 0;
+ if (peer->passiveport)
+ {
+ select_delfd(peer->sel, peer->passiveport);
+ peer->passiveport = 0;
+ }
+
+ if (readipstr(param, &(peer->remoteport), &(peer->dataip)))
+ {
+ if ((peer->remoteport <= 1024) || (peer->remoteport >= 65536))
+ {
+ peer->remoteport = 0;
+ return(ftp_write(peer, FALSE, 500, REPLY_PORTBADPORT));
+ }
+ if ((peer->dataip != peer->remoteip) && (!peer->fxpallow))
+ {
+ peer->remoteport = 0;
+ peer->dataip = peer->remoteip;
+ return(ftp_write(peer, FALSE, 500, REPLY_PORTBADFXP));
+ }
+ return(ftp_write(peer, FALSE, 200, REPLY_PORTOK(
+ peer->dataip >> 24, peer->dataip >> 16 & 255,
peer->dataip >> 8 & 255,
+ peer->dataip & 255, peer->remoteport)));
+ }
+ else
+ return(ftp_write(peer, FALSE, 501, REPLY_PORTBADPARM));
+ }
+
+ int ftp_eprt(FTPSTATE *peer, char *param)
+ {
+ char *ipstr;
+ int proto, tcpport;
+ unsigned int remote_ip;
+
+ if (peer->epsv_forced)
+ return(ftp_write(peer, FALSE, 500, REPLY_EPSVSET));
+
+ ipstr = mallocwrapper(strlen(param) + 1);
+
+ /* clear off old ports */
+ peer->remoteport = 0;
+ if (peer->passiveport)
+ {
+ select_delfd(peer->sel, peer->passiveport);
+ peer->passiveport = 0;
+ }
+
+ if (sscanf(param, "|%d|%[0-9.]|%d|", &proto, ipstr, &tcpport) != 3)
+ ftp_write(peer, FALSE, 500, REPLY_EPRTBADPARM);
+ else if (proto != FTP_IPV4)
+ ftp_write(peer, FALSE, 522, REPLY_BADPROTO);
+ else if (!readeipstr(ipstr, &(remote_ip)))
+ ftp_write(peer, FALSE, 500, REPLY_EPRTBADPARM);
+ else if (tcpport <= 1024)
+ ftp_write(peer, FALSE, 500, REPLY_EPRTBADPORT);
+ else if ((remote_ip != peer->remoteip) && (!peer->fxpallow))
+ ftp_write(peer, FALSE, 500, REPLY_EPRTBADFXP);
+ else
+ {
+ /* everything seems to be ok */
+ peer->remoteport = tcpport;
+ peer->dataip = remote_ip;
+ ftp_write(peer, FALSE, 200, REPLY_EPRTOK(
+ peer->dataip >> 24, peer->dataip >> 16 & 255,
peer->dataip >> 8 & 255,
+ peer->dataip & 255, peer->remoteport));
+ }
+ freewrapper(ipstr);
+ return(FALSE);
+ }
+
+ int ftp_pwd(FTPSTATE *peer, char *param)
+ {
+ return(ftp_cwddo(peer, ".", FALSE));
+ }
+
+ int ftp_type(FTPSTATE *peer, char *param)
+ {
+ if ((param[0] & (255-32)) == 'A')
+ {
+ peer->binary = FALSE;
+ return(ftp_write(peer, FALSE, 200, REPLY_TYPEASCII));
+ }
+ else if ((param[0] & (255-32)) == 'I')
+ {
+ peer->binary = TRUE;
+ return(ftp_write(peer, FALSE, 200, REPLY_TYPEBINARY));
+ }
+ else
+ return(ftp_write(peer, FALSE, 504, REPLY_TYPEUNIMP));
+ }
+
+ int ftp_abor(FTPSTATE *peer, char *param)
+ {
+ /* abort any active or pending data port */
+ abortdatasocket(peer);
+ return(ftp_write(peer, FALSE, 226, REPLY_ABORT));
+ }
+
+ int ftp_passive_do(FTPSTATE *peer, int *rip)
+ {
+ int pcount, count;
+
+ if (peer->passiveport != 0)
+ select_delfd(peer->sel, peer->passiveport);
+
+ /* if a port range is specified, choose a port within it */
+ if (config->pasvport_first)
+ {
+ pcount = config->pasvport_last - config->pasvport_first + 1;
+ peer->remoteport = config->pasvport_first + (((random() &
0x00FFFF00) >> 8) % pcount);
+
+ peer->passiveport = listenparrelelport(peer->remotefd,
&(peer->remoteport), rip, 5);
+
+ count = 1;
+ // while I can't get a port, increment and try again.
+ while ((peer->passiveport == -1) && (count < pcount))
+ {
+ peer->remoteport++;
+ if (peer->remoteport > config->pasvport_last)
+ peer->remoteport = config->pasvport_first;
+ count++;
+ peer->passiveport = listenparrelelport(peer->remotefd,
&(peer->remoteport), rip, 5);
+ }
+ }
+ else
+ {
+ peer->remoteport = 0;
+ peer->passiveport = listenparrelelport(peer->remotefd,
&(peer->remoteport), rip, 5);
+ }
+
+ if ((peer->passiveport != -1) && (config->natip))
+ {
+ /* determine if we should use the IP the stack tells us or if
+ the stack is lying to us */
+
+ if (!ipacllist_query(config->nat_localips, peer->remoteip,
peer->hostname))
+ {
+ // yep, its a remote user, rewrite ip
+ *rip = config->natip;
+ }
+ }
+
+ return (peer->passiveport != -1);
+ }
+
+ int ftp_pasv(FTPSTATE *peer, char *param)
+ {
+ unsigned int a1, a2, a3, a4, a5, a6;
+
+ if (peer->epsv_forced)
+ return(ftp_write(peer, FALSE, 500, REPLY_EPSVSET));
+
+ if (!ftp_passive_do(peer, &a1))
+ {
+ peer->passiveport = 0;
+ reporterror(peer, "passive port", errno);
+ return(FALSE);
+ }
+ select_addfd(peer->sel, peer->passiveport);
+ a2 = ((a1 >> 8) & 255);
+ a3 = ((a1 >> 16) & 255);
+ a4 = ((a1 >> 24) & 255);
+ a1 = a1 & 255;
+ a5 = (peer->remoteport >> 8);
+ a6 = (peer->remoteport & 255);
+ return(ftp_write(peer, FALSE, 227, REPLY_PASV(a4, a3, a2, a1, a5, a6)));
+ }
+
+ int ftp_epsv(FTPSTATE *peer, char *param)
+ {
+ int proto, a1;
+
+ /* the all parameter means that only epsv can be used from now on */
+
+ if (peer->passiveport != 0)
+ select_delfd(peer->sel, peer->passiveport);
+
+ peer->remoteport = 0;
+ peer->passiveport = 0;
+
+ if (param)
+ {
+ if (strcasecmp(param, "ALL") == 0)
+ {
+ peer->epsv_forced = 1;
+ return(ftp_write(peer, FALSE, 200, REPLY_EPSVON));
+ }
+ else if (sscanf(param, "%d", &proto) == 1)
+ {
+ if (proto != FTP_IPV4)
+ return(ftp_write(peer, FALSE, 522,
REPLY_BADPROTO));
+ }
+ else
+ return(ftp_write(peer, FALSE, 500, REPLY_EPSVERR));
+ }
+
+ if (!ftp_passive_do(peer, &a1))
+ {
+ peer->passiveport = 0;
+ reporterror(peer, "passive port", errno);
+ return(FALSE);
+ }
+ select_addfd(peer->sel, peer->passiveport);
+
+ return(ftp_write(peer, FALSE, 229, REPLY_EPSV(peer->remoteport)));
+ }
+
+ int ftp_list(FTPSTATE *peer, char *param)
+ {
+ char *p = param;
+ int done = FALSE;
+ int parm = 0;
+ while (!done)
+ {
+ if (p == NULL)
+ done = TRUE;
+ else if ((p[0] != '-') && (p[0] != ' ') && (p[0] != 0))
+ done = TRUE;
+ else
+ {
+ parm = parm | ftplist_parseflags(p + 1);
+ p = strchr(p, ' ');
+ if (p != NULL)
+ p++;
+ }
+ }
+
+ return(ftp_lister(peer, p, FALSE, parm));
+ }
+
+ int ftp_nlst(FTPSTATE *peer, char *param)
+ {
+ char *p = param;
+ int done = FALSE;
+ int parm = 0;
+ while (!done)
+ {
+ if (p == NULL)
+ done = TRUE;
+ else if ((p[0] != '-') && (p[0] != ' ') && (p[0] != 0))
+ done = TRUE;
+ else
+ {
+ parm = parm | ftplist_parseflags(p + 1);
+ p = strchr(p, ' ');
+ if (p != NULL)
+ p++;
+ }
+ }
+
+ return(ftp_lister(peer, p, TRUE, parm));
+ }
+
+ int ftp_cdup(FTPSTATE *peer, char *param)
+ {
+ return(ftp_cwd(peer, ".."));
+ }
+
+ int ftp_rnfr(FTPSTATE *peer, char *param)
+ {
+ freeifnotnull(peer->renameoldname);
+ peer->renameoldname = file_expand(peer, param);
+ return(ftp_write(peer, FALSE, 350, REPLY_RENAMESOURCE));
+ }
+
+ int ftp_noop(FTPSTATE *peer, char *param)
+ {
+ return(ftp_write(peer, FALSE, 200, REPLY_NOOP));
+ }
+
+ int ftp_rein(FTPSTATE *peer, char *param)
+ {
+ if (peer->jailenabled)
+ return(ftp_write(peer, FALSE, 530, REPLY_JAILUSER));
+ if (peer->loggedin)
+ shinfo_delusergroup(peer->groupname);
+
+ peer->loggedin = FALSE;
+ abortdatasocket(peer);
+ return(ftp_write(peer, FALSE, 220, "Reinitialize successful, enter
username."));
+ }
+
+ int ftp_none(FTPSTATE *peer, char *param)
+ {
+ return(FALSE);
+ }
+
+ int ftp_help(FTPSTATE *peer, char *param)
+ {
+ return(ftp_dohelp(peer, mainftpcmd, param, peer->cmddisableset));
+ }
+
+ int ftp_dohelp(FTPSTATE *peer, FTPCMD *ftpcmds, char *command, int
*disableset)
+ {
+ char outstr[128];
+ char cmd[10];
+ int result = FALSE;
+ int count2,count = 0;
+
+ if (command != NULL)
+ {
+ while(((strcasecmp(ftpcmds[count].command, command) != 0) &&
+ (ftpcmds[count].ftpfunc != NULL)) ||
+ (peer->loggedin ? disableset[count] :
ftpcmds[count].needslogin))
+ count++;
+
+ if (ftpcmds[count].ftpfunc == NULL)
+ ftp_write(peer, FALSE, 502, REPLY_HELPUNKNOWN(command));
+ else
+ ftp_write(peer, FALSE, 214, "%-8s : %s",
ftpcmds[count].command, ftpcmds[count].helpdesc);
+ return(FALSE);
+ }
+
+ ftp_write(peer, TRUE, 0, REPLY_HELPSTART);
+ while (ftpcmds[count].ftpfunc != NULL)
+ {
+ count2 = 0;
+ if (config->altlongreplies)
+ strcpy(outstr, "214-");
+ else
+ strcpy(outstr, " ");
+ /* now increment past disabled commands */
+ while((peer->loggedin ? disableset[count] :
ftpcmds[count].needslogin))
+ count++;
+
+ while ((count2 < 7) && (ftpcmds[count].ftpfunc != NULL))
+ {
+ snprintf(cmd, 10, "%-9s", ftpcmds[count].command);
+ strcat(outstr, cmd);
+ count2++;
+ count++;
+ /* now increment past disabled commands */
+ while((peer->loggedin ? disableset[count] :
ftpcmds[count].needslogin))
+ count++;
+ }
+ ftp_write(peer, TRUE, 0, outstr);
+ }
+
+ result = ftp_write(peer, FALSE, 214,
REPLY_HELPEND(peer->vserver->email));
+
+ return(result);
+ }
+
+ int ftp_allo(FTPSTATE *peer, char *param)
+ {
+ return(ftp_write(peer, FALSE, 202, REPLY_ALLO));
+ }
+
+ int ftp_acct(FTPSTATE *peer, char *param)
+ {
+ return(ftp_write(peer, FALSE, 200, REPLY_ACCT));
+ }
+
+ int ftp_stru(FTPSTATE *peer, char *param)
+ {
+ if ((param[0] & (255-32)) == 'F')
+ return(ftp_write(peer, FALSE, 200, REPLY_STRUFILE));
+ else
+ return(ftp_write(peer, FALSE, 500, REPLY_STRUUNKNOWN));
+ }
Index: muddleftpd/src/ftpd.h
diff -c /dev/null muddleftpd/src/ftpd.h:1.2.4.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/src/ftpd.h Tue Nov 4 10:41:22 2003
***************
*** 0 ****
--- 1,812 ----
+ /* Copyright (C) 1999 Beau Kuiper
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ /* Includes */
+
+ #ifndef DEBUG /* If we are not debuging, disable assertions! */
+ #define NDEBUG
+ #endif
+
+ #include "../config.h" /* Insert the config header */
+ #include "../defaults.h" /* insert default info */
+
+ #include <assert.h> /* enable assertions */
+
+ #include "myglob.h" /* use our simple glob */
+ #include "util/strerror.h"
+ #include <sys/types.h>
+ #ifdef HAVE_SYS_CAPABILITY_H
+ #include <sys/capability.h>
+ #undef WNOHANG
+ #undef WUNTRACED
+ #endif
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+ #include <pwd.h>
+ #include <grp.h>
+ #include <stdarg.h>
+ #include <sys/wait.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <syslog.h>
+ #include <string.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>
+ #include <netdb.h>
+ #include <sys/socket.h>
+ #include <sys/time.h>
+ #include <sys/stat.h>
+ #include <sys/resource.h>
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <time.h>
+ #include <signal.h>
+ #include <ctype.h>
+ #include <dirent.h>
+ #include <malloc.h>
+ #include <syslog.h>
+ #include <setjmp.h>
+
+ #ifdef HAVE_DLFCN_H
+ #include <dlfcn.h>
+ #endif
+
+ #ifdef HAVE_CRYPT_H
+ #include <crypt.h>
+ #endif
+
+ #ifdef HAVE_GETSPNAM
+ #include <shadow.h>
+ #endif
+
+ #ifndef INT_MAX
+ #define INT_MAX 0x7FFFFFFF
+ #endif
+
+ #include "pnums.h"
+ #include "configfile.h"
+ #include "acl.h"
+ #include "tokset.h"
+ #include "ratio.h"
+ #include "string.h"
+
+ /* Inportant Constants */
+
+ #ifndef FALSE
+ #define FALSE 0
+ #endif
+ #ifndef TRUE
+ #define TRUE !FALSE
+ #endif
+ #define SYSLOG 1
+ #define TERMINAL 2
+ #define MUDLOG 3
+
+ #define MYLOG_DACCESS 1
+ #define MYLOG_FTRANS 2
+ #define MYLOG_COMMAND 4
+ #define MYLOG_RESPONSE 8
+ #define MYLOG_INFO 16
+ #define MYLOG_LOGIN 32
+ #define MYLOG_DEBUG 64
+
+ #define TRANS_LIST 1
+ #define TRANS_UPLOAD 2
+ #define TRANS_DOWNLOAD 3
+ #define TRANS_SUPLOAD 4
+ #define TRANS_RUNNING 5
+
+ /* used in authentication modules */
+ #define AUTH_OK 0
+ #define AUTH_USERNKNOW 1
+ #define AUTH_ERROR 2
+
+ /* used for config errors */
+
+ #define CONFIG_OK 0
+ #define CONFIG_HANDLER_ERROR 1
+ #define CONFIG_FILE_UNSAFE 2
+ #define CONFIG_FILE_ERROR 3
+
+ #define CFC_INCLUDE_ERROR 10
+ #define CFC_SECTION_NONE 11
+ #define CFC_SECTION_EXISTS 12
+ #define CFC_NO_SECTION 13
+ #define CFC_INCLUDE_LOOP 14
+
+ /* used to define maximum IP address size (for ipv6 support) */
+
+ #define MAX_IPSIZE 16
+
+ #define FTP_IPV4 1
+ #define FTP_IPV6 2
+
+ /* DO NOT CHANGE THESE DEFINES. THEY ARE REQUIRED CONSTANTS */
+
+ #define CR 13
+ #define LF 10
+
+ /* Macros */
+
+ #define MAXIMUM(x, y) ((x) > (y) ? (x) : (y))
+ #define MINIMUM(x, y) ((x) > (y) ? (y) : (x))
+ #define ERRORMSG(x) errormsg(x, __FILE__, __LINE__)
+ #define ERRORMSGFATAL(x) errormsgfatal(x, __FILE__, __LINE__)
+
+ #ifndef FNM_PATHNAME
+ #define FNM_PATHNAME 1
+ #endif
+
+ /* this specifies that the operation cannot be stopped by a signal */
+
+ #define NOSIGNALINTR(x) while(((x) == -1) && (errno == EINTR))
+
+ /* Typedefs */
+
+ typedef unsigned int ipaddr_mt[MAX_IPSIZE];
+
+ typedef struct
+ {
+ int fd;
+ STRING *buffer;
+ int eof;
+ } NEWFILE;
+
+ typedef struct strcache
+ {
+ int size;
+ struct {
+ int num;
+ char *str;
+ } data[STRCACHESIZE];
+ } STRCACHE;
+
+ struct selector;
+
+ struct selectorobj
+ {
+ int (* readsockopt)(struct selector *, int, void *);
+ int (* writesockopt)(struct selector *, int,void *);
+ void *readdata;
+ void *writedata;
+ int next; /* linked list of file descriptors */
+ int last;
+ };
+
+ typedef struct selector
+ {
+ fd_set readset;
+ fd_set writeset;
+ struct selectorobj **fdtable;
+ int firstfd;
+ int maxfds;
+ int smax;
+ } SELECTER;
+
+ typedef struct limiter
+ {
+ int maxspeed;
+ struct timeval current_time;
+ int bytes_transfered;
+ } LIMITER;
+
+ typedef struct
+ {
+ int pos;
+ MYGLOBDATA *dirdata;
+ int nlist;
+ int recursive;
+ int all;
+ STRCACHE *uidcache;
+ STRCACHE *gidcache;
+ char *dir;
+ char *rdir;
+ int odirlen;
+ int numsubdirs;
+ char **subdirs;
+ unsigned int year; /* this is stored as 4 chars */
+ } LISTHANDLE;
+
+ typedef struct dataport
+ {
+ int filefd;
+ int socketfd;
+ off_t pos;
+ off_t startpos;
+ off_t tsize;
+ STRING *buffer;
+ LISTHANDLE *lhandle;
+ int trans_type;
+ int binary;
+ int passive;
+ off_t transbytes;
+ LIMITER *download_limiter;
+ LIMITER *upload_limiter;
+ } DATAPORT;
+
+ typedef struct
+ {
+ unsigned int ipaddr;
+ unsigned int netmask;
+ char *fnstr;
+ int type;
+ int accept;
+ } IPACL;
+
+ typedef struct
+ {
+ int count;
+ int defaultret;
+ IPACL *list;
+ } IPACLLIST;
+
+ typedef struct vserver
+ {
+ IPACLLIST *ipaccess;
+ int maxusers;
+ int loglevel;
+ int timeout;
+ char *logfile;
+ char *email;
+ int logincount;
+ int authwait;
+ int umask;
+ int maxperip;
+ char *sectionname;
+ char **grouplist;
+ char *vhostname;
+ char *prelogindump;
+ char *prelogindumpdata;
+ char *greetline;
+ char *toobusy;
+ struct vserver *next;
+ } VSERVER;
+
+ typedef struct vserverconn
+ {
+ int port;
+ int ip;
+ int fd;
+ VSERVER *vptr;
+ struct vserverconn *next;
+ } VSERVERCONN;
+
+ typedef struct configdata
+ {
+ CONFIGFILECACHE *configfile;
+
+ pid_t parentpid; /* the pid to signal when an fatal error occurs */
+
+ int rootmode; /* are we in root mode or not */
+ int logout; /* log context */
+
+ uid_t uidt_asuid; /* change to this user after listening to
port */
+ gid_t gidt_asgid;
+
+ int toobusycount; /* number of connections being given too busy
+ messages by main thread */
+ char *username; /* the username muddleftpd will run as */
+ uid_t uidt_nobodyuid; /* uid for user nobody */
+ gid_t gidt_nobodygid; /* gid for user nobody */
+
+ int inetd; /* are we running as inetd */
+ int hostvservers; /* are we running with hostname only
+ virtual servers */
+ int dnstimeout; /* maximum time to wait for reversedns */
+ int altlongreplies; /* use alternate long replies, more compatible
+ with crappy clients */
+ int smartbind; /* specifies whether to search for effecient
+ fd usage, or correct binding */
+ int zerobind; /* bind all ports using address 0.0.0.0, use
+ with smartbind on Freebsd to use
+ virtual servers */
+ int pasvport_first; /* When a passive connection is to be made */
+ int pasvport_last; /* this can specify what ports can be used */
+ /* useful for firewalls or NAT */
+ int natip; /* if the ftp server is behind NAT, this stores */
+ /* the real IP address */
+ IPACLLIST *nat_localips; /* if the ftp server is behind NAT, this
stores */
+ /* the access list that determines if the what IP
*/
+ /* to show for the PASV command */
+
+ char *hostname; /* Computer host name */
+ VSERVER *defaults; /* Default values for VSERVER */
+ VSERVER *defaulthost; /* The default host for hostvservers */
+ char **vserverlist; /* list of virtual servers names */
+ VSERVER *vservers; /* virtual server list */
+ VSERVERCONN *inports; /* input ports */
+
+ } CONFIGDATA;
+
+ typedef struct ftpstate
+ {
+ int remotefd; /* fd of the port to the remote system */
+ unsigned int remoteip; /* the systems IP number */
+ int connport; /* port connected to */
+ char *username; /* the username of the ftp user */
+ char *pwd; /* the current dir the ftp user is in */
+ char *homedir; /* the home directory of the ftp user */
+ char *basedir; /* the / directory for that user */
+ int passiveport; /* the fd of the listening passive port */
+ char *renameoldname; /* the source file to rename */
+ int loggedin; /* true if the user is logged in */
+ off_t restartpos; /* the position to start a download or upload */
+ int remoteport; /* the port number to connect to for data conns
*/
+ int binary; /* true if binary mode is set */
+ int threadnum; /* the number of the thread in ftpd terms (not
pid) */
+ int *cmddisableset; /* a set of integers used to disable commands */
+ int *sitedisableset; /* a set of integers used to disable site
commands */
+ STRING *inbuffer; /* the input buffer */
+
+ char *logindump; /* file to print after login */
+ char *cwddump; /* dump this file when you move to this dir */
+ char *busydump; /* dump this file if too many users are logged
in */
+ char *quitdump; /* dump this file when the user quits */
+
+ char *logindumpdata; /* this is for login dump */
+ char *cwddumpdata; /* this is when we change dir */
+ char *busydumpdata; /* this is when we are too busy */
+ char *quitdumpdata; /* this is when we quit */
+
+ ACLLIST *acldata; /* The access lists for this user */
+ int umask; /* the umask of newly created files */
+ gid_t gidt_asgid; /* all file work is done as this gid (if
possible) */
+ uid_t uidt_asuid; /* all file work is done as this uid (if
possible) */
+ int maxusers; /* maximum instances of this user allowed to be
logged in */
+ int maxtimeout; /* maximum time out for this user */
+ int timeout; /* timeout for this user */
+ int chmodable; /* can do chmod and change umask */
+ SELECTER *sel; /* select data stored here */
+ DATAPORT *dport; /* Data port information */
+ int loginsleft; /* number of login attempts left */
+ int jailenabled; /* is this user a jail */
+ int chroot; /* does a chroot occur */
+ int droproot; /* do we drop root when logging in */
+ int nicevalue; /* what niceness to run as */
+ int realdir; /* use real directory instead of built up
+ name */
+ int fxpallow; /* allow fxp(server-server) transfers */
+ int usercount; /* the number of users in the current group
when the user logged on */
+ char *hostname; /* the hostname of the remote host */
+ int accessdevices; /* can the user access device files */
+ char *groupname;
+ int fakemode;
+ char *fakename;
+ char *fakegroup;
+ VSERVER *vserver; /* vserver the user is connected to */
+ RATIOHANDLE *ratioinfo; /* ratio info */
+ gid_t *supgids; /* user supplementary gids */
+ unsigned int dataip; /* ip to connect data port to */
+ STRING *outbuffer; /* output coalessing buffer */
+ int maxtranspd; /* Maximum transfer speed */
+ int maxtranspd_down; /* Maximum download speed, overrides maxtranspd
*/
+ int maxtranspd_up; /* Maximum upload speed, overrides maxtranspd */
+ int epsv_forced; /* EPSV ALL was called, deny everything else */
+
+ /* Counters for stats */
+ int downloadedfiles;
+ int uploadedfiles;
+ off_t downloadedfilebytes;
+ off_t uploadedfilebytes;
+ off_t listdownloadedbytes;
+ int listconns;
+ } FTPSTATE;
+
+ typedef struct ftpcmd
+ {
+ char *command;
+ int (* ftpfunc)(FTPSTATE *peer, char *params);
+ int paramnum;
+ int needslogin;
+ int dataportok;
+ char *helpdesc;
+ } FTPCMD;
+
+ typedef struct inputline
+ {
+ FTPCMD *command;
+ char *parameters;
+ } INPUTLINE;
+
+ /* GLOBAL VARIABLES */
+
+ CONFIGDATA *config; /* configuration data stored here for easy access */
+ int inetd; /* is process running as inetd */
+ int logerrors; /* do we log config errors to screen, syslog,
or
+ screen */
+
+ /* these prototypes are mostly auto generated by scribe */
+
+ /* procnum.h */
+
+ void writescratch(int pos, int size, char *buff);
+ void writeshmem(int num, int pos, int len, void *buff);
+ void shinfo_addtogrouplist(VSERVER *vs);
+ void shinfo_setuparea(void);
+ void shinfo_init(char *scfilename);
+ void inetd_init(char *scfile);
+ void shinfo_reinit(void);
+ int shinfo_addstandalone(int newthid, char *vservername, unsigned int ip, int
viplimit, int iplimit);
+ int shinfo_adduser_inetd(unsigned int ip, int slimit, int iplimit, int
*error);
+ int shinfo_adduser(char *vserver, unsigned int ip, int vlimit, int slimit,
int viplimit, int iplimit);
+ int shinfo_setvserver(int thid, char *vservername, unsigned int ip, int
vlimit, int viplimit, int *error);
+ int shinfo_newuser_standalone(unsigned int ip, int iplimit, int *error);
+ void shinfo_changeop(char *operation);
+ void shinfo_changeuser(char *username);
+ void shinfo_sethost(char *hostname);
+ int shinfo_addusergroup(char *groupname, int limit);
+ void shinfo_setpid(int thrid, int pid);
+ void shinfo_delbypid(int pid);
+ void shinfo_delusergroup(char *groupname);
+ void shinfo_freebynum(int threadnum);
+ void shinfo_freethreads(int freecount, pid_t *freelist);
+ void pnums_signalchildren(int signalnum);
+ void shinfo_shutdown(void);
+
+ /* socket.h */
+
+ char *getipstr(unsigned int server);
+ void takentoolong(int sig);
+ char *getnetworkstr(unsigned int server);
+ int getnetworkint(char *server, unsigned int *out);
+ int conn_server(unsigned int ip, int port);
+ int conn_server_nonblocking(unsigned int ip, int port, int localport, int fd);
+ int listenport(int port, unsigned int ip, int maxconnect);
+ int get_conn(int socketin, unsigned int *addr);
+ int listenparrelelport(int fd, int *port, unsigned int *ip, int maxconnect);
+ void getsockinfo(int fd, unsigned int *ip, int *port);
+ unsigned int getremoteip(int fd);
+ void socket_flush_wait(int fd, int timeout);
+
+ /* select.h */
+
+ SELECTER *select_new(void);
+ void select_addfd(SELECTER *sel, int newport);
+ void select_delfd(SELECTER *sel, int deadport);
+ void select_addread(SELECTER *sel, int port, int (* proc)(SELECTER *, int,
void *), void *dat);
+ void select_addwrite(SELECTER *sel, int port, int (* proc)(SELECTER *, int,
void *), void *dat);
+ void select_takeread(SELECTER *sel, int port);
+ void select_takewrite(SELECTER *sel, int port);
+ int select_do(SELECTER *sel, int *signum, int timeout);
+ void select_shutdown(SELECTER *sel);
+
+ /* ftpsite.h */
+
+ int ftp_site(FTPSTATE *peer, char *cmd);
+ int ftpsite_dump(FTPSTATE *peer, char *cmd);
+ int ftpsite_umask(FTPSTATE *peer, char *cmd);
+ int ftpsite_help(FTPSTATE *peer, char *cmd);
+ int ftpsite_idle(FTPSTATE *peer, char *cmd);
+ int ftpsite_chmod(FTPSTATE *peer, char *cmd);
+ int ftpsite_access(FTPSTATE *peer, char *cmd);
+
+ /* proxy.h */
+
+ int controlportgotdata(SELECTER *sel, int fd, void *peerdata);
+ char *remove_rootcomponent(FTPSTATE *peer, char *filename, char *descript);
+ void dochroot(FTPSTATE *peer);
+ void rotatelogs(FTPSTATE *peer);
+ void ftpserverside_main(int remotefd, int remoteip, int threadnum, int
portnum, VSERVER *vserver);
+ int inport_bind(int portid, unsigned int bindip, int dodie);
+ int inport_getconn(SELECTER *mainsel, int fd, void *vs);
+ int vserver_select(FTPSTATE *peer, VSERVER *vserver);
+
+ /* version.h */
+
+ void showversion(char *desc);
+
+ /* acl.h */
+
+ ACLLIST *acllist_create(void);
+ char *acllist_makepermstr(ACLLIST *acl, int cnt, char *ret);
+ void acllist_add(ACLLIST *acl, char *dir, char *attribs, int is_regexp);
+ void acllist_tokendo(ACLLIST *acl, TOKENSET *tset);
+ int acllist_check(ACLLIST *acl, char *dir, int attr);
+ int check_acl(FTPSTATE *peer, char *path, int perm);
+ void acllist_dest(ACLLIST *acl);
+
+ /* ftpout.h */
+
+ void control_timeout(int num);
+ int ftp_write(FTPSTATE *peer, int bare, int messnum, char *fmt, ...);
+
+ /* utils.h */
+
+ void *mallocwrapper(int size);
+ void reallocwrapper(int size, void **inarea);
+ char *strdupwrapper(char *s);
+ void freewrapper(void *tofree);
+ void freeifnotnull(void *);
+ char *offt_tostr(off_t size);
+ int strto_offt(char *str, off_t *ret);
+
+ #ifndef HAVE_MEMMOVE
+ void *memmove(void *, const void *, int);
+ #endif
+
+ void strtrimspace(char *string);
+ int strchrcount(char *string, char tok);
+ char *safe_vsnprintf(int size, char *format, va_list ap);
+ char *safe_snprintf(char *format, ...);
+ char *getcwd2(void);
+ void pathname_simplify(char *pathname);
+ void test_libc(int verbose);
+
+ #ifndef HAVE_USLEEP
+ int usleep(int usecs);
+ #endif
+
+ STRCACHE *strcache_new(void);
+ char *strcache_check(STRCACHE *cache, int num);
+ void strcache_add(STRCACHE *cache, int num, char *str);
+ void strcache_free(STRCACHE *cache);
+ TOKENSET *tokenset_new(void);
+ void tokenset_settoken(TOKENSET *tset, unsigned char tok, char *data);
+ void tokenset_deltoken(TOKENSET *tset, unsigned char tok);
+ char *tokenset_apply(TOKENSET *tok, char *inputstr, int);
+ void tokenset_finish(TOKENSET *tset);
+
+ void init_pwgrfiles(void);
+ char *get_passwdname(uid_t inuid, int usefile);
+ char *get_groupname(gid_t ingid, int usefile);
+ gid_t *getusergrouplist(char *username);
+ gid_t *newgidlist(void);
+ gid_t *addgidlist(gid_t *list, gid_t new);
+ void delgidlist(gid_t *list, gid_t old);
+ gid_t *parsegidlist(char *str);
+ char *makegidliststr(gid_t *list);
+ void kill_uidgidfiles(void);
+ int isfilesafe(int fd);
+ LIMITER *limiter_new(int maxspeed);
+ void limiter_add(LIMITER *l, int byte_count, int force);
+ int giveuproot(uid_t uid, gid_t gid);
+ void errormsg( char *errmessage, char *file, int line );
+ void errormsgfatal( char *errmessage, char *file, int line );
+ void blockallsignals( void );
+ void unblockallsignals( void );
+
+ /* init.h */
+
+ void ftpd_setnogroups(void);
+ void ftpd_preinit(void);
+ void ftpd_init(char *filename, int verbose);
+
+ /* ftp.h */
+
+ void reporterror(FTPSTATE *peer, char *filename, int errorno);
+ int readipstr(char *data, int *port, unsigned int *ip);
+ int ftp_dele(FTPSTATE *peer, char *filename);
+ int ftp_chmod(FTPSTATE *peer, char *filename, int mode);
+ int ftp_size(FTPSTATE *peer, char *filename);
+ int ftp_mdtm(FTPSTATE *peer, char *filename);
+ void setdumptokens(FTPSTATE *peer, TOKENSET *ts);
+ int ftp_dumper(FTPSTATE *peer, NEWFILE *infile, int number, char *fmessage,
int dotokens, int endtokens);
+ int ftp_dumpstr(FTPSTATE *peer, char *dumpstr, int number, char *fmessage,
int endtokens);
+ int ftp_rnto(FTPSTATE *peer, char *filename);
+ int ftp_mkd(FTPSTATE *peer, char *filename);
+ int ftp_rmd(FTPSTATE *peer, char *filename);
+ int ftp_cwddo(FTPSTATE *peer, char *newdir, int dump);
+ int ftp_cwd(FTPSTATE *peer, char *newdir);
+ int ftp_run(FTPSTATE *peer, INPUTLINE *cmd, char *token);
+ int ftp_quit(FTPSTATE *peer, char *param);
+ int ftp_user(FTPSTATE *peer, char *param);
+ int ftp_pass(FTPSTATE *peer, char *param);
+ int ftp_rest(FTPSTATE *peer, char *param);
+ int ftp_syst(FTPSTATE *peer, char *param);
+ int ftp_port(FTPSTATE *peer, char *param);
+ int ftp_pwd(FTPSTATE *peer, char *param);
+ int ftp_type(FTPSTATE *peer, char *param);
+ int ftp_abor(FTPSTATE *peer, char *param);
+ int ftp_pasv(FTPSTATE *peer, char *param);
+ int ftp_list(FTPSTATE *peer, char *param);
+ int ftp_nlst(FTPSTATE *peer, char *param);
+ int ftp_cdup(FTPSTATE *peer, char *param);
+ int ftp_rnfr(FTPSTATE *peer, char *param);
+ int ftp_noop(FTPSTATE *peer, char *param);
+ int ftp_rein(FTPSTATE *peer, char *param);
+ int ftp_none(FTPSTATE *peer, char *param);
+ int ftp_help(FTPSTATE *peer, char *param);
+ int ftp_dohelp(FTPSTATE *peer, FTPCMD *ftpcmds, char *command, int
*disableset);
+ int ftp_allo(FTPSTATE *peer, char *param);
+ int ftp_acct(FTPSTATE *peer, char *param);
+ int ftp_stru(FTPSTATE *peer, char *param);
+
+ /* ftpstat.h */
+
+ int ftp_stat(FTPSTATE *peer, char *param);
+
+ /* cmd.h */
+
+ int *disableset_create(void);
+ void disableset_disablecmd(int *set, FTPCMD *ctable, char *cmd);
+ char *getkeyword(char **iline);
+ void cmd_split(FTPSTATE *peer, INPUTLINE *cmd, char* inpline, FTPCMD *ctable,
int log, int *disableset);
+
+ /* logger.h */
+
+ int log_initcontext(char *logname);
+ void log_setcontext(int logfd, int logmask);
+ void log_addentry(int type, FTPSTATE *peer, char *desc);
+ void log_giveentry(int type, FTPSTATE *peer, char *desc);
+ void debuglog(char *format, ...);
+ void log_shutdown(void);
+
+ /* dir.h */
+
+ char *dir_getreal(FTPSTATE *peer);
+ char *dir_getvirtual(FTPSTATE *peer, char *);
+ void dir_combine(FTPSTATE *peer, char **pwd, char *newdir);
+
+ /* shmem.h */
+
+ void shmem_finish(int shmemnum);
+ void *shmem_get(char *ipcfile, int size, int *shmemnum, int *isnew, int
*lockfd);
+
+ /* ftplist.h */
+
+ int ftplist_parseflags(char *params);
+ char *listmakeline(FTPSTATE *peer, char *longname, char *filename, struct
stat *fileinfo, STRCACHE *uidcache, STRCACHE *gidcache, int year);
+ LISTHANDLE *getlisthandle(FTPSTATE *peer, char *dirpattern, int nlist, char
*reldir, int params);
+ char *getlisthandleline(FTPSTATE *peer, LISTHANDLE *lh);
+ void freelisthandle(LISTHANDLE *lh);
+ int list_write(SELECTER *sel, int fd, void *peerv);
+ char *listmakepattern(FTPSTATE *peer, char *parm, char **rdir, int flags);
+ int ftp_lister(FTPSTATE *peer, char *parm, int nlist, int params);
+
+ /* checkip.h */
+
+ int checknamelist(CONFIGFILECACHE *cf, int section, char *username);
+ IPACLLIST *ipacllist_new(CONFIGFILECACHE *cf, int section, char *setting,
char acceptchar, int defaultret);
+ void ipacllist_destroy(IPACLLIST *list);
+ int ipacllist_query(IPACLLIST *list, int ip, char *hostname);
+
+ /* ftpstate.h */
+
+ void ftpstate_init(FTPSTATE *ftp, int fd, int ip, int threadnum, int portnum,
VSERVER *vs);
+ void ftpstate_dest(FTPSTATE *ftp);
+
+ /* bufread.h */
+
+ int popcmd(FTPSTATE *peer, char **outstr);
+ int readcmd(FTPSTATE *peer);
+
+ /* config.h */
+
+ int loadconfigfile(char *filename, int (* confighandler)(char *, char *, int,
void *),
+ void *configdata, int bescure, int *handlererror, int
*linenum);
+ int cachemaker(char *cmd, char *data, int linenum, void *c);
+ CONFIGFILECACHE *loadconfigcache(char *filename, int *linenum, int *error);
+ char *config_errorstr(int result);
+ int getsectionid(CONFIGFILECACHE *cache, char *section);
+ char *getconfigdata_r(CONFIGFILECACHE *cache, int section, char *cmd, int
*occur, int depth, int *error);
+ char *getconfigdata(CONFIGFILECACHE *cache, int section, char *cmd, int
occur);
+ char **makeconfiglist(CONFIGFILECACHE *cache, char *section, char *label);
+ void loadintfromconfig(CONFIGFILECACHE *cache, int section, char *setting,
+ int *to, int def);
+ void loadstrfromconfig(CONFIGFILECACHE *cache, int section, char *setting,
+ char **to, char *def);
+ void freeconfigcache(CONFIGFILECACHE *cache);
+
+ /* ftptrans.h */
+
+ int sigio_handler(int signum);
+ int filter_toascii(char *data, int *len);
+ int filter_fromascii(char *data, int *len);
+ int download_write(SELECTER *sel, int fd, void *peerv);
+ int upload_read(SELECTER *sel, int fd, void *peerv);
+ int ftp_retr(FTPSTATE *peer, char *filename);
+ int ftp_stor(FTPSTATE *peer, char *filename);
+ int ftp_stou(FTPSTATE *peer, char *filename);
+ int ftp_appe(FTPSTATE *peer, char *filename);
+
+ /* newfile.h */
+
+ int readbuffer(NEWFILE *file);
+ NEWFILE *nfopen(char *filename);
+ NEWFILE *nfdopen(int fd);
+ char *nfgetcs(NEWFILE *file, char testchar);
+ void nfclose(NEWFILE *file);
+
+ /* main.h */
+
+ void logfullmessage(int error, unsigned int ip);
+ VSERVER *findvserver(unsigned int ip, int port);
+ void smartbind(SELECTER *selset, VSERVERCONN *list, int dodie);
+ void dumbbind(SELECTER *selset, VSERVERCONN *list, int dodie);
+ void sighandler(int signum);
+ int mainprog(char *fconfig, int runforeground, int verbose);
+ void mainprog_inetd(char *fconfig, unsigned int ip);
+ void diehandler(int signum);
+ int main(int argc, char **argv);
+
+ /* datasock.h */
+
+ int datasock_connect(SELECTER *sel, int fd, void *peerv);
+ int startdatasocket(FTPSTATE *peer, int filefd, int trans_type, off_t tsize);
+ void closedatasocket(FTPSTATE *peer);
+ void abortdatasocket(FTPSTATE *peer);
+
+ /* auth.h */
+
+ void converttorealstr(char *strbuf);
+ int chkpassword(char *encrypass, char *password);
+ int checkexploits(FTPSTATE *peer);
+ int authlogmsg(char *directive, char *groupname);
+ int checkabsdir(char *dir);
+ void clearauth(FTPSTATE *peer);
+ char *mkconfrealstr(int sectionid, char *item, char *defaul);
+ char *mktokconfstr(TOKENSET *tset, int sectionid, char *item, char *defaul);
+ int mktokconfint(TOKENSET *tset, int sectionid, char *item, char *format,
+ char *defaultstr, int defaultint);
+ void setupacls(FTPSTATE *peer, TOKENSET *tset, int section, char *funcname,
int aclfunc);
+ int transferconfig(FTPSTATE *peer, TOKENSET *tset, int section);
+ int auth_getcursectionid(FTPSTATE *peer);
+ void *auth_getconfigcache(void);
+ char *setuseropts(FTPSTATE *peer, char *password);
+
+ /* file.h */
+
+ void file_becomeuser(FTPSTATE *peer);
+ void file_becomeroot(FTPSTATE *peer);
+ int checkdir(char *dir);
+ int checkfile(char *file);
+ int checkchdir(FTPSTATE *peer, char *dir);
+ void convertperms(char *permstr, int mode);
+ char *file_expand(FTPSTATE *peer, char *filename);
+ int file_isfdregularfile(int fd);
+ int file_isfdadir(int fd);
+ int file_ustoreopen(FTPSTATE *peer, char *, int *, char **rname);
+ int file_storeopen(FTPSTATE *peer, char *infile, char **rname);
+ int file_readopen(FTPSTATE *peer, char *infile, char **rname);
+ NEWFILE *file_nfopen(FTPSTATE *peer, char *filename);
+ MYGLOBDATA *file_glob(FTPSTATE *peer, char *dir, char *pattern, int allfiles);
+ int file_unlink(FTPSTATE *peer, char *infile);
+ char *file_rename(FTPSTATE *peer, char *infile, char *infile2);
+ int file_stat(FTPSTATE *peer, char *infile, struct stat *output);
+ int file_mkdir(FTPSTATE *peer, char *infile);
+ int file_rmdir(FTPSTATE *peer, char *infile);
+ int file_chmod(FTPSTATE *peer, char *infile, int mode);
+
+ /* cfloader.h */
+
+ char *gethostname2(void);
+ void configerror(char *str);
+ void vserver_kill(VSERVER *c);
+ VSERVER *vserver_load(CONFIGDATA *cf, char *sectionname, VSERVER *def,
VSERVERCONN ***vp);
+ void ftpd_killconfig(CONFIGDATA *dc);
+ CONFIGDATA *ftpd_loadconfig(char *inidata, int as_inetd, int use_umask);
+ int ftpd_checkvserver(CONFIGDATA *cdat, VSERVER *vs);
+ int ftpd_checkconfig(CONFIGDATA *cdat);
+
+ /* ratio.h */
+
+ int lockarea(int fd, int pos, int len, int locktype, int do_wait);
+ void lock_n_read(RATIOHANDLE *rh);
+ void write_n_unlock(RATIOHANDLE *rh);
+ int openratiofile(char *filename);
+ int decoderatiostr(char *ratstr, int *pa, int *pb);
+ RATIOHANDLE *ratio_loaduser(char *username, int section);
+ void ratio_uploadbytes(RATIOHANDLE *rh, int bytes);
+ int ratio_downloadbytes(RATIOHANDLE *rh, int bytes);
+ void ratio_uploadfile(RATIOHANDLE *rh);
+ int ratio_downloadfile(RATIOHANDLE *rh);
+ void ratio_reread(RATIOHANDLE *rh);
+ void ratio_stat(FTPSTATE *peer, RATIOHANDLE *rh, char *replystr);
+ void ratio_settokens(RATIOHANDLE *rh, TOKENSET *ts);
+ void ratio_finish(RATIOHANDLE *rh);
+
+
Index: muddleftpd/src/proxy.c
diff -c /dev/null muddleftpd/src/proxy.c:1.1.8.1
*** /dev/null Tue Nov 4 10:41:23 2003
--- muddleftpd/src/proxy.c Tue Nov 4 10:41:22 2003
***************
*** 0 ****
--- 1,454 ----
+ /* Copyright (C) 1999 Beau Kuiper
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #include "ftpd.h"
+ #include "ftpcmd.h"
+ #include "reply.h"
+
+ typedef struct overload_info
+ {
+ int pos;
+ char *msg;
+ int len;
+ } OVERLOAD_INFO;
+
+ extern FTPCMD mainftpcmd[];
+ extern pid_t *deadlist;
+
+ int controlportgotdata(SELECTER *sel, int fd, void *peerdata)
+ {
+ FTPSTATE *peer = (FTPSTATE *)peerdata;
+ char *instring = NULL;
+ int connclosed = readcmd(peer);
+ int exits = FALSE;
+ INPUTLINE cmd;
+
+ if (connclosed)
+ return(TRUE);
+ else
+ {
+ if (popcmd(peer, &instring))
+ {
+ ftp_write(peer, FALSE, 500, REPLY_ONECMDONLY);
+ return(TRUE);
+ }
+ if (instring) /* we have a command */
+ {
+ cmd_split(peer, &cmd, instring, mainftpcmd, TRUE,
+ (peer->loggedin ? peer->cmddisableset :
NULL));
+ if (!peer->dport)
+ if (cmd.command->ftpfunc != ftp_pass)
+ shinfo_changeop(instring);
+
+ exits = ftp_run(peer, &cmd, "FTP");
+ freeifnotnull(cmd.parameters);
+ if (!peer->dport)
+ shinfo_changeop("idle");
+
+ string_clear(&(peer->inbuffer));
+ }
+ return(exits);
+ }
+ }
+
+ char *remove_rootcomponent(FTPSTATE *peer, char *filename, char *descript)
+ {
+ int baselen = strlen(peer->basedir);
+ pathname_simplify(filename);
+
+ if (strncmp(peer->basedir, filename, baselen) == 0)
+ memmove(filename, filename + baselen, strlen(filename) -
baselen + 1);
+ else
+ {
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("%s(%s) is
outside of rootdir(%s) with chroot enabled!", descript, filename,
peer->basedir));
+ freewrapper(filename);
+ return(NULL);
+ }
+ return(filename);
+ }
+
+ void dochroot(FTPSTATE *peer)
+ {
+ /* this prevents bugs in resolving filenames */
+ if (strcmp(peer->basedir, "/") == 0)
+ {
+ peer->chroot = FALSE;
+ return;
+ }
+ if (config->rootmode)
+ {
+ int res = chroot(peer->basedir);
+ if (res == 0)
+ {
+ /* put ourselves into the tree */
+ chdir("/");
+
+ /* once chroot is done, nothing can undo it,
+ so user cannot relogin */
+ peer->jailenabled = TRUE;
+
+ /* now change dumped file names */
+ pathname_simplify(peer->basedir);
+ if (peer->logindump)
+ peer->logindump = remove_rootcomponent(peer,
peer->logindump, "welcome");
+ if (peer->quitdump)
+ peer->quitdump = remove_rootcomponent(peer,
peer->quitdump, "quitdump");
+ if (peer->cwddump)
+ if ((peer->cwddump)[0] == '/')
+ peer->cwddump =
remove_rootcomponent(peer, peer->cwddump, "cddump");
+
+ freewrapper(peer->basedir);
+ peer->basedir = strdupwrapper("/");
+
+ }
+ else
+ log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("chroot('%s') gave error %s", peer->basedir, strerror(errno)));
+ }
+ else
+ log_addentry(MYLOG_INFO, NULL, "Cannot use chroot() without
root permission.");
+ }
+
+ void rotatelogs(FTPSTATE *peer)
+ {
+ char *logfile;
+ int newlogcontext;
+
+ if (peer->vserver->logfile)
+ logfile = peer->vserver->logfile;
+ else
+ logfile = config->defaults->logfile;
+
+ if ((!peer->chroot) || (!peer->droproot))
+ {
+ /* use root to open log */
+ file_becomeroot(peer);
+ newlogcontext = log_initcontext(logfile);
+ file_becomeuser(peer);
+
+ if (newlogcontext == -1)
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("Could
not open log file '%s', reopen failed", peer->vserver->logfile));
+ else
+ {
+ log_shutdown();
+ config->logout = newlogcontext;
+ log_setcontext(config->logout, peer->vserver->loglevel);
+ }
+ }
+ else
+ log_addentry(MYLOG_INFO, NULL, "Cannot reopen log file in
chroot or droproot mode");
+ }
+
+ int vserver_select(FTPSTATE *peer, VSERVER *vserver)
+ {
+ int error, result;
+ int newlogcontext;
+
+ peer->vserver = vserver;
+
+ /* initalize the new log context */
+ newlogcontext = config->logout;
+
+ if (vserver->logfile)
+ if (strcmp(config->defaults->logfile, vserver->logfile) != 0)
+ {
+ newlogcontext = log_initcontext(vserver->logfile);
+ if (newlogcontext == -1)
+ {
+ log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("Dropping connection, error opening virtual server logfile '%s':
%s", vserver->logfile, strerror(errno)));
+ return(1);
+ }
+ log_shutdown();
+ config->logout = newlogcontext;
+ }
+
+ log_setcontext(config->logout, vserver->loglevel);
+
+ /* see if the user is allowed in this vserver */
+ if (!ipacllist_query(vserver->ipaccess, peer->remoteip, peer->hostname))
+ {
+ log_addentry(MYLOG_DACCESS, peer, NULL);
+ return(2);
+ }
+
+ /* set the procdata up */
+ result = shinfo_setvserver(peer->threadnum, vserver->sectionname,
+ peer->remoteip, vserver->maxusers,
+ vserver->maxperip, &error);
+ if (!result)
+ {
+ logfullmessage(error, peer->remoteip);
+ return(3);
+ }
+
+ return(0);
+ }
+
+ void ftpserverside_main(int remotefd, int remoteip, int threadnum, int
portnum, VSERVER *vserver)
+ {
+ int newlogcontext, exits = FALSE;
+ int flag = 1;
+ struct rlimit mylimits = { MAXMEMUSAGE, MAXMEMUSAGE };
+ FTPSTATE *peer = mallocwrapper(sizeof(FTPSTATE));
+ char *greetline;
+
+ ftpstate_init(peer, remotefd, remoteip, threadnum, portnum, vserver);
+ /* initalize ftp state data struture */
+ shinfo_sethost(peer->hostname);
+
+ if (!ipacllist_query(config->defaults->ipaccess, remoteip,
peer->hostname))
+ {
+ log_addentry(MYLOG_DACCESS, peer, NULL);
+ close(remotefd);
+ return;
+ }
+
+ newlogcontext = config->logout;
+
+ if (vserver->logfile)
+ if (strcmp(config->defaults->logfile, vserver->logfile) != 0)
+ {
+ newlogcontext = log_initcontext(vserver->logfile);
+ if (newlogcontext == -1)
+ {
+ log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("Dropping connection, error opening virtual server logfile '%s':
%s", vserver->logfile, strerror(errno)));
+ close(remotefd);
+ return;
+ }
+ log_shutdown();
+ config->logout = newlogcontext;
+ }
+
+ log_setcontext(config->logout, vserver->loglevel);
+
+ setrlimit(RLIMIT_DATA, &mylimits);
+
+ peer->vserver = vserver;
+
+ /* see if user is allowed to enter */
+
+ if (!ipacllist_query(vserver->ipaccess, remoteip, peer->hostname))
+ {
+ log_addentry(MYLOG_DACCESS, peer, NULL);
+ close(remotefd);
+ return;
+ }
+
+ /* initalize the PRNG */
+
+ srandom((unsigned int)time(NULL));
+
+ peer->sel = select_new();
+
+ setsockopt(peer->remotefd, IPPROTO_TCP, TCP_NODELAY, &flag,
sizeof(int));
+
+ /* add the remote fd for reading */
+ select_addfd(peer->sel, remotefd);
+ select_addread(peer->sel, remotefd, controlportgotdata, (void *)peer);
+
+ /* output our greeting */
+ shinfo_changeop("idle");
+
+ if (vserver->greetline)
+ greetline = vserver->greetline;
+ else
+ greetline = REPLY_GREET;
+
+ if (vserver->prelogindumpdata)
+ exits = ftp_dumpstr(peer, vserver->prelogindumpdata, 220,
greetline, TRUE);
+ else
+ exits = ftp_dumper(peer, nfopen(vserver->prelogindump), 220,
greetline, TRUE, TRUE);
+
+ while(!exits)
+ {
+ int fd, signalnum;
+
+ fd = select_do(peer->sel, &signalnum, peer->timeout);
+ /* if we get 3 back, simply loop and update timeout */
+ if (fd == -1)
+ {
+ if ((signalnum == SIGTERM) || (signalnum == SIGHUP))
+ {
+ /* server is shutting down! */
+ ftp_write(peer, FALSE, 421,
REPLY_SERVERSHUTDOWN);
+ exits = TRUE;
+ }
+ else if (signalnum == SIGUSR1)
+ {
+ rotatelogs(peer);
+ }
+ else if (signalnum == 0)
+ exits = TRUE;
+
+ }
+ else if (fd == 0)
+ {
+ /* timeout has occurred */
+ ftp_write(peer, FALSE, 421,
REPLY_TIMEOUT(peer->timeout));
+ exits = TRUE;
+ }
+ else if (fd != 3)
+ exits = TRUE;
+ }
+
+ log_addentry(MYLOG_LOGIN, peer, "User logged out.");
+ if (peer->acldata)
+ acllist_dest(peer->acldata);
+ select_shutdown(peer->sel);
+ ftpstate_dest(peer);
+ }
+
+ int inport_bind(int portid, unsigned int bindip, int dodie)
+ {
+ int incon;
+
+ if ((portid < 1024) && (getuid() != 0))
+ {
+ char *error = safe_snprintf("root access required to bind port
%d (less than 1024), skipping", portid);
+ if (dodie)
+ ERRORMSGFATAL(error);
+ else
+ log_giveentry(MYLOG_INFO, NULL, error);
+ return(-1);
+ }
+
+ incon = listenport(portid, bindip, MAXPENDCONN);
+
+ if (incon == -1)
+ {
+ char *error = safe_snprintf("Cannot bind to port %d, ip %s,
skipping!", portid, getipstr(bindip));
+ if (dodie)
+ ERRORMSGFATAL(error);
+ else
+ log_giveentry(MYLOG_INFO, NULL, error);
+ }
+ return(incon);
+ }
+
+ int overload_sendmessage(SELECTER *mainsel, int fd, void *in)
+ {
+ OVERLOAD_INFO *i = (OVERLOAD_INFO *)in;
+ int c;
+
+ c = write(fd, i->msg + i->pos, i->len);
+
+ i->len -= c;
+ i->pos += c;
+
+ if ((c <= 0) || (i->len <= 0))
+ {
+ freewrapper(i);
+ return(2);
+ }
+
+ return(FALSE);
+ }
+
+ int inport_getconn(SELECTER *mainsel, int fd, void *vs)
+ {
+ int newconn;
+ unsigned int ipaddress, lip;
+ VSERVER *vserver;
+ int tnum, port, error, result;
+ pid_t fresult;
+
+ newconn = get_conn(fd, &ipaddress);
+ if (newconn == -1)
+ {
+ log_giveentry(MYLOG_INFO, NULL, safe_snprintf("Error accepting
control connection: %s", strerror(errno)));
+ return(FALSE);
+ }
+
+ if (config->hostvservers)
+ {
+ getsockinfo(newconn, &lip, &port);
+ vserver = config->defaults;
+ }
+ else if (vs != NULL)
+ {
+ vserver = ((VSERVERCONN *)vs)->vptr;
+ port = ((VSERVERCONN *)vs)->port;
+ }
+ else
+ {
+ getsockinfo(newconn, &lip, &port);
+ vserver = findvserver(lip, port);
+ }
+
+ /* was not able to find a vserver for the port/ip they connected to */
+ if (vserver == NULL)
+ {
+ close(newconn);
+ return(FALSE);
+ }
+
+ result = TRUE;
+ tnum = shinfo_newuser_standalone(ipaddress, config->defaults->maxperip,
&error);
+ if ((tnum != -1) && (config->vservers) && (!config->hostvservers))
+ result = shinfo_setvserver(tnum, vserver->sectionname,
ipaddress,
+ vserver->maxusers,
+ vserver->maxperip,
+ &error);
+
+ if ((tnum != -1) && (result))
+ {
+ fresult = fork();
+ if ((int)fresult == 0)
+ {
+ shinfo_setpid(tnum, (int)getpid());
+ select_shutdown(mainsel);
+ freewrapper(deadlist);
+ ftpserverside_main(newconn, ipaddress, tnum, port,
vserver);
+ ftpd_killconfig(config);
+ kill_uidgidfiles();
+ log_shutdown();
+ exit(0);
+ }
+ else if ((int)fresult == -1)
+ {
+ shinfo_freebynum(tnum);
+ log_addentry(MYLOG_INFO, NULL, "Could not fork,
dropping connection.");
+ ERRORMSG("Could not fork, dropping connection!");
+ close(newconn);
+ }
+ else
+ {
+ close(newconn);
+ }
+ }
+ else
+ {
+ /* server is full, or too many connections */
+ if (tnum != -1)
+ shinfo_freebynum(tnum);
+ logfullmessage(error, ipaddress);
+ if (config->toobusycount <= MAXTOOMANYUSERS)
+ {
+ OVERLOAD_INFO *i = mallocwrapper(sizeof(OVERLOAD_INFO));
+
+ i->msg = vserver->toobusy;
+ if (i->msg == NULL)
+ i->msg = REPLY_SERVERBUSY;
+ i->pos = 0;
+ i->len = strlen(i->msg);
+ fcntl(newconn, F_SETFL, O_NONBLOCK);
+ select_addfd(mainsel, newconn);
+ select_addwrite(mainsel, newconn, overload_sendmessage,
i);
+ }
+ else
+ close(newconn);
+ }
+ return(FALSE);
+ }
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/02
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/03
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/03
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Beau Kuiper, 2003/11/04
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Beau Kuiper, 2003/11/04
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd,
Beau Kuiper <=
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Beau Kuiper, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Beau Kuiper, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06
- [Muddleftpd-cvs] CVSROOT: /cvsroot/muddleftpd, Joerg Jaspert, 2003/11/06