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