====== Pure-FTPd with MySQL ====== This is how I setup my ftp server with Pure-FTPd and MySQL as backend for authentication and user profiles and sOLARiZ PureFTPd Manager as interface to MySQL. ===== Pure-FTPd Setup ===== Install Pure-FTPd the way you like it. As I use SuSE 9.3 I use the version bundled with the distribution and hence use the "SuSE Standard" for file locations. Start out by editing the ///etc/pure-ftpd/pure-ftpd.conf// file to make use of MySQL as backend. Mine looks like this: ChrootEveryone yes BrokenClientsCompatibility no MaxClientsNumber 10 Daemonize yes MaxClientsPerIP 3 VerboseLog no AllowDotFiles yes DisplayDotFiles yes AnonymousOnly no NoAnonymous yes SyslogFacility ftp DontResolve yes MaxIdleTime 15 MySQLConfigFile /etc/pure-ftpd/pureftpd-mysql.conf LimitRecursion 2000 8 AnonymousCanCreateDirs no MaxLoad 4 Umask 177:077 MinUID 100 AllowUserFXP no AllowAnonymousFXP no ProhibitDotFilesWrite no ProhibitDotFilesRead no AutoRename yes AnonymousCantUpload yes NoChmod yes CreateHomeDir yes MaxDiskUsage 99 NoRename yes CustomerProof yes Lets create ///etc/pure-ftpd/pureftpd-mysql.conf//: MYSQLServer localhost MYSQLPort 3306 MYSQLUser ftpd MYSQLPassword 123456 MYSQLDatabase System MYSQLCrypt md5 MYSQLGetPW SELECT Password FROM ftpd WHERE User="\L" AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") MYSQLGetUID SELECT Uid FROM ftpd WHERE User="\L" AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") MYSQLGetGID SELECT Gid FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") MYSQLGetDir SELECT Dir FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") MySQLGetBandwidthUL SELECT ULBandwidth FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") MySQLGetBandwidthDL SELECT DLBandwidth FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") MySQLGetQTASZ SELECT QuotaSize FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") MySQLGetQTAFS SELECT QuotaFiles FROM ftpd WHERE User="\L"AND status="1" AND (ipaccess = "*" OR ipaccess LIKE "\R") ===== MySQL ===== Install MySQL on a server or use a already installed one. Again I use the one following SuSE 9.3. I use a thirdparty PHP interface to the MySQL database called [[http://www.solariz.de/|sOLARiZ PureFTPd Manager]], so I also have Apache2 with PHP and PHP-mysql installed. You can also download it here {{:howtos:pureftp-mgr.tar|pureftp-mgr.tar}} You can configure the MySQL database in many ways and make use of a lot of Pure-FTPd's features, but as I'm using PureFTPd Manager I'm bound to its design. Create a database: # mysqladmin -u root -p create System Next make the following file called //create.sql//: DROP TABLE IF EXISTS ftpd; CREATE TABLE ftpd ( User varchar(16) NOT NULL default '', status enum('0','1') NOT NULL default '0', Password varchar(64) NOT NULL default '', Uid varchar(11) NOT NULL default '-1', Gid varchar(11) NOT NULL default '-1', Dir varchar(128) NOT NULL default '', ULBandwidth smallint(5) NOT NULL default '0', DLBandwidth smallint(5) NOT NULL default '0', comment tinytext NOT NULL, ipaccess varchar(15) NOT NULL default '*', QuotaSize smallint(5) NOT NULL default '0', QuotaFiles int(11) NOT NULL default 0, PRIMARY KEY (User), UNIQUE KEY User (User) ) TYPE=MyISAM; Use this file to create the our user table: # mysql -u root -p System < create.sql Use this file, //create-user.sql//, to create the ftpd user and its rights: USE mysql; INSERT INTO user (Host, User, Password) VALUES ('localhost','ftpd',password('123456')); INSERT INTO db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv) VALUES ('localhost', 'System', 'ftpd', 'Y', 'Y', 'Y', 'Y'); FLUSH PRIVILEGES; GRANT SELECT, INSERT, DELETE, UPDATE ON System.* TO ftpd@localhost; Now run it: # mysql -u root -p -h localhost < create-ftpd.sql ===== Apache2 ===== Now copy the sOLARiZ PureFTPd Manager files into your documentroot somewhere. As we are dealing with usernames and passwords I like to use https. With SuSE 9.3 the tool //gensslcert// will make the certificate for you. If you aren't using SuSE, look at the manpages for openssl. To make use of this I have created ///etc/apache2/vhosts.d/pureftpd.conf//: Listen 666 DocumentRoot "/srv/www/htdocs/pureftpd" ServerName localhost:666 ServerAdmin you@example.com ErrorLog /var/log/apache2/pureftpd_error_log TransferLog /var/log/apache2/pureftpd_access_log SSLEngine on SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL SSLCertificateFile /etc/apache2/ssl.crt/server.crt SSLCertificateKeyFile /etc/apache2/ssl.key/server.key SSLOptions +StdEnvVars SSLRequireSSL SetEnvIf User-Agent ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 CustomLog /var/log/apache2/postfixadmin_request_log \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" AllowOverride AuthConfig Order deny,allow Allow from all This creates an https webinterface listening on port 666/tcp. To enter this interface you browse to https://yourserver:666 I would like to be the only one accessing this interface and therfor we need some authentication. Create .htaccess in the documentroot /srv/www/htdocs/pureftpd/: AuthUserFile /srv/www/htdocs/pureftpd/.htpasswd AuthGroupFile /dev/null AuthName "Pure-ftpd Admin" AuthType Basic require valid-user Create the htpasswd file and create a admin user: # htpasswd2 -c /srv/www/htdocs/pureftpd/.htpasswd admin ===== PureFTPd Manager ===== Create a user and group called "//pureftpd//". Extract the PureFTPd Manager files into "///srv/www/htdocs/pureftpd//". To make use of md5 instead of crypt I changed "//index.php//" to: $PUREFTP_CONFIG_FILE"); $USERARRAY = array(); $raw = file($PUREFTP_CONFIG_FILE); foreach($raw AS $zeile): if(!ereg("^#",$zeile)): #skip comments // Einlesen der einzelnen Zeilen als Variable $tmp = split(" ",trim($zeile)); // UNIX Tab workaround if(count($tmp) < 2) $tmp = explode("\t",trim($zeile)); $var = strtoupper(trim($tmp[0])); for($n=1;$n".mysql_error()); echo '
'; if(!empty($user)) echo ''; else echo ''; echo ''; echo ''; echo ''; if(!empty($user)) { echo ''; echo ''; } else echo ''; echo ''; echo ''; // UA if ($PW) { echo ''; } else { echo ''; } echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; // UA echo ''; // UA echo ''; echo ''; echo '
Status Inactive    Active
Delete user ? Yes, i am know exactly what i am doing! (NO UNDO)
Username'.stripslashes($USERARRAY['User']).'
Username
Password
UID
GID
DIR
UL Throttle kb/s
DL Throttle kb/s
IP ACCESS
Type in * for any IP
QuotaSize in MB
Type in 0 for NO VirtualQuotaSize
QuotaFiles Anzahl
Type in 0 for NO VirtualQuotaFiles
COMMENT
'; echo '
'; }#end edit elseif($action == "save") { $addnew = addslashes( get_var("addnew") ); $User = addslashes(get_var("requireduser")); // UA - MG Optimized ;) $Password = addslashes(get_var("requiredpass")); IF($Password == '') $Password = ''; ELSEif($PW) $Password = md5($Password); $Uid = addslashes(get_var("requireduid")); $Gid = addslashes(get_var("requiredgid")); $Dir = addslashes(get_var("requireddir")); $ULThrottle = addslashes(get_var("requiredulthrottle")); $DLThrottle = addslashes(get_var("requireddlthrottle")); $QuotaSize = addslashes(get_var("requiredQuotaSize")); // UA $QuotaFiles = addslashes(get_var("requiredQuotaFiles")); $comment = addslashes(get_var("comment")); $status = addslashes(get_var("status")); $delete = addslashes(get_var("delete")); $ipaccess = addslashes(get_var("requiredipaccess")); if(empty($User) || empty($Uid) || empty($Gid) || empty($Dir)) DIE("Invalid or missing data entered..."); if(empty($delete)) { // Mini workarounds if($Password) $PW_QUERY = ",Password='$Password'"; if(!$status) $status = (string) '0'; if(!$ULBandwidth) $ULBandwidth = (string) '0'; if(!$DLBandwidth) $DLBandwidth = (string) '0'; if(!$QuotaSize) $QuotaSize = (string) '0'; if(!$QuotaFiles) $QuotaFiles = (string) '0'; if($addnew == False) { $SQL = "UPDATE `$DB_TABLE` SET status='$status'".$PW_QUERY.",Uid='$Uid',Gid='$Gid',Dir='$Dir',ULBandwidth='$ULThrottle',DLBandwidth='$DLThrottle',comment='$comment',ipaccess='$ipaccess',QuotaSize='$QuotaSize',QuotaFiles='$QuotaFiles' WHERE User LIKE '$User' LIMIT 1"; $Q = DB_QUERY($SQL); if($Q) echo "\n"; }#end if else{ $Q = DB_QUERY("INSERT INTO `$DB_TABLE` SET User='$User',status='$status'".$PW_QUERY.",Uid='$Uid',Gid='$Gid',Dir='$Dir',ULBandwidth='$ULThrottle',DLBandwidth='$DLThrottle',comment='$comment',ipaccess='$ipaccess',QuotaSize='$QuotaSize',QuotaFiles='$QuotaFiles'"); if($Q) echo "\n"; }#end if }#end if elseif($User && !empty($delete)){#DELETE $Q = DB_QUERY("DELETE FROM `$DB_TABLE` WHERE User LIKE '$User' LIMIT 1"); if($Q) echo "\n"; }#end if echo "\n"; }#end else (save) ###### elseif($action == "ftpwho") { echo ''; exec($FTP_WHO." -s", $ftpresult ); $arraySize = sizeof($ftpresult); $x = 0; echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; $x++; EndWhile; echo '
PID'; echo 'user'; echo 'min\'s'; echo 'state'; echo 'file'; echo 'IP'; echo 'current'; echo 'total'; echo '%'; echo 'bw.'; while($x < $arraySize): $ftpwho = $ftpresult[$x]; list($pid, $user, $mins, $state, $file, $host, $port,$h, $current, $total, $percent, $bandwidth ) = explode("|", $ftpwho ); $mins = round($mins / 60); if (empty($file) or !isset($file)) { ( $file = "---" ); ++$ftp_activity; } else { if(strlen($file) > 10) $file_short = substr($file,0,10); $file = "$file_short..."; }#end else $host = gethostbyname($host); echo '
' .$pid. '' .$user. '' .$mins. '' .$state. '' .$file. '' .$host. '' .$current. '' .$total. '' .$percent. '' .$bandwidth. ' kb/s
'; if(!$ftp_activity) echo 'No users currenty using the FTP.
'; echo '

'; echo '
'; }#end else (ftpwho) ###### elseif($action == "info") { ?> sOLARiZ PureFTPd Manager
Version Build

About
    The first version of this Script was developed roughly at the end of 2001 in need of a simplyfied remote FTP administration. Since this many user submited changes / updates were integrated. If you got special wishes please let me know via mail.
    One thing to note; I don't take any guarantee either I'm not liable for possible caused damage. This script is free no need to pay for it. But if you like it im be glad for a donation. Everything is welcome e.g. a PayPAL donation:

    For Information or other stuff regarding pureFTPd Manager or other scripts please visit www.solariz.de
ChangeLog
    \n"; EndForEach; ?>
'; echo 'LOGIN'; if($viewpw) echo 'PASSWORD'; // UA echo 'UIDGIDDIRUL/ksDL/ksQuota SizeQuota FilesIP AccessStatus '; WHILE($R=MYSQL_FETCH_ARRAY($Q)) { echo ''; echo ''.$R['User'].''; if($viewpw) echo ''.$R['Password'].''; echo ''.$R['Uid'].''; echo ''.$R['Gid'].''; echo ''.$R['Dir'].''; if($R['ULBandwidth']) echo ''.$R['ULBandwidth'].''; ELSE echo '-'; if($R['DLBandwidth']) echo ''.$R['DLBandwidth'].''; ELSE echo '-'; if($R['QuotaSize']) echo ''.$R['QuotaSize'].' MB'; ELSE echo '-'; // UA if($R['QuotaFiles']) echo ''.$R['QuotaFiles'].''; ELSE echo '-'; echo ''.$R['ipaccess'].''; if($R['status'] == '0') echo 'inactive'; elseif($R['status'] == '1') echo 'active'; echo ""; echo "\n"; }#end while echo ''; ?> "; // Add User Button ECHO ""; // View Password Button echo ''; if($viewpw) echo ''; ELSE echo ''; ECHO ''; echo ''; // Status Button ECHO ""; // Update Button ECHO ""; echo "
PureFTP User Management.
v written by sOLARiZ
[Information]
 
"; ######## echo ''; }#end else // SQL Verbindung schliessen DB_CLOSE(); // Seite abschliessen PAGE_FOOTER(); // EOC <--* // Funktionen function PAGE_HEADER() { GLOBAL $VERSION, $BUILD; include("inc/top.php"); }#end func function PAGE_FOOTER() { include("inc/bottom.php"); }#end func function DB_OPEN() { GLOBAL $MYSQLSERVER,$MYSQLUSER,$MYSQLPASSWORD,$MYSQLDATABASE,$MYSQLCON; $MYSQLCON = @mysql_connect($MYSQLSERVER,$MYSQLUSER,$MYSQLPASSWORD); if(!$MYSQLCON OR @mysql_error()) DIE("Can't establish DB connection.
".mysql_error()); if(!@mysql_select_Db($MYSQLDATABASE)) DIE("Can't establish DB connection.
".mysql_error()); }#end func function DB_CLOSE() { GLOBAL $MYSQLCON; RETURN @mysql_close($MYSQLCON); }#end func function DB_QUERY($sql) { GLOBAL $MYSQLCON,$MYSQLDATABASE; $Q = @MySql_DB_query($MYSQLDATABASE,$sql,$MYSQLCON); if(@mysql_error()) DIE("MySQL Error during Query !

[$sql]
".mysql_error()); return $Q; }#end func function get_var($var){ GLOBAL $$var; GLOBAL $_POST,$_GET,$HTTP_POST_VAR,$HTTP_GET_VAR; $inhalt = $$var; # This function checks if the _GET or _POST var is set or if an old PHP version used if($_POST[$var]) RETURN $_POST[$var]; elseif($HTTP_POST_VAR[$var]) RETURN $HTTP_POST_VAR[$var]; elseif($_GET[$var]) RETURN $_GET[$var]; elseif($HTTP_GET_VAR[$var]) RETURN $HTTP_GET_VAR[$var]; elseif($inhalt) RETURN $inhalt; }#end func ?>
My "//pureftp.config.php//" looks like this: This is basically it. Point your browser at //https://yourwebserver:666//, login and start sharing diskspace :-P \\ An alternate Pure-Ftpd GUI can be found at http://machiel.generaal.net/index.php?subject=user_manager_pureftpd.