After jumping to a custom build after backfire RC5, i.e (10.03.1-RC6, r27794) I needed to configure again my Samba3 server.
Since I put a new bigger flash drive (16GB) as external storage I wanted to build a little more complex samba environment with separate users and storage for every user, adding a proper permissions and a good security level, giving the users the ability to share between each other, but in the same time allowing them to put some data in a private directories that could not be accessed by anyone else except them.
The main idea of the script is to easily add or remove a user to the samba server, configuring the proper user entries on the device and adding the user share directories and applying the correct user permissions.
Here I have two partitions, as I decided to give the users a separate partition, thus limiting then from eating the whole storage (I am not familiar with quotas, etc. in Samba, would appreciate if someone share some stuff about it).
I am using a Samba administration user account (smbadmin) and a separate user group for all samba users (smbusers), these may be easily altered in the script according to individual needs.
root@OpenWrt:~# df -m
Filesystem 1M-blocks Used Available Use% Mounted on
/dev/root 6 6 0 100% /rom
tmpfs 14 0 14 2% /tmp
tmpfs 1 0 1 0% /dev
/dev/sda1 610 26 553 4% /overlay
mini_fo:/overlay 6 6 0 100% /
/dev/sda6 11425 429 10416 4% /mnt/storage
/dev/sda5 2884 68 2669 2% /mnt/storage/SHARE/users
root@OpenWrt:~# cat /etc/config/samba
config samba
option 'name' 'kanzownet-sofia'
option 'workgroup' 'kanzownet-sofia'
option 'description' 'Samba-Server'
option 'homes' '0'
config sambashare
option 'name' 'Admin'
option 'path' '/mnt/storage'
option 'read_only' 'no'
option 'guest_ok' 'no'
option 'create_mask' '0640'
option 'dir_mask' '0750'
option 'users' 'smbadmin'
config sambashare
option 'name' 'Storage'
option 'path' '/mnt/storage/SHARE'
option 'read_only' 'no'
option 'guest_ok' 'yes'
option 'create_mask' '0640'
option 'dir_mask' '0750'
#option 'users' 'abc'
As you can see I have two separate Samba shares, since the first one is used by the Samba administrator to gain control over the whole share. The second one is purposed to be accessed by the individual users, as the whole directory tree is applied the proper user permissions, every user directory is accompanied with a Private folder (700 permissions) that could be accessed only by the particular user.
There are several variables set at the beginning of the script, where you can easily adapt the paths of the shares, as well as the usernames, etc., to your needs. I hope this one is helpful.
Here is the script itself. The bash package is highly recommended!
Copy -> Paste -> Save as "samba_users.sh" somewhere on your router -> make it executable (chmod +x samba_users.sh) -> run ./samba_users.sh -h
#!/bin/bash
#
#Script for Creating new Samba user and configuring parameters
SCRIPT_NAME="samba_users.sh"
#Defining variables:
OPTION="$1"
USER="$2"
SAMBA_SHARE_DIR="/mnt/storage/SHARE"
SAMBA_USER_DIR="/mnt/storage/SHARE/users/${USER}"
SAMBA_HOME="/var"
SAMBA_SHELL="/bin/false"
SAMBA_ADMIN="smbadmin"
SAMBA_GROUP="smbusers"
SAMBA_GROUP_ID="1001"
SAMBA_USER_ID_START="1001"
SAMBA_ADMIN_ENTRY="${SAMBA_ADMIN}:*:${SAMBA_USER_ID_START}:${SAMBA_GROUP_ID}:${SAMBA_GROUP}:${SAMBA_HOME}:${SAMBA_SHELL}"
SAMBA_GROUP_ENTRY="${SAMBA_GROUP}:x:${SAMBA_GROUP_ID}:"
function Usage() {
# Define the help/warning message:
echo -e "\tUsage: ./${SCRIPT_NAME} [OPTION] <samba_username>\n\t-h, --help : show this menu\n\t-a - add user\n\t-d - remove user"
}
function AddUser() {
if [ ! -d "${SAMBA_SHARE_DIR}" ]; then
#echo "Directory does not exist"
echo "Creating directory"
mkdir -p ${SAMBA_SHARE_DIR}
#Setting the permission for the main share directory
chown -R ${SAMBA_ADMIN}:${SAMBA_GROUP} ${SAMBA_SHARE_DIR}
fi
#Creating the new Samba group if it does not exist
grep -e "${SAMBA_GROUP_ENTRY}" /etc/group >/dev/null || echo "${SAMBA_GROUP_ENTRY}" >> /etc/group
#Creating the Samba administrator account if it does not exist
#grep -e "${SAMBA_ADMIN_ENTRY}" /etc/passwd >/dev/null || echo "${SAMBA_ADMIN_ENTRY}" >> /etc/passwd
smbadm_check=$(grep -e "${SAMBA_ADMIN}" /etc/passwd)
if [ -z "${smbadm_check}" ]; then # -n the argument is non empty, -z the argument is empty
#Create the Samba administrator (smbadmin user)
echo -e "Creating the Samba global administrator\n"
echo "${SAMBA_ADMIN_ENTRY}" >> /etc/passwd
echo -ne "Please, enter password for the Samba global administrator ${SAMBA_ADMIN}:\n"
read password
clear
sleep 1
/bin/smbpasswd ${SAMBA_ADMIN} ${password}
unset password
#Setting the permission for the main share directory
chown -R ${SAMBA_ADMIN}:${SAMBA_GROUP} ${SAMBA_SHARE_DIR}
fi
#Creating the new Samba username and user on the server itself if it does not exist
SAMBA_USER_ID=$(grep -e "${SAMBA_GROUP}" /etc/passwd | tail -n1 | cut -d: -f3)
let "SAMBA_USER_ID += 1"
SAMBA_USER_ENTRY="${USER}:*:${SAMBA_USER_ID}:${SAMBA_GROUP_ID}:${SAMBA_GROUP}:${SAMBA_HOME}:${SAMBA_SHELL}"
grep -e "${SAMBA_USER_ENTRY}" /etc/passwd >/dev/null || echo "${SAMBA_USER_ENTRY}" >> /etc/passwd
#Configuring the new user directory
mkdir -p ${SAMBA_USER_DIR}
mkdir -p ${SAMBA_USER_DIR}/Private
touch ${SAMBA_USER_DIR}/.profile
chown -R ${USER}:${SAMBA_GROUP} ${SAMBA_USER_DIR}
#Set the user permissions
chmod u=rwx,g=rx,o= ${SAMBA_USER_DIR}
#Prohibit access to the particular user's private folder
chmod u=rwx,go= ${SAMBA_USER_DIR}/Private
chmod -R u=rw,go= ${SAMBA_USER_DIR}/Private/*
#Status message:
echo -e "\nConfiguring user ${USER}...\n"
sleep 3
#Configuring the Samba passwd for the specified user
echo -ne "Please, enter password for the new user ${USER}:\n"
read password
clear
sleep 1
/bin/smbpasswd ${USER} ${password}
echo Finished
unset password
sleep 1
exit 0
}
function DelUser() {
#This function might remove all of the user files and directories as well as the user from the server itself
rm -R -f ${SAMBA_USER_DIR}
#Status message:
echo -e "\nRemoving user ${USER}...\n"
sleep 1
#sed -i '/'"${USER}"'/ d' /etc/samba/smbpasswd
/bin/smbpasswd -del ${USER}
sed -i '/'"${USER}"'/ d' /etc/passwd
echo Finished
sleep 1
exit 0
}
#MAIN
#Initialize script parameters and usage
if [ "$#" -ne "2" ] || [ "${OPTION}" = "-h" ] || [ "${OPTION}" = "--help" ] || [ "${OPTION}" = "help" ]; then
Usage
exit 0
fi
case ${OPTION} in
"-a" )
AddUser
;;
"-d" )
DelUser
;;
* )
echo -e "<${OPTION}> is invalid script option\n"
Usage
;;
esac