Friday, June 24

phpNuke FTP user uploads

Together with some friends I run a small website that uses the phpNuke CMS-system. Our uses have been asking for a way to upload image to a FTP-site to be able to publish articles with images on the web site. All user logins must be authenticated through an existing MySQL schema and since MySQL sucks and the version we use doesn't support views the FTPd must allow user defined queries for all operations. I've been thinking on a way to do this for quite some time and finally came up with this solution. I'm a ProFTPD monkey at heart but in this scenario I had to use PureFTPD due to some SQL-limitation in ProFTPD. This solution should work with a phpBB database as well and should be easily adaptable for other systems.

PureFTPD installation.
$ wget ftp://ftp.pureftpd.org/pub/pure-ftpd/releases/
pure-ftpd-1.0.20.tar.bz2
$ tar xjf pure-ftpd-1.0.20.tar.bz2
$ ./configure --prefix=/usr/local/pureftpd --with-mysql
$ make
$ make install
$ groupadd -g 800 nukeftp
$ useradd -u 800 -g nukeftp -d /u01/user_uploads nukeftp
Create a MySQL config file and save it as /etc/pureftpd-mysql.conf.
I created a new MySQL user and granted it select privs to the nuke database (although using the same user as the web site also works fine). I also choose to use one single UID/GID for all uploads, there is really no need for anything else since all users are chrooted to their home and since we don't have real home directories in the DB I just did a fake select from nothing (same as DUAL in Oracle) using the \L (login name) macro.
This is what I used.

Example:
MYSQLSocket     /var/lib/mysql/mysql.sock
MYSQLUser username
MYSQLPassword password
MYSQLDatabase nukedb
MYSQLCrypt md5
MYSQLGetPW select user_password FROM nuke_users WHERE UserName='\L'
MYSQLDefaultUID 800
MYSQLDefaultGID 800
MYSQLGetDir SELECT '/u01/user_uploads/\L'
Apache configuration
Recommended reading: Apache 2.0 docs
SetEnvIfNoCase Referer "^http://www.mysite/" local=1
SetEnvIfNoCase Referer "^-" local=1
SetEnvIfNoCase Referer "^$" local=1
[ Stop hot-linking to picture from outside your site, you may
want to add google/yahoo/msn etc. to this list to allow searches
to hit your image archive. ]


ReadmeName README.html
HeaderName HEADER.html
[ Allow users to have descriptions of their image archives. ]
Alias /uploads/ "/u01/user_uploads"
< Directory "/u01/user_uploads">
AllowOverride AuthConfig Limit
Options +Indexes
Order allow,deny
Allow from env=local
< /Directory>
Start PureFTPD
One really annoying thing with PureFTPD is that it doesn't have a propper configuration file, there is some lame perl wrapper that can parse a text file and provide the command line arguments. PureFTPD will also create any user home directories that does not exist. Specify the IP to listen on with the -S option.
I choose do it manually anyway (./pure-ftpd -h to see all options).
Start PureFTPD with this command (don't forget to put this in a init file somewhere):
$ /usr/local/pureftpd/sbin/pure-ftpd -B -fftp -H -A -lmysql:/etc/pureftpd-mysql.conf -m4 -s -S10.0.0.1,21 -j -p55000:60000 -I300 -d

Finished! Go test it out!

No comments: