filthttp − The HTTP File Transfer Daemon
filthttp [ options ]
filthttp is a minimalistic authenticated, multiuser HTTP server, designed for multiuser, bidirectional file transfer in a form that can be secure and easily scripted. It reads from descriptor 0 and writes to descriptor 1, and is intended to be run behind a network service daemon such as stunnel or tcpserver. Log data is sent to stderr.
filthttp must be run as root. As root, the following actions are performed, in order: Minimal parsing (most parsing is put off until after privileges have been dropped); user authentication; user authorization; chroot to the user’s home directory; dropping of privileges. Additional parsing and actions are performed as the user’s own ID.
Supported HTTP commands include GET, POST, PUT, and DELETE. Only the relative path portion of the URL is considered relevant.
All payload data is transferred in 8-bit format; uploaded data must conform to this as well. No URL-encoded payload allowed, regardless of Content-Type. Bad. Outside!
Options are
parsed a la structural get_opts(3).
-d level
Set debug level to level. level is calculated by the ORing of debug flags, as follows:
0x1 DEBUG_ACCESS |
Access logging | ||
0x2 DEBUG_INFO |
Informational data | ||
0x4 DEBUG_NOISE |
Lots of debugging noise | ||
0x8 DEBUG_PRIVATE |
Includes private data such as passwords |
For informational and access log data, for example, the option -d 3 could be used, or to log everything while debugging your installation, -d 0xf.
-a |
(toggle) Atomic writes. Files will be uploaded with an appendage of .XXXXXX, where X is replaced as specified in mkstemp(3). When a file is fully uploaded, the temporary file is moved into place, and any previously existing file is removed implicitly; this is an atomic operation. If the file cannot be fully uploaded or cannot be moved into place, the temporary file is removed. |
filthttp can tell whether the file has been fully uploaded because the Content-Length specifier is required for uploads. If the system crashes or if filthttp is killed during an atomic upload, the temporary file will dangle until it is cleaned up by the user.
-I |
(toggle) Generate an index page when the GET request specifies a directory as its location. | ||
-p |
(toggle) Create the full path for uploaded files if it does not exist. Without this option, an upload request to a nonexistent directory will result in a ‘403 forbidden’ response. |
-m mode
The default mode used for creating files (mode & ~umask). Currently has no effect for atomic uploads, since mkstemp(3) has no facility for passing mode. mode is an octal integer, and should be passed with a leading 0 on the command line. Default is 0660.
-U user
Blacklist the specified user from access to the service. See Access Resolution, below. This option may be given multiple times to blacklist multiple users.
-u user
Whitelist the specified user, to allow access to the service. See Access Resolution, below. This option may be given multiple times to whitelist multiple users.
-G group
Blacklist members of the specified group from access to the service. See Access Resolution, below. This option may be given multiple times to blacklist multiple groups.
-g group
Whitelist members of the specified group, to allow access to the service. See Access Resolution, below. This option may be given multiple times to whitelist multiple groups.
-r |
(toggle) Disable read access (except directory listings if -I is set). Attmepts to read will result in ‘403 forbidden’ responses (if a file does not exist, ‘404 not found’ will still be returned). | ||
-w |
(toggle) Disable write access, including PUT, POST, and DELETE requests. Attempts to write will result in ‘403 forbidden’ responses. | ||
-S |
(toggle) Advertise the session ID (currently the PID of the process) in user responses. This has information leakage implications, but can assist with user support. |
XXX: Currently unimplemented.
-P |
(toggle) Use PAM instead of Unix authentication. Only available if PAM support is compiled in. |
XXX: Currently unimplemented.
-R realm
Use realm as the realm (i.e., the prompt) for HTTP Basic Auth. Default is access.
Access
Resolution
Users are denied by default. With no options given, no users
will be able to access the service. Once a user has been
successfully authenticated, authorization checks are
prioritized as follows:
1. user is
explicitly blacklisted (deny)
2. user is explicitly whitelisted (allow)
3. user is a member of a group that is blacklisted (deny)
4. user is a member of a group that is whitelisted (allow)
5. default action (deny)
Authorization is resolved the instant the user is matched against a rule.
RFC
compliance
Only a small subset of RFC 1945 (HTTP 1.0) and RFC 2068
(HTTP 1.1) are implemented, which means filthttp is
not really RFC-compliant as a web server (certain things
must be implemented, but aren’t). However, that
which it does implement, it attempts to implement in full
compliance with both specs. The portions it does not
implement should not affect general use.
One inconsistency to note is that the protocol version is not parsed pre-authentication, so filthttp doesn’t even know whether the protocol information is valid before it parses authentication headers and verifies the user. Error responses are therefore statically assumed to use protocol 1.0. This should not cause any problems and has been deemed an acceptable compromise by the author.
Running the
Service
Sample stunnel.conf for running the service over
HTTPS (port 443 in this case):
[filthttp]
accept = 443
exec = /usr/sbin/filthttp
execargs = filthttp -g xfer -I -p
Command line for running the service over HTTP using tcpserver, with atomic writes enabled, and logging to the /var/log/xferlog multilog logging directory:
tcpserver 0
8080 \
/usr/sbin/filthttp -g users -G noxfer -a -p 2>&1 \
|multilog /var/log/xferlog
Accessing
with Clients
Web browsers may, of course act as clients, and directory
indices are generated in HTML format (yet are easily
parsable using awk or sed). Command-line
clients, however, such as curl and wget, are
recommended over browsers, as they are generally more
flexible and scriptable.
To retrieve a file using wget, you might try the following:
wget --user=bob --password=stuff https://host:8443/path/file.zip
Or using curl:
curl -u bob -f -O https://host:8443/path/file.zip
To upload a file using wget, to the /some/path directory (which will be created if it doesn’t exist and -p has been passed on the server command line):
wget --user=bob
--password=stuff -O - --post-file=file.zip \
https://host:8443/some/path/file.zip
curl:
curl -u bob -f -T file.zip https://host:8443/some/path/file.zip
Note that using curl --data-binary @file.zip is broken and should not be used. It will work acceptably for small files, but it loads the entire file into memory before sending, which is inefficient and will break for larger files. curl -T uses the PUT method, which is accepted by filthttp.
To delete the file and its subdirectories (if empty), you might use:
curl -u bob -f
-X DELETE \
https://host:8443/some/path/file.zip \
https://host:8443/some/path \
https://host:8443/some
get_opts(3), stunnel(8), curl(1), wget(1)