This server is Copyright 2001 by Michael Lecuyer. Please
mail problems and suggestions to Michael.
The latest version is always available at www.theorem.com.
Introduction:
The FTP server is written in Java which requires either
the Java Developer's Kit (JDK) or the Java Runtime Environment (JRE). The
server is 100% pure Java and has been tested under Windows 95/98/NT/2000, Linux 6.1 - 7.3,
and Novell Netware 4.10/5.0 and requires Java 1.2 or better. The server offers a
flexible security structure as well as effective authentication methods, the most flexible
and secure using a RADIUS server for authentication. The distribution file contains
a ftpserver.jar file. The command to run the server might look something like this:
java -cp ftpserver.jar com.theorem.ftp.ftpd.
java -jar ftpserver.jar [configuration directory]
Installation:
Some Inner Workings
Configuration changes (changes to FTP.CFG or DIR.CFG) are checked every 60 seconds. If a configuration change occurs all subsequent connections will feel the effects of the change, but current connections will be unaffected.
The configuration thread runs a lower priority that other threads. This may slow down configuration changes on a very busy system. There is notification in the log file when the configuration has been read..
New logons receive their home directories (if configured) upon login, and these home directory mappings are lost upon logout or disconnection.
If RADIUS authentication is used the Idle-Timeout
configured on the RADIUS server can be applied to the client. This means difference people
may be allotted different time outs, or a common timeout. This does not yet apply to
anonymous clients.
Run this from /etc/rc.d/init.d (Redhat) as ftpd. There is a script called 'javaps' available at Linux Java Process Status
page. It's very useful when determining which process to kill. Or just start it up in local.rcConfiguration:
There are two configuration files - FTP.CFG and DIR.CFG. The
first, FTP.CFG, contains general configuration parameters while DIR.CFG contains the
virtual directory and permissions set up. The SAMPLES directory has an example
setup.
FTP.CFG:
This file's default location is the current directory where
the FTP server is run. An alternate directory may be specified on the command line: java
com.theorem.ftp.ftpd c:\ftpdir. The contents of the file are simple assignments.
Comments may be specified by a leading ; or #. Blank lines are
ignored.
Built in authentication uses a plain text password
file. If you want something more aggressive you can define your own class.
Sample code for using the RADIUS protocol is in RadiusAuthenticate in the sample
directory.
If you're not using a RADIUS server, but want to use a
password file or your own password check class both are available. To use a simple name
& password file comment out or remove at least the radius.server entry to
disable and use the following configuration:
; Authentication may be done two ways.
; The native internal way is to use a plain text file of
names and passwords.
; Clearly this is a security problem, but effective for
demonstrations or for an anonymous
; server.
; The file contains comma delimited name/password lines:
michael, java98
; To use this method you must provide a text file defined
here. If the next method of
; authentication is provided this directive will be ignored.
; The file resides in the configuration directory.
password.file = password.txt
; The alternative is to provide your own class to perform
authentications.
; This is the second authentication method.
; If you have your own class to authenticate with and do not
wish to use the
; two internal methods define yours here:
; password.class = com.theorem.ftp.samples.TestAuthenticate
You can use your own class to, let say, use LDAP to look up names and passwords. Examples of an authentication implementation are found in the samples directory.
The server port number defaults to 21. If you need a different port number (to support multiple servers, or for another reason) you can modify the command port number. The default data port will always be one less than the command port.
; Server port number
server.port = 21
The log file may be located anywhere. The default is called FTP.LOG and is in the current directory.
; Server log file. This can be anywhere - records
status and errors
server.logfile = ./ftpnote.log
; Server transfer log file.
; Traditional FTP logs compatible with FTP log analysis
programs
server.xferlog = ./ftp.log
; You can log commands as they arrive. Sometimes this is
useful if the other side is sending
; unusual commands or gets stuck. Yes or no.
server.logcommands = no
An inactivity timeout may be set for clients. If radius.timeout (above) is specified server.timeout will be used for anonymous logins only. Initially all logons are considered to be anonymous until logged in so make this value at least sufficient to logon. If the server.timeout is set to zero no timeout will occur.
; Server socket timeout in minutes.
server.timeout = 15
If you want a file to be displayed at login define it's name here. It must be located in the same directory as the FTP.CFG file.
As clients move about the server's virtual directories you can arrange to display a file upon a directory change. This defines the name of the file to look for. Usually this file will describe the contents of the directory and it's files.
; Display this file on a chdir if it exists.
server.display = 00_index.txt
The total number of connections (including anonymous connections) can be set. If this parameter is not given or is zero unlimited connections will be permitted.
connections.max=100
Anonymous login control is exercised here. If the anonymous.allow parameter is missing the default is to deny anonymous logins. If set to yes you can specify the maximum number of simultaneous anonymous logins. The default is zero anonymous logins.
anonymous.allow=yes
anonymous.max=10
If you need a class to track certain uploads and downloads
you can create a class to follow this activity.
The FileReceipt class implementation (see the examples
directory for FileCheck.java - a very simple implementation) can match and track
files. There are two methods called when a file is uploaded and downloaded.
FileReceipt.getBefore() is called before a file is downloaded, and FileReceipt.getAfter()
is called after a file is successfully downloaded. The getBefore method can deny a
file's download by returning a standard FTP response string (e.g. 553 Requested action
not taken.).
; An example of a FileReciept class. This class is
called when a file is up/downloaded
; to trigger some event.
filereceipt.class = com.theorem.ftp.examples.FileCheck
DIR.CFG:
This file controls the names of the virtual directories (the
directories the client sees), the physical directories associated with them, and the
permissions for access.
Groups are used to shorten a list of names into one name. The special character '@' implies all real logon clients, i.e. those that have a name and password. To put it another way this means everyone but Anonymous. The format of the group statement is: group ClassName ClassList. An example would be:
group webauthors mjl fred susan
group temp @
Groups may not contain the '*' wild card. Duplicates resulting from list expansions are safe to use. Groups may contain other classes. The next example, although it contains redundant names, is harmless:
class toomany temp @ webauthors mjl fred
The default virtual home directory must be defined and must exist as a physical directory. This is the directory that the newly logged on client will find themselves. This is designated by assigning the virtual directory to a physical directory. It can be the same as another virtual directory setup. If "/" isn't defined it will be impossible to use CDUP or CWD .. to get back to the root.
The format is Virtual_Directory Physical_Directory Permission_List. The Virtual Directories are described in with UNIX style path separators, the Physical Directories are described in the local system's structure.
Permissions come in three varieties.
Not specifying any permission denies everyone access to the directory. Always specify mappings in the UNIX style (forward slashes). Physical paths will be corrected internal for your platform. Here's a short example:
; Set up a virtual directory of "/" as the apparent root using the
physical directory of C:\PUB. Anyone, including
; anonymous, has read permission.
/
C:\PUB *
; The webmaster is the only client who may read/write to the web pages
/www.theorem.com C:\WEB\DOCS +webmaster
; Michael may administer his web page, but the webmaster is denied.
/www.theorem.com/michael C:\WEB\DOCS\MJL +michael !webmaster
; Only Cynthia may write to her personal directory. No one else has access.
/users/cynthia C:\PUB\CYNTHIA
+cynthia
; The local directory is denied to anonymous even though the virtual directory
"/" is accessible.
/local
C:\PUB\LOCAL !anonymous
; The web authors class has free reign over this directory
/webpages
C:\WEB\DOCS +webauthors
; Everyone may write in /tmp, except anonymous
/tmp
C:\TMP +@
Home directories are supported and are quite flexible. Multiple home directories may be defined both as shortcuts, and to provide multiple personal FTP directories. Each directory configuration has a name, A.user through Z.user. Each name specifies a physical directory. A string of "{}" within the physical directory will be substituted with the logon name. If the "{}" is missing it's appended to the physical directory. The resulting virtual directory will appear as "/user/{}/[subdirectory]". From the following example this will become clearer. This is example is for Linux, on windows the paths will look like C:\although forward slashes are correctly handled under windows.
A.user = /user/{}/www>/FONT>
B.user = /user
This will result in two mappings when Michael logs in:
/user/michael/www ---> SYS:/user/michael/www /user/michael ---> SYS:/user/michael
The logged in client will have full permissions to the directory (see below under DIR.CFG what this implies). Multiple mappings that result in the same virtual directory will only appear once. Always specify mappings in the UNIX style (forward slashes). Physical paths will be corrected internal for your platform.
WELCOME.TXT:
The WELCOME.TXT file (if it exists) contains a welcome
message presented to each client as they successfully log on. The file is in the
same directory as the FTP.CFG file.
Setting the root directory is very important, and the server won't run without one. Preferably it should be set to a public directory and given public access:
/ /test *
Any virtual directory's contents will inherit the
permission. You may change permissions to particular directories by naming
them:
; Set the root directory:
/ /test *
; Deny access to the source directory, except to michael
/test/source !* !@ michael
Denials: If you deny an entity, you must enable another if you want access to a directory.
; Deny anoymous but permit everyone logged in.
/test /pub/test !anonymous @
or
; Deny michael access, but permit general access.
/test /pub/test !michael *
or
; Deny anonymous but permit michael
/test /pub/test !anonymous michael
The reason is that the FTP server can't determine who should have access '*' for public access or '@' for those actually logged in.
If you're having trouble accessing virtual directories
check the log file - just after the server announces that it's started it prints a list of
virtual directories and their permissions. If a directory can't be accessed it'll
say so too.
The code is divided into inner classes, each of which handles a particular FTP command (USER, CWD, STOR, etc). n addition there are several sections:
CurrentInfo - holds current session information - the login name, directories they have permissions to access (read only or read/write). This also contains the methods necessary to check that the entity has permission which is done on the fly.
Changing the configuration files - a separate thread periodically checks to see if the configuration files have changed and makes those changes to the static Global class. As each session starts it gets it's own copy of the Global class.
There are two other classes that may be implemented. One is a preferred authentication method, beyond the simple text file lookup. The other is a class is informed of attempts to access files for upload or download. You may control access more finely through this class (lets say you'll never let anyone get password files) or use it to notify other programs that a file has bee uploaded or downloaded.