| #!/bin/sh |
| ############################################################################### |
| # BRLTTY - A background process providing access to the console screen (when in |
| # text mode) for a blind person using a refreshable braille display. |
| # |
| # Copyright (C) 1995-2023 by The BRLTTY Developers. |
| # |
| # BRLTTY comes with ABSOLUTELY NO WARRANTY. |
| # |
| # This is free software, placed under the terms of the |
| # GNU Lesser General Public License, as published by the Free Software |
| # Foundation; either version 2.1 of the License, or (at your option) any |
| # later version. Please see the file LICENSE-LGPL for details. |
| # |
| # Web Page: http://brltty.app/ |
| # |
| # This software is maintained by Dave Mielke <dave@mielke.cc>. |
| ############################################################################### |
| |
| set -e |
| . "`dirname "${0}"`/brltty-prologue.sh" |
| . "${programDirectory}/brltty-config.sh" |
| |
| showProgramUsagePurpose() { |
| cat <<END_OF_PROGRAM_USAGE_PURPOSE |
| Simplify the job of Creating and making changes to BRLTTY's unprivileged user. |
| END_OF_PROGRAM_USAGE_PURPOSE |
| } |
| |
| declare -A privilegeParameters |
| parseParameterString privilegeParameters "${BRLTTY_PRIVILEGE_PARAMETERS}" lx |
| |
| readonly defaultUserName="${privilegeParameters["USER"]}" |
| readonly defaultUserInformation="Braille Device Daemon" |
| readonly defaultHomeDirectory="${BRLTTY_UPDATABLE_DIRECTORY}" |
| readonly defaultLoginShell="/sbin/nologin" |
| |
| showProgramUsageNotes() { |
| cat <<END_OF_PROGRAM_USAGE_NOTES |
| When creating a new user, these options have the following defaults: |
| -d ${defaultHomeDirectory:-the home directory isn't defined} |
| -g a new group with the same name as the user |
| -i ${defaultUserInformation} |
| -l ${defaultLoginShell} |
| These defaults don't apply when making changes to an existing user. |
| END_OF_PROGRAM_USAGE_NOTES |
| } |
| |
| executeCommand() { |
| "${useSudo}" && set -- sudo -- "${@}" |
| |
| if "${testMode}" |
| then |
| echo "${*}" |
| else |
| "${@}" |
| fi |
| } |
| |
| groupList=() |
| addGroups() { |
| while [ "${#}" -gt 0 ] |
| do |
| local group="${1}" |
| shift 1 |
| [ -n "${group}" ] || continue |
| |
| [ "${group#*/}" = "${group}" ] || { |
| group="$(stat -c "%G" "${group}")" || : |
| [ -n "${group}" ] || continue |
| } |
| |
| local g |
| for g in "${groupList[@]}" |
| do |
| [ "${g}" = "${group}" ] && { |
| group="" |
| break |
| } |
| done |
| |
| [ -n "${group}" ] && groupList[${#groupList[*]}]="${group}" |
| done |
| |
| return 0 |
| } |
| |
| addProgramOption a flag noALSA "don't allow playing sound via the ALSA framework" |
| addProgramOption b flag noBrlapi "don't allow reading BrlAPI's authorization key file" |
| addProgramOption c flag noConsoles "don't allow access to the virtual consoles" |
| addProgramOption d string.path homeDirectory "set/change the home (login) directory" |
| addProgramOption g string.group primaryGroup "set/change the primary (login) group" |
| addProgramOption i string.text userInformation "set/change the user information (gecos) text" |
| addProgramOption k flag noKeyboards "don't allow keyboard monitoring" |
| addProgramOption l string.path loginShell "set/change the login shell" |
| addProgramOption p flag noPulse "don't allow playing sound via the Pulse Audio server" |
| addProgramOption s flag noSerial "don't allow access to serial devices" |
| addProgramOption u flag noUSB "don't allow access to USB devices" |
| addProgramOption E flag allowChanges "allow changes to an existing user" |
| addProgramOption G flag noGroups "don't set/change the supplementary group list" |
| addProgramOption N flag allowCreate "allow creating a new user" |
| addProgramOption S flag useSudo "use sudo to execute the commands as root" |
| addProgramOption T flag testMode "test mode - show the commands that would be executed" |
| addProgramOption U string.user userName "the user to be created/changed" "${defaultUserName}" |
| parseProgramArguments "${@}" |
| |
| [ -n "${userName}" ] || userName="${defaultUserName}" |
| [ -n "${userName}" ] || syntaxError "unprivileged user not configured - use -U (user) to specify" |
| |
| if id -u "${userName}" >/dev/null 2>&1 |
| then |
| "${allowChanges}" || semanticError "user already exists: ${userName} - use -E (existing) to allow" |
| command=(usermod) |
| else |
| "${allowCreate}" || semanticError "user doesn't exist: ${userName} - use -N (new) to allow" |
| command=(useradd --system) |
| [ -n "${primaryGroup}" ] || command+=(--user-group) |
| |
| [ -n "${userInformation}" ] || userInformation="${defaultUserInformation}" |
| [ -n "${homeDirectory}" ] || homeDirectory="${defaultHomeDirectory}" |
| [ -n "${loginShell}" ] || loginShell="${defaultLoginShell}" |
| |
| if [ -n "${homeDirectory}" ] |
| then |
| command+=(--create-home) |
| else |
| command+=(--no-create-home) |
| fi |
| fi |
| |
| [ -n "${homeDirectory}" ] && command+=(--home "${homeDirectory}") |
| [ -n "${primaryGroup}" ] && command+=(--gid "${primaryGroup}") |
| [ -n "${userInformation}" ] && command+=(--comment "${userInformation}") |
| [ -n "${loginShell}" ] && command+=(--shell "${loginShell}") |
| |
| "${noGroups}" || { |
| "${noALSA}" || addGroups audio |
| "${noBrlapi}" || addGroups "${BRLAPI_KEY_FILE}" |
| "${noConsoles}" || addGroups tty /dev/vcs1 /dev/tty1 |
| "${noKeyboards}" || addGroups input |
| "${noPulse}" || addGroups pulse-access |
| "${noSerial}" || addGroups /dev/ttyS0 |
| "${noUSB}" || addGroups /dev/bus/usb |
| |
| groupsOperand="${groupList[*]}" |
| groupsOperand="${groupsOperand// /,}" |
| command+=(--groups "${groupsOperand}") |
| } |
| |
| "${testMode}" || { |
| if "${useSudo}" |
| then |
| sudo -v |
| elif [ "$(id -u)" -ne 0 ] |
| then |
| semanticError "not executing as root" |
| fi |
| } |
| |
| command+=(-- "${userName}") |
| executeCommand "${command[@]}" |
| exit 0 |