Hi,
I setup vsftpd because I needed a really secure FTP setup. Here is the how-to that came out of it. I also needed a way to mange it via ssh and I couldn't find anything on the net so I wrote this script. Hope someone else finds it useful.
Don H.
I setup vsftpd because I needed a really secure FTP setup. Here is the how-to that came out of it. I also needed a way to mange it via ssh and I couldn't find anything on the net so I wrote this script. Hope someone else finds it useful.
Don H.
Code:
#!/bin/bash # writen for vsftpd 2.06, MySQL 5, # Version 1.01 2008-10-30 by Don Hess # This script will provide a menu to manipulate the mysql database # and manage the files for all type of user administration. It is # intended that the server only need ftp and ssh open and you can secure # ssh to lock out IP address apon a certain number of failures. The mysql # should be setup similar to this how-to [url]http://www.howtoforge.com/vsftpd_mysql_debian_etch[/url] # with the addition of a description field in the db. chrootftploc=/storage/sharedfiles/ftp # ftp root directory vsftpduserconfloc=/etc/vsftpd_user_conf # location of user specific config override files vsftpduserconflocdef=$vsftpduserconfloc/default # location of default template for above vsftpsysuser=vsftpdvirtual # the system user that vsftpd runs under myuserlogin="" # mysql login this script will use myuserpass="" # "" "" "" db="vsftpd_db" # database used to store our information mysqlhost="localhost" # host computer for mysql server mysqlloginstr="" # used in sql queries instead of long string, set in getmysqllogin function mysqltables="username, LEFT(pass, 6) AS pass, description" #used inplace of * for SELECT statements so password display is shorter. # mysql syntax reference [url]http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-data-manipulation.html[/url] mainprompt() { USERINPUT=1 echo "-------------------------------" echo "vsftp mysql database utility" echo "" echo "1 Query user(s)" echo "2 Add new user" echo "3 Update user" echo "4 Delete user" echo "5 Change this scripts MySQL login" echo "6 Quit" echo "" echo -n "--> " read USERINPUT } hideechoing() { local stty_orig=`stty -g` # set the original stty state to variable stty -echo # turn off terminal echoing so we don't see password read hidinput; # read user input sanitizeinput "$hidinput" password; # sanitize input stty $stty_orig # put terminal back the way it was } sanitizeinput() { # $1 is input to be sanitized # $2 tells us which options to use to sanitize parm1=`echo "$1" | tr -d '[\000-\037][\041-\054]\057[\072-\077]\100[\133-\136]\140[\173-\176]' | tr -d '[:cntrl:]'`; # remove non-alpha characters using octets, [url]http://en.wikipedia.org/wiki/ASCII[/url] # only non-alpha characters allowed are space, underscore "_", hyphen "-", and period "." parm2="$2" case "$parm2" in username) UNIN=`echo $parm1 | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/^\(..............................\).*$/\1/'`;; # use sed to crop to 30 chars password) PASSIN=`echo $parm1 | tr -d '[:space:]' | sed 's/^\(..............................\).*$/\1/'`;; # use sed to crop to 30 chars description) DESCIN=`echo $parm1 | sed 's/^\(........................................\).*$/\1/'`;; # use sed to crop to 40 chars * ) echo -n "";; esac } getmysqllogin() { echo "You must enter the connection information for MySQL before continuing." echo -n "Enter MySQL username (case sensitive): "; read aa; myuserlogin=`echo "$aa"`; echo -n "Enter MySQL password (case sensitive): "; # this is a one-off hidding of password because we may need special chars local stty_orig=`stty -g` # set the original stty state to variable stty -echo # turn off terminal echoing so we don't see password read bb # read user input stty $stty_orig # put terminal back the way it was myuserpass=`echo "$bb"`; mysqlloginstr="--host=$mysqlhost --user="$myuserlogin" --password="$myuserpass" --database="$db"" #reset the login variable with new data echo ""; echo ""; echo "Username and password for MySQL set." echo Using MySQL host "'$mysqlhost'" with database "'$db'". } printusers() { # --skip-column-names removes coloumn headers # mysql --host=host_name --user=user_name --password=your_password --database=dbname -e "statement;" clear echo -n "Input at least part of the username or press [Enter] key to show all: "; read UNIN; sanitizeinput "$UNIN" username; if [ "$UNIN" = "" ]; then echo "" echo "First 1000 ftp users in database: " mysql $mysqlloginstr -e "SELECT $mysqltables FROM accounts a LIMIT 0,1000;" echo "Password field is truncated for display purposes only." else #search for similar names. echo "Here are the closes matches to '$UNIN' " mysql $mysqlloginstr -e "SELECT $mysqltables FROM accounts WHERE username LIKE '%$UNIN%';" echo "Password field is truncated for display purposes only." fi } adduser() { echo "" echo "Note you must have sudo privileges to add a user." # tell sanitize function how sanitize (username, password, etc, UNIN var is globalally available so we won't pass echo -n "Enter new ftp username (30 char max) [cancel]: "; read UNIN; sanitizeinput "$UNIN" username; echo "The username that will be used after sanitizing is '$UNIN'. " echo -n "Enter new ftp user's password (30 char max, only _ - . puncuation allowed): "; echo ""; hideechoing; # use hideechoing function echo -n "Enter user description (40 char max) [NULL]: "; read DESCIN; sanitizeinput "$DESCIN" description; if [ "$UNIN" = "" ]; then echo "OOPS, you didn't enter anything for a username." else if [ "$PASSIN" = "" ]; then echo "OOPS, you didn't enter anything for a password." else mysql $mysqlloginstr -e "INSERT INTO accounts (id, username, pass, description) VALUES(DEFAULT, '$UNIN', PASSWORD('$PASSIN'), '$DESCIN');" PASSIN=""; # clear password because we are done with it. # create user home directory? echo "" echo -n "Do you want to create a ftp home directory for the user? "; read YN; case "$YN" in [yY]) sudo mkdir "$chrootftploc/$UNIN"; sudo chown $vsftpsysuser:$vsftpsysuser "$chrootftploc/$UNIN"; sudo chmod 775 "$chrootftploc/$UNIN";; * ) echo -n "";; esac # copy the default file to username so we can configure them independently echo "" echo "Copying default user configuration to $vsftpduserconfloc/$UNIN " sudo cp "$vsftpduserconflocdef" "$vsftpduserconfloc/$UNIN" echo "" echo -n "Do you want to edit the $vsftpduserconfloc/$UNIN configuration file? [y/N]: "; read YN; case "$YN" in [yY]) sudo vi "$vsftpduserconfloc/$UNIN";; * ) echo -n "";; esac fi fi } updateuser() { echo -n "Enter ftp username to update: "; read UNIN; sanitizeinput "$UNIN" username; if [ "$UNIN" = "" ]; then echo "OOPS, you didn't enter anything." else #check if name is in db, if it is continue. If not search for similar names. UU=`mysql --skip-column-names $mysqlloginstr -e "SELECT username FROM accounts a WHERE username='$UNIN';"` if [ "$UNIN" = "$UU" ]; then echo -n "Do you want to update password for '$UNIN'? [y/N]: "; read YN; case "$YN" in [yY]) echo -n "Enter new password for '$UNIN' (30 char max, only _ - . puncuation allowed): "; echo ""; hideechoing; # use hideechoing function mysql $mysqlloginstr -e "UPDATE accounts SET pass=PASSWORD('$PASSIN') WHERE username='$UNIN';" PASSIN="";; # clear password because we are done with it. * ) echo -n "";; esac echo -n "Do you want to update description for '$UNIN'? [y/N]: "; read YN; case "$YN" in [yY]) echo -n "Enter new description for '$UNIN' (40 char max): "; read DESCIN; sanitizeinput "$DESCIN" description; mysql $mysqlloginstr -e "UPDATE accounts SET description='$DESCIN' WHERE username='$UNIN';" ;; * ) echo -n "";; esac else echo "" echo "FTP username '$UNIN' not in database." echo "but here are some names that are close: " mysql $mysqlloginstr -e "SELECT $mysqltables FROM accounts WHERE username LIKE '%$UNIN%';" fi fi } deleteuser() { echo "" echo "Note you must have sudo privileges to properly delete a user." echo -n "Input the username or part of the username to delete [cancel]: "; read UNIN; sanitizeinput "$UNIN" username; if [ "$UNIN" = "" ]; then echo "OOPS, you didn't enter anything." else #check if name is in db, if it is delete. If not, search for similar names. UU=`mysql --skip-column-names $mysqlloginstr -e "SELECT username FROM accounts WHERE username='$UNIN';"` if [ "$UNIN" = "$UU" ]; then echo -n "Are you sure you want to delete user '$UNIN'? [y/N]: "; read YN; case "$YN" in [yY]) mysql $mysqlloginstr -e "DELETE FROM accounts WHERE username='$UNIN';" sudo rm "$vsftpduserconfloc/$UNIN"; # delete user specific config file if [ -e "$chrootftploc/$UNIN" ]; then # check if user has a ftp root folder created for them echo -n "Are you sure you want to delete the folder $chrootftploc/$UNIN? [y/N]: "; read YN; case "$YN" in [yY]) sudo rm -r "$chrootftploc/$UNIN";; # delete users ftp root folder * ) echo "";; esac else echo "Username '$UNIN' deleted" fi echo "Username '$UNIN' deleted";; * ) echo ""; echo -n "User '$UNIN' kept safe";; esac else echo "" echo "The FTP username '$UNIN' not in database " echo "but here are some names that are close: " mysql $mysqlloginstr -e "SELECT $mysqltables FROM accounts WHERE username LIKE '%$UNIN%';" fi fi } clear getmysqllogin; mainprompt; while [ "$USERINPUT" != "6" ] do case "$USERINPUT" in "1") printusers;; "2") adduser;; "3") updateuser;; "4") deleteuser;; "5") getmysqllogin;; "6") echo "Good Bye";; * ) clear echo "Please select a number";; esac echo "" echo "" mainprompt; done
Comment