Improved Jailed SFTP Creator for Web Server

So I decided to give this idea an overhaul after I was asked to find a way to create these accounts from PHP in the web server

I definitely would not go as far to say that I regard myself as a programmer, so there are probably things I’ve done in the script below that would make a veteran programmer cringe, but this is a massive improvement from the way it was as well as it really only being designed for my own usage.

The other new main requirement is that Apache can write to the new user’s SFTP directory so they can upload data, and get reporting on their services.

Because of security concerns it was decided that it wouldn’t be wise to allow a PHP script to be executing shell commands from the web server as root no matter how we went about it so the idea for the changes here are in relation to the next version creating a cron job to run the shell commands independently.

So the idea here is that there is a PHP script that when required will generate a simple file with the new username and password, and there will be a cron job running every few minutes looking for that file.

If there is the request to add a public key, this will search for it and add it as well.

It also generates an output file which contains the information for the new account, along with the bottom 5 lines of /var/log/secure to confirm that the permissions were applied correctly.

As said in previous post on the matter you must have your sshd_config setup as so:

Prerequisites:

OpenSSH 5 (I had to upgrade OpenSSH manually because CentOS 5 natively supports a previous version that wouldn’t suffice for this purpose). 

…if by chance you need to do the same on CentOS or another RPM distro that has the same limitation, follow the installation instructions in this guide:

Installing OpenSSH 5 in CentOS 5

Add group SFTP:

In the script below I added, but haven’t yet tested a few lines which checks to see if group exists and creates it but it’s not enabled by default. Otherwise simply run this command.

# groupadd sftponly


Configuring:

Locate your sshd_config file and open with your desired text editor.

Locate out the following line and comment out with a # if not already done so:

# Subsystem sftp /usr/libexec/openssh/sftp-server

Scroll down and append the following to the end:


Subsystem sftp internal-sftp         

Match Group sftponly         

ChrootDirectory  /home/%u         

ForceCommand internal-sftp         

AllowTcpForwarding no

The script:

Change the paths for  lusername, pubkey & output file

#!/bin/bash
## Creates user and necessary SFTP directory permissions
## Refined Version 16th June 2014 --Chris. Tested CentOS 5+6
## Change file paths edit in getPaths function to suit:
## *lusername:
## *pubkey:
## *outputFilePath:
## Note: Pre-Configuration for group sftponly in sshd_config
## for SFTP is necessary.
isRoot() {
    # Check if the current user is root or not !
    if [ $EUID = 0 ]; then
        return 0
    else
        return 1
    fi
}
getPaths() {
    lusername="/var/www/html/newsftp"
    outputFilePath="/home/admin/"
    pubkey="/var/www/html/newsftpkey"
    hostName=$(hostname)
}
findUsername() {
##path to user data file in format <username> <password>

    findUserPass=$(find $lusername)
    if [[ $findUserPass == $lusername ]]
    then
            echo "found username file"
    else
            echo "no username file match" && exit
    fi
}
checkSFTPonly() {
    mksftpGrp=$(cat /etc/group | grep sftponly | sed s/:/" "/g | awk '{print $1}')
    mksftpTrue=$(echo "sftponly")
    if [[ $mksftpGrp == $mksftpTrue ]]; then
        echo "group exists!"; else
        echo "group doesn't exist!"; /usr/sbin/groupadd sftponly;
        echo "group sftponly created"; fi
}

outputKeys() {
    outputFile="$outputFilePath"/"$user"_sftp
    echo "Your SFTP account details are: " >> $outputFile
    echo "Username: "$user"" >> $outputFile
    echo "Password: "$pass"" >> $outputFile
    echo "Directory for files: /sftp" >> $outputFile
    echo "Port: 222" >>  $outputFile
    echo "Example: sftp -oPort=222 "$user"@"$hostName":/sftp" >> $outputFile
    echo "Looking for public key in path "$pubkey""

    ##If pubkey is found at path it adds to .ssh/authorized_keys
    findPubkey=$(find "$pubkey")
    if [[ $findPubkey == $pubkey ]]
    then
            echo "pubkey found - adding to authorized_keys..";
            cat $pubkey  >> "/home/"$user"/.ssh/authorized_keys";
    else
            echo "pubkey not found - you will have to add manually" | tee -a $outputFile; exit
    fi
    ##Adds lines spacing to Account Info Output
    echo -e "Public key added to authorized_keys: " >> $outputFile;
    sed -i '0~1 a\ ' $outputFile;
    echo -e "$pub \n" >> $outputFile;
    echo -e "Log output to confirm\debug: \n"

    ##Copies Secure Log output lines CentOS\RHEL only!
    tail -5 /var/log/secure | tee -a $outputFile;
    echo -e "\n Account info can be found at $outputFile";
    mv $lusername /home/admin/sftp_"$user"
    mv $pubkey /home/admin/"$user"_key

}

assignUserPass() {
    pub=$(cat $pubkey)
    echo $pub
    ##Get user and pass variables
    getUserPass=$(cat "$lusername")
    user=$(echo $getUserPass | awk '{ print $1 }')
    pass=$(echo $getUserPass | awk '{ print $2 }')
    echo $user $pass
    ##Add user
    echo "creating account for "$user"..."
    /usr/sbin/useradd -m "$user" -p "$pass"
    ##Add to group 'sftponly'
    /usr/sbin/usermod -G sftponly $user
    ##Strip account of shell priv.
    /usr/sbin/usermod -s /bin/false $user
    ##Change owner ~/ directory to root
    chown root:root /home/$user
    ##Jail the user folder
    chmod 755 /home/$user/
    chmod 755 /home/$user
    ##Create directory for file transfers
    mkdir /home/$user/sftp
    echo "/home/"$user"/sftp directory created"
    ##Give user ownership sftponly group ownership
    chown $user:sftponly /home/$user/sftp
    ##Allow sftponly group to write and enable Apache to write to directory
    /usr/sbin/usermod -aG apache sftponly
    chmod g+w /home/$user/sftp
    ##Make and lock down .ssh directory & authorised keys file
    mkdir /home/$user/.ssh/
    touch /home/$user/.ssh/authorized_keys
    chown $user:$user /home/$user/.ssh
    chmod 700 /home/$user/.ssh/
    chmod 700 /home/$user/.ssh
    chown $user:$user /home/$user/.ssh/authorized_keys
    chmod 600 /home/$user/.ssh/authorized_keys
}

if [ isRoot = 0 ];
then
    echo "Not root. Exiting.." && exit
else
	    getPaths;findUsername;checkSFTPonly;assignUserPass;outputKeys
fi