|
@@ -0,0 +1,295 @@
|
|
|
|
|
+#!/usr/bin/env bash
|
|
|
|
|
+#===============================================================================
|
|
|
|
|
+# FILE: samba.sh
|
|
|
|
|
+#
|
|
|
|
|
+# USAGE: ./samba.sh
|
|
|
|
|
+#
|
|
|
|
|
+# DESCRIPTION: Entrypoint for samba docker container
|
|
|
|
|
+#
|
|
|
|
|
+# OPTIONS: ---
|
|
|
|
|
+# REQUIREMENTS: ---
|
|
|
|
|
+# BUGS: ---
|
|
|
|
|
+# NOTES: ---
|
|
|
|
|
+# AUTHOR: David Personette ([email protected]),
|
|
|
|
|
+# ORGANIZATION:
|
|
|
|
|
+# CREATED: 09/28/2014 12:11
|
|
|
|
|
+# REVISION: 1.0
|
|
|
|
|
+#===============================================================================
|
|
|
|
|
+
|
|
|
|
|
+set -o nounset # Treat unset variables as an error
|
|
|
|
|
+
|
|
|
|
|
+### charmap: setup character mapping for file/directory names
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# chars) from:to character mappings separated by ','
|
|
|
|
|
+# Return: configured character mapings
|
|
|
|
|
+charmap() { local chars="$1" file=/etc/samba/smb.conf
|
|
|
|
|
+ grep -q catia $file || sed -i '/TCP_NODELAY/a \
|
|
|
|
|
+\
|
|
|
|
|
+ vfs objects = catia\
|
|
|
|
|
+ catia:mappings =\
|
|
|
|
|
+ ' $file
|
|
|
|
|
+
|
|
|
|
|
+ sed -i '/catia:mappings/s| =.*| = '"$chars"'|' $file
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### generic: set a generic config option in a section
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# section) section of config file
|
|
|
|
|
+# option) raw option
|
|
|
|
|
+# Return: line added to smb.conf (replaces existing line with same key)
|
|
|
|
|
+generic() { local section="$1" key="$(sed 's| *=.*||' <<< $2)" \
|
|
|
|
|
+ value="$(sed 's|[^=]*= *||' <<< $2)" file=/etc/samba/smb.conf
|
|
|
|
|
+ if sed -n '/^\['"$section"'\]/,/^\[/p' $file | grep -qE '^;*\s*'"$key"; then
|
|
|
|
|
+ sed -i '/^\['"$1"'\]/,/^\[/s|^;*\s*\('"$key"' = \).*| \1'"$value"'|' \
|
|
|
|
|
+ "$file"
|
|
|
|
|
+ else
|
|
|
|
|
+ sed -i '/\['"$section"'\]/a \ '"$key = $value" "$file"
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### global: set a global config option
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# option) raw option
|
|
|
|
|
+# Return: line added to smb.conf (replaces existing line with same key)
|
|
|
|
|
+global() { local key="$(sed 's| *=.*||' <<< $1)" \
|
|
|
|
|
+ value="$(sed 's|[^=]*= *||' <<< $1)" file=/etc/samba/smb.conf
|
|
|
|
|
+ if sed -n '/^\[global\]/,/^\[/p' $file | grep -qE '^;*\s*'"$key"; then
|
|
|
|
|
+ sed -i '/^\[global\]/,/^\[/s|^;*\s*\('"$key"' = \).*| \1'"$value"'|' \
|
|
|
|
|
+ "$file"
|
|
|
|
|
+ else
|
|
|
|
|
+ sed -i '/\[global\]/a \ '"$key = $value" "$file"
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### include: add a samba config file include
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# file) file to import
|
|
|
|
|
+include() { local includefile="$1" file=/etc/samba/smb.conf
|
|
|
|
|
+ sed -i "\\|include = $includefile|d" "$file"
|
|
|
|
|
+ echo "include = $includefile" >> "$file"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### import: import a smbpasswd file
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# file) file to import
|
|
|
|
|
+# Return: user(s) added to container
|
|
|
|
|
+import() { local file="$1" name id
|
|
|
|
|
+ while read name id; do
|
|
|
|
|
+ grep -q "^$name:" /etc/passwd || adduser -D -H -u "$id" "$name"
|
|
|
|
|
+ done < <(cut -d: -f1,2 $file | sed 's/:/ /')
|
|
|
|
|
+ pdbedit -i smbpasswd:$file
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### perms: fix ownership and permissions of share paths
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# none)
|
|
|
|
|
+# Return: result
|
|
|
|
|
+perms() { local i file=/etc/samba/smb.conf
|
|
|
|
|
+ for i in $(awk -F ' = ' '/ path = / {print $2}' $file); do
|
|
|
|
|
+ chown -Rh smbuser. $i
|
|
|
|
|
+ find $i -type d ! -perm 775 -exec chmod 775 {} \;
|
|
|
|
|
+ find $i -type f ! -perm 0664 -exec chmod 0664 {} \;
|
|
|
|
|
+ done
|
|
|
|
|
+}
|
|
|
|
|
+export -f perms
|
|
|
|
|
+
|
|
|
|
|
+### recycle: disable recycle bin
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# none)
|
|
|
|
|
+# Return: result
|
|
|
|
|
+recycle() { local file=/etc/samba/smb.conf
|
|
|
|
|
+ sed -i '/recycle:/d; /vfs objects/s/ recycle / /' $file
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### share: Add share
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# share) share name
|
|
|
|
|
+# path) path to share
|
|
|
|
|
+# browsable) 'yes' or 'no'
|
|
|
|
|
+# readonly) 'yes' or 'no'
|
|
|
|
|
+# guest) 'yes' or 'no'
|
|
|
|
|
+# users) list of allowed users
|
|
|
|
|
+# admins) list of admin users
|
|
|
|
|
+# writelist) list of users that can write to a RO share
|
|
|
|
|
+# comment) description of share
|
|
|
|
|
+# Return: result
|
|
|
|
|
+share() { local share="$1" path="$2" browsable="${3:-yes}" ro="${4:-yes}" \
|
|
|
|
|
+ guest="${5:-yes}" users="${6:-""}" admins="${7:-""}" \
|
|
|
|
|
+ writelist="${8:-""}" comment="${9:-""}" file=/etc/samba/smb.conf
|
|
|
|
|
+ sed -i "/\\[$share\\]/,/^\$/d" $file
|
|
|
|
|
+ echo "[$share]" >>$file
|
|
|
|
|
+ echo " path = $path" >>$file
|
|
|
|
|
+ echo " browsable = $browsable" >>$file
|
|
|
|
|
+ echo " read only = $ro" >>$file
|
|
|
|
|
+ echo " guest ok = $guest" >>$file
|
|
|
|
|
+ [[ ${VETO:-yes} == no ]] || {
|
|
|
|
|
+ echo -n " veto files = /.apdisk/.DS_Store/.TemporaryItems/" >>$file
|
|
|
|
|
+ echo -n ".Trashes/desktop.ini/ehthumbs.db/Network Trash Folder/" >>$file
|
|
|
|
|
+ echo "Temporary Items/Thumbs.db/" >>$file
|
|
|
|
|
+ echo " delete veto files = yes" >>$file
|
|
|
|
|
+ }
|
|
|
|
|
+ [[ ${users:-""} && ! ${users:-""} == all ]] &&
|
|
|
|
|
+ echo " valid users = $(tr ',' ' ' <<< $users)" >>$file
|
|
|
|
|
+ [[ ${admins:-""} && ! ${admins:-""} =~ none ]] &&
|
|
|
|
|
+ echo " admin users = $(tr ',' ' ' <<< $admins)" >>$file
|
|
|
|
|
+ [[ ${writelist:-""} && ! ${writelist:-""} =~ none ]] &&
|
|
|
|
|
+ echo " write list = $(tr ',' ' ' <<< $writelist)" >>$file
|
|
|
|
|
+ [[ ${comment:-""} && ! ${comment:-""} =~ none ]] &&
|
|
|
|
|
+ echo " comment = $(tr ',' ' ' <<< $comment)" >>$file
|
|
|
|
|
+ echo "" >>$file
|
|
|
|
|
+ [[ -d $path ]] || mkdir -p $path
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### smb: disable SMB2 minimum
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# none)
|
|
|
|
|
+# Return: result
|
|
|
|
|
+smb() { local file=/etc/samba/smb.conf
|
|
|
|
|
+ sed -i 's/\([^#]*min protocol *=\).*/\1 LANMAN1/' $file
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### user: add a user
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# name) for user
|
|
|
|
|
+# password) for user
|
|
|
|
|
+# id) for user
|
|
|
|
|
+# group) for user
|
|
|
|
|
+# gid) for group
|
|
|
|
|
+# Return: user added to container
|
|
|
|
|
+user() { local name="$1" passwd="$2" id="${3:-""}" group="${4:-""}" \
|
|
|
|
|
+ gid="${5:-""}"
|
|
|
|
|
+ [[ "$group" ]] && { grep -q "^$group:" /etc/group ||
|
|
|
|
|
+ addgroup ${gid:+--gid $gid }"$group"; }
|
|
|
|
|
+ grep -q "^$name:" /etc/passwd ||
|
|
|
|
|
+ adduser -D -H ${group:+-G $group} ${id:+-u $id} "$name"
|
|
|
|
|
+ echo -e "$passwd\n$passwd" | smbpasswd -s -a "$name"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### workgroup: set the workgroup
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# workgroup) the name to set
|
|
|
|
|
+# Return: configure the correct workgroup
|
|
|
|
|
+workgroup() { local workgroup="$1" file=/etc/samba/smb.conf
|
|
|
|
|
+ sed -i 's|^\( *workgroup = \).*|\1'"$workgroup"'|' $file
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### widelinks: allow access wide symbolic links
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# none)
|
|
|
|
|
+# Return: result
|
|
|
|
|
+widelinks() { local file=/etc/samba/smb.conf \
|
|
|
|
|
+ replace='\1\n wide links = yes\n unix extensions = no'
|
|
|
|
|
+ sed -i 's/\(follow symlinks = yes\)/'"$replace"'/' $file
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+### usage: Help
|
|
|
|
|
+# Arguments:
|
|
|
|
|
+# none)
|
|
|
|
|
+# Return: Help text
|
|
|
|
|
+usage() { local RC="${1:-0}"
|
|
|
|
|
+ echo "Usage: ${0##*/} [-opt] [command]
|
|
|
|
|
+Options (fields in '[]' are optional, '<>' are required):
|
|
|
|
|
+ -h This help
|
|
|
|
|
+ -c \"<from:to>\" setup character mapping for file/directory names
|
|
|
|
|
+ required arg: \"<from:to>\" character mappings separated by ','
|
|
|
|
|
+ -G \"<section;parameter>\" Provide generic section option for smb.conf
|
|
|
|
|
+ required arg: \"<section>\" - IE: \"share\"
|
|
|
|
|
+ required arg: \"<parameter>\" - IE: \"log level = 2\"
|
|
|
|
|
+ -g \"<parameter>\" Provide global option for smb.conf
|
|
|
|
|
+ required arg: \"<parameter>\" - IE: \"log level = 2\"
|
|
|
|
|
+ -i \"<path>\" Import smbpassword
|
|
|
|
|
+ required arg: \"<path>\" - full file path in container
|
|
|
|
|
+ -n Start the 'nmbd' daemon to advertise the shares
|
|
|
|
|
+ -p Set ownership and permissions on the shares
|
|
|
|
|
+ -r Disable recycle bin for shares
|
|
|
|
|
+ -S Disable SMB2 minimum version
|
|
|
|
|
+ -s \"<name;/path>[;browse;readonly;guest;users;admins;writelist;comment]\"
|
|
|
|
|
+ Configure a share
|
|
|
|
|
+ required arg: \"<name>;</path>\"
|
|
|
|
|
+ <name> is how it's called for clients
|
|
|
|
|
+ <path> path to share
|
|
|
|
|
+ NOTE: for the default value, just leave blank
|
|
|
|
|
+ [browsable] default:'yes' or 'no'
|
|
|
|
|
+ [readonly] default:'yes' or 'no'
|
|
|
|
|
+ [guest] allowed default:'yes' or 'no'
|
|
|
|
|
+ NOTE: for user lists below, usernames are separated by ','
|
|
|
|
|
+ [users] allowed default:'all' or list of allowed users
|
|
|
|
|
+ [admins] allowed default:'none' or list of admin users
|
|
|
|
|
+ [writelist] list of users that can write to a RO share
|
|
|
|
|
+ [comment] description of share
|
|
|
|
|
+ -u \"<username;password>[;ID;group;GID]\" Add a user
|
|
|
|
|
+ required arg: \"<username>;<passwd>\"
|
|
|
|
|
+ <username> for user
|
|
|
|
|
+ <password> for user
|
|
|
|
|
+ [ID] for user
|
|
|
|
|
+ [group] for user
|
|
|
|
|
+ [GID] for group
|
|
|
|
|
+ -w \"<workgroup>\" Configure the workgroup (domain) samba should use
|
|
|
|
|
+ required arg: \"<workgroup>\"
|
|
|
|
|
+ <workgroup> for samba
|
|
|
|
|
+ -W Allow access wide symbolic links
|
|
|
|
|
+ -I Add an include option at the end of the smb.conf
|
|
|
|
|
+ required arg: \"<include file path>\"
|
|
|
|
|
+ <include file path> in the container, e.g. a bind mount
|
|
|
|
|
+The 'command' (if provided and valid) will be run instead of samba
|
|
|
|
|
+" >&2
|
|
|
|
|
+ exit $RC
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+[[ "${USERID:-""}" =~ ^[0-9]+$ ]] && usermod -u $USERID -o smbuser
|
|
|
|
|
+[[ "${GROUPID:-""}" =~ ^[0-9]+$ ]] && groupmod -g $GROUPID -o smb
|
|
|
|
|
+
|
|
|
|
|
+while getopts ":hc:G:g:i:nprs:Su:Ww:I:" opt; do
|
|
|
|
|
+ case "$opt" in
|
|
|
|
|
+ h) usage ;;
|
|
|
|
|
+ c) charmap "$OPTARG" ;;
|
|
|
|
|
+ G) eval generic $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $OPTARG) ;;
|
|
|
|
|
+ g) global "$OPTARG" ;;
|
|
|
|
|
+ i) import "$OPTARG" ;;
|
|
|
|
|
+ n) NMBD="true" ;;
|
|
|
|
|
+ p) PERMISSIONS="true" ;;
|
|
|
|
|
+ r) recycle ;;
|
|
|
|
|
+ s) eval share $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $OPTARG) ;;
|
|
|
|
|
+ S) smb ;;
|
|
|
|
|
+ u) eval user $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $OPTARG) ;;
|
|
|
|
|
+ w) workgroup "$OPTARG" ;;
|
|
|
|
|
+ W) widelinks ;;
|
|
|
|
|
+ I) include "$OPTARG" ;;
|
|
|
|
|
+ "?") echo "Unknown option: -$OPTARG"; usage 1 ;;
|
|
|
|
|
+ ":") echo "No argument value for option: -$OPTARG"; usage 2 ;;
|
|
|
|
|
+ esac
|
|
|
|
|
+done
|
|
|
|
|
+shift $(( OPTIND - 1 ))
|
|
|
|
|
+
|
|
|
|
|
+[[ "${CHARMAP:-""}" ]] && charmap "$CHARMAP"
|
|
|
|
|
+while read i; do
|
|
|
|
|
+ eval generic $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $i)
|
|
|
|
|
+done < <(env | awk '/^GENERIC[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
|
|
|
|
|
+while read i; do
|
|
|
|
|
+ global "$i"
|
|
|
|
|
+done < <(env | awk '/^GLOBAL[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
|
|
|
|
|
+[[ "${IMPORT:-""}" ]] && import "$IMPORT"
|
|
|
|
|
+[[ "${RECYCLE:-""}" ]] && recycle
|
|
|
|
|
+while read i; do
|
|
|
|
|
+ eval share $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $i)
|
|
|
|
|
+done < <(env | awk '/^SHARE[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
|
|
|
|
|
+[[ "${SMB:-""}" ]] && smb
|
|
|
|
|
+while read i; do
|
|
|
|
|
+ eval user $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $i)
|
|
|
|
|
+done < <(env | awk '/^USER[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
|
|
|
|
|
+[[ "${WORKGROUP:-""}" ]] && workgroup "$WORKGROUP"
|
|
|
|
|
+[[ "${WIDELINKS:-""}" ]] && widelinks
|
|
|
|
|
+[[ "${INCLUDE:-""}" ]] && include "$INCLUDE"
|
|
|
|
|
+[[ "${PERMISSIONS:-""}" ]] && perms &
|
|
|
|
|
+
|
|
|
|
|
+if [[ $# -ge 1 && -x $(which $1 2>&-) ]]; then
|
|
|
|
|
+ exec "$@"
|
|
|
|
|
+elif [[ $# -ge 1 ]]; then
|
|
|
|
|
+ echo "ERROR: command not found: $1"
|
|
|
|
|
+ exit 13
|
|
|
|
|
+elif ps -ef | egrep -v grep | grep -q smbd; then
|
|
|
|
|
+ echo "Service already running, please restart container to apply changes"
|
|
|
|
|
+else
|
|
|
|
|
+ [[ ${NMBD:-""} ]] && ionice -c 3 nmbd -D
|
|
|
|
|
+ exec ionice -c 3 smbd -FS --no-process-group </dev/null
|
|
|
|
|
+fi
|