pure-ftpd with mysql back end howto

OS Used: Gentoo, Mandriva 2007, openSUSE 11.0
First written: June 2007
Last updated: September 2008

 
 

While this howto has been aimed at Gentoo users, I have however used this same setup on both Mandriva and OpenSUSE Installations.

*  net-ftp/pure-ftpd
      Latest version available: 1.0.21-r1
      Latest version installed: [ Not Installed ]
      Size of files: 464 kB
      Homepage:      http://www.pureftpd.org/
      Description:   Fast, production-quality, standard-conformant FTP server.
      License:       BSD

 

Install pure-ftpd with MySQL and SSL support.

server ~ # echo "net-ftp/pure-ftpd mysql ssl" >> /etc/portage/package.use
server ~ # emerge -D net-ftp/pure-ftpd

 

Create users and group for file access

server ~ # groupadd -g 4400 ftpgroup
server ~ # adduser -u 4401 -d /home/ftpROOT -s /bin/false -g ftpgroup ftpread
server ~ # adduser -u 4402 -d /home/ftpROOT -s /bin/false -g ftpgroup ftpwrite
server ~ # mkdir /home/ftpROOT
server ~ # chown ftpwrite: /home/ftpROOT
server ~ # chmod 750 /home/ftpROOT

 

Create MySQL database. (You can just copy and paste the below into the mysql command prompt. Be sure to change the password though.)

CREATE DATABASE ftp;

USE ftp;

CREATE TABLE users (
  User VARCHAR(64) BINARY NOT NULL,
  Password VARCHAR(256) BINARY NOT NULL,
  Uid INT(11) NOT NULL default '4401',
  Gid INT(11) NOT NULL default '4400',
  Dir VARCHAR(256) BINARY NOT NULL default '/home/ftpROOT',
  PRIMARY KEY  (User)
);

GRANT SELECT, INSERT, UPDATE ON ftp.* TO 'pure-ftp'@'localhost' IDENTIFIED BY 'P@$$w0rD!' ;

FLUSH PRIVILEGES;

 

Once the database is setup, insert some user accounts for testing.

INSERT INTO `ftp`.`users` (`User` ,`Password` ,`Uid` ,`Gid` ,`Dir`)
VALUES ('upload', ENCRYPT( 'upload' ) , '4402', '4400', '/home/ftpROOT');

INSERT INTO `ftp`.`users` (`User` ,`Password` ,`Uid` ,`Gid` ,`Dir`)
VALUES ('download', ENCRYPT( 'download' ) , '4401', '4400', '/home/ftpROOT');

 

Now edit your Pure-FTPd config file to look something like this.

# Config file for /etc/init.d/pure-ftpd
##Comment variables out to disable its features, or change the values in it... ##

## This variable must be uncommented in order for the server to start ##
IS_CONFIGURED="yes"

## FTP Server,Port (separated by comma) ##
## If you prefer host names over IP addresses, it's your choice:
SERVER="-S ftp.uplinkzero.com,21"
## IPv6 addresses are supported.
## !!! WARNING !!!
## Using an invalid IP will result in the server not starting,
## but reporting a correct start!
## SERVER="-S 192.168.0.1,21"
## By default binds to all available IPs.
SERVER="-S 21"

## Number of simultaneous connections in total, and per IP ##
MAX_CONN="-c 30"
MAX_CONN_IP="-C 10"

## Start daemonized in background ##
DAEMON="-B"

## Don't allow uploads if the partition is more full then this var ##
DISK_FULL="-k 90%"

## If your FTP server is behind a NAT box, uncomment this ##
#USE_NAT="-N"

## Authentication mechanisms (others are 'pam', ...) ##
## Further infos can be found in the README file.
AUTH="-l mysql:/etc/conf.d/pure-ftpd-mysql"

## Change the maximum idle time (in minutes) ##
## If this variable is not defined, it will default to 15 minutes.
TIMEOUT="-I 10'"

## Facility used for syslog logging ##
## If this variable is not defined, it will default to the 'ftp' facility.
## Logging can be disabled with '-f none'.
LOG="-f ftp"

## Charset conversion support *experimental* ##
## Only works if USE "charconv" is enabled (only Pure-FTPd >=1.0.21).
## Set the charset of the filesystem.
# CHARCONV="--fscharset "

## If you want to process each file uploaded through Pure-FTPd, enter the name
## of the script that should process the files below.
## man pure-uploadscript to learn more about how to write this script.
# UPLOADSCRIPT="/path/to/uploadscript"

## Misc. Others ##
MISC_OTHER="-A -E -i -R -Z"

#
# Use these inside $MISC_OTHER
# More can be found on "http://download.pureftpd.org/pub/pure-ftpd/doc/README"
#
# -A [ chroot() everyone, but root ]
# -e [ Only allow anonymous users ]
# -E [ Only allow authenticated users. Anonymous logins are prohibited. ]
# -i [ Disallow upload for anonymous users, whatever directory perms are ]
# -j [ If the home directory of a user doesn't exist, auto-create it ]
# -M [ Allow anonymous users to create directories. ]
# -R [ Disallow users (even non-anonymous ones) usage of the CHMOD command ]
# -x [ In  normal  operation mode, authenticated users can read/write
#       files beginning with a dot ('.'). Anonymous users can't, for security reasons
#       (like changing banners or a forgotten .rhosts). When '-x' is used, authenticated
#       users can download dot-files, but not overwrite/create  them,  even  if they own
#       them. ]
# -X [ This  flag  is  identical  to  the  previous one (writing
#       dot-files is prohibited), but in addition, users can't even *read* files and
#       directories beginning with a dot (like "cd .ssh"). ]
# -D [ List files beginning with a dot ('.') even when the client doesn't
#      append the '-a' option to the list command. A workaround for badly
#      configured FTP clients. ]
# -G [ Disallow renaming. ]
# -d [ Send various debugging messages to the syslog. ONLY for DEBUG ]
# -F  [ Display a fortune cookie on login. Check the README file ]
# -H [ By default, fully-qualified host names are logged. The '-H' flag avoids host names resolution. ]

 

Now create the MySQL config file defined in the main config file above.

# Sample Pure-FTPd Mysql configuration file. #
# See README.MySQL for explanations.         #

# Optional : MySQL server name or IP. Don't define this for unix sockets.
MYSQLServer     localhost

# Optional : MySQL port. Don't define this if a local unix socket is used.
MYSQLPort       3306

# Optional : define the location of mysql.sock if the server runs on this host.
# MYSQLSocket     /tmp/mysql.sock

# Mandatory : user to bind the server as.
MYSQLUser       pure-ftp

# Mandatory : user password. You must have a password.
MYSQLPassword   P@$$w0rD!

# Mandatory : database to open.
MYSQLDatabase   ftp

# Mandatory : how passwords are stored
# Valid values are : "cleartext", "crypt", "md5" and "password"
# ("password" = MySQL password() function)
# You can also use "any" to try "crypt", "md5" *and* "password"
MYSQLCrypt      crypt

# In the following directives, parts of the strings are replaced at
# run-time before performing queries :
#
# \L is replaced by the login of the user trying to authenticate.
# \I is replaced by the IP address the user connected to.
# \P is replaced by the port number the user connected to.
# \R is replaced by the IP address the user connected from.
# \D is replaced by the remote IP address, as a long decimal number.
#
# Very complex queries can be performed using these substitution strings,
# especially for virtual hosting.

# Query to execute in order to fetch the password
MYSQLGetPW      SELECT Password FROM users WHERE User="\L"

# Query to execute in order to fetch the system user name or uid
MYSQLGetUID     SELECT Uid FROM users WHERE User="\L"

# Optional : default UID - if set this overrides MYSQLGetUID
# MYSQLDefaultUID 4401

# Query to execute in order to fetch the system user group or gid
MYSQLGetGID     SELECT Gid FROM users WHERE User="\L"

# Optional : default GID - if set this overrides MYSQLGetGID
# MYSQLDefaultGID 4400

# Query to execute in order to fetch the home directory
MYSQLGetDir     SELECT Dir FROM users WHERE User="\L"

# Optional : query to get the maximal number of files 
# Pure-FTPd must have been compiled with virtual quotas support.
# MySQLGetQTAFS  SELECT QuotaFiles FROM users WHERE User="\L"

# Optional : query to get the maximal disk usage (virtual quotas)
# The number should be in Megabytes.
# Pure-FTPd must have been compiled with virtual quotas support.
# MySQLGetQTASZ  SELECT QuotaSize FROM users WHERE User="\L"

# Optional : ratios. The server has to be compiled with ratio support.
# MySQLGetRatioUL SELECT ULRatio FROM users WHERE User="\L"
# MySQLGetRatioDL SELECT DLRatio FROM users WHERE User="\L"

# Optional : bandwidth throttling.
# The server has to be compiled with throttling support.
# Values are in KB/s .
# MySQLGetBandwidthUL SELECT ULBandwidth FROM users WHERE User="\L"
# MySQLGetBandwidthDL SELECT DLBandwidth FROM users WHERE User="\L"

# Enable ~ expansion. NEVER ENABLE THIS BLINDLY UNLESS :
# 1) You know what you are doing.
# 2) Real and virtual users match.
# MySQLForceTildeExpansion 1


# If you upgraded your tables to transactionnal tables (Gemini,
# BerkeleyDB, Innobase...), you can enable SQL transactions to
# avoid races. Leave this commented if you are using the
# traditionnal MyIsam databases or old (< 3.23.x) MySQL versions.
# MySQLTransactions On

 

Now start pure-ftpd and test.
Login with upload and upload and make sure that you can create a directory.
Then login with download and download and make sure that you are unable to create or remove directories.

Users with the UID 4402 in the MySQL database get write access to the file system.
Users with the UID 4401 only get read access to the file system because the directory structure is owned by ftpwrite (UID 4402) and the group ftpgroup (UID 4400) of which both ftpwrite (UID 4402) and ftp read (UID 4401) are members.

 

server ~ # ftp localhost
Connected to localhost (127.0.0.1).
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 1 of 30 allowed.
220-Local time is now 11:50. Server port: 21.
220-This is a private system - No anonymous login
220 You will be disconnected after 10 minutes of inactivity.
Name (localhost:user): upload
500 This security scheme is not implemented
SSL not available
331 User upload OK. Password required
Password:
230-User upload has group access to:  ftpgroup
230 OK. Current restricted directory is /
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -l
200 PORT command successful
150 Connecting to port 39689
drwxr-x---    4 4402     ftpgroup       96 May 12 00:20 Debian
drwxr-x---    4 4402     ftpgroup       96 May 12 00:27 Gentoo
drwxr-x---    3 4402     ftpgroup       72 May 12 00:35 OpenOffice
226-Options: -l 
226 3 matches total
ftp> quit
221-Goodbye. You uploaded 0 and downloaded 0 kbytes.
221 Logout.