Advertisement
Guest User

XSu

a guest
Jan 24th, 2016
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 9.07 KB | None | 0 0
  1. #!/bin/bash
  2. #Written by Manuel Iglesias. glesialo@gmail.com
  3.  
  4. CommandName=${0##*/}
  5. TempDir=/tmp
  6. HomeBasePath="/home"
  7. TempXSessionErrorsFileName=".xsession-errors"
  8. TempXAuthorityFileName=".Xauthority"
  9. UserNamePlaceHolder="USERNAME"
  10. DefaultAskForPasswordMessage="Please type $UserNamePlaceHolder password."
  11. UserOption="--user"
  12. UserOptionMissingMessage="Missing user's name"
  13. MessageOption="--message"
  14. MessageOptionMissingMessage="Missing message string"
  15. DefaultMissingMessage="Missing string"
  16. English_LANG=en_IE.UTF-8
  17. English_LANGUAGE=en_IE:en
  18. SuAuthenticationFailureMessage="su: Authentication failure"
  19. Dialog_MessageTimedTimeout=5 # In seconds.
  20. WrongPasswordMessage="ERROR: Incorrect password."
  21.  
  22.  
  23.  
  24. #Functions. BEGIN.
  25. echoE()
  26. {
  27. echo -e "$@" 1>&2 # If run in a X window application: writes to XsessionErrorsFile
  28. Dialog_MessageTimed --title "$CommandName-$$" --timeout $Dialog_MessageTimedTimeout "$(echo -e "$@")" &>/dev/null &
  29. return 0
  30. }
  31.  
  32. Exit() # $1: Script ExitCode
  33. {
  34. if [ -n "$Old_DBUS_SESSION_BUS_ADDRESS" ]
  35.   then
  36.     export DBUS_SESSION_BUS_ADDRESS=$Old_DBUS_SESSION_BUS_ADDRESS
  37. fi
  38. if [ -n "$Old_XAUTHORITY" ]
  39.   then
  40.     export XAUTHORITY=$Old_XAUTHORITY
  41. fi
  42. if [ -n "$Old_USER" ]
  43.   then
  44.     export USER=$Old_USER
  45. fi
  46. if [ -n "$Old_HOME" ]
  47.   then
  48.     export HOME=$Old_HOME
  49. fi
  50. if [ -n "$Old_LANG" ]
  51.   then
  52.     export LANG=$Old_LANG
  53. fi
  54. if [ -n "$Old_LANGUAGE" ]
  55.   then
  56.     export LANGUAGE=$Old_LANGUAGE
  57. fi
  58. if [ -f "$TempXAuthorityFile" ]
  59.   then
  60.     if ! rm $TempXAuthorityFile &>/dev/null
  61.       then
  62.         echoE "$CommandName-$$: Warning! Can't remove temporary \$XAUTHORITY file."
  63.     fi
  64. fi
  65. if [ -f "$TempXSessionErrorsFile" ]
  66.   then
  67.     if [ -s "$TempXSessionErrorsFile" ] # If more than 0 bytes
  68.       then
  69.         while read Line
  70.           do
  71.             echo "$CommandName-$$: $Line"
  72.           done < "$TempXSessionErrorsFile"
  73.     fi
  74.     if ! rm $TempXSessionErrorsFile &>/dev/null
  75.       then
  76.         echoE "$CommandName-$$: Warning! Can't remove '$TempXSessionErrorsFile' file."
  77.     fi
  78. fi
  79. echo "$CommandName-$$: Exit code: $1."
  80. echo "#### $CommandName-$$. END." # Mark end of output
  81. exit $1 # This is not a mistake. Here the whole script exits.
  82. }
  83.  
  84. Usage()
  85. {
  86. echoE "'$CommandName' lets user run a (graphical) Command as a different user (UserName) if the correct
  87. password is given. If no UserName is supplied, '$CommandName' will run the given Command as 'root'.
  88. Command will run with the same environment UserName would have after login.
  89. Usage: '$CommandName [Options] Command [CommandParameters]'.
  90. Options:
  91.  [$UserOption UserName] (Command will run for UserName).
  92.  [$MessageOption request_password_message] (will replace the default message).
  93. Note: StdOut & StdError will be redirected to (invoking user's) '\$HOME/$TempXSessionErrorsFileName'."
  94. return 0
  95. }
  96. #Functions. END.
  97.  
  98.  
  99.  
  100. if [ $# -lt 1 ] || [ "$1" == "-h" ] || [ "$1" == "-?" ] || [ "$1" == "--help" ] || [ "$1" == "-help" ]
  101.   then
  102.     Usage
  103.     exit 64
  104. fi
  105.  
  106. #Mark beginning of output. BEGIN.
  107. CommandLine="$CommandName"
  108. for Param in "$@"
  109.   do
  110.     Substrings=0
  111.     for SubString in $Param
  112.       do
  113.         let Substrings++
  114.       done
  115.     if [ $Substrings -gt 1 ]
  116.       then
  117.         CommandLine=$CommandLine" \"$Param\""
  118.       else
  119.         CommandLine=$CommandLine" $Param"
  120.     fi
  121.   done
  122. echo -e "#### $CommandName-$$. BEGIN.\n$CommandName-$$.CmmdLine:>$CommandLine<"
  123. CommandLine=""
  124. #Mark beginning of output. END.
  125.  
  126. #!! Use 'Exit' instead of 'exit' from now on to remove temporary files and mark end of output
  127.  
  128. #Temporary XSessionErrorsFile file. BEGIN.
  129. if ! TempXSessionErrorsFile=$(mktemp ${TempDir}/${CommandName}${TempXSessionErrorsFileName}.XXXXXXXX 2>/dev/null) # Copy different for each instance of script.
  130.  then
  131.    echoE "$CommandName-$$: Failed to create temporary '$TempXSessionErrorsFileName' file. Aborting."
  132.    Exit 73
  133. fi
  134. if ! chmod 666 $TempXSessionErrorsFile 2>/dev/null
  135.   then
  136.     echoE "$CommandName-$$: Can't change permissions of '$TempXSessionErrorsFile'. Aborting."
  137.     Exit 77
  138. fi
  139. #Temporary XSessionErrorsFile file. END.
  140.  
  141. #Temporary $XAUTHORITY file. BEGIN.
  142. if [ -z "$XAUTHORITY" ] || ! [ -f "$XAUTHORITY" ]
  143.   then
  144.     echoE "$CommandName-$$: \$XAUTHORITY file does not exist. Aborting."
  145.     Exit 70
  146. fi
  147. if ! TempXAuthorityFile=$(mktemp ${TempDir}/${CommandName}${TempXAuthorityFileName}.XXXXXXXX 2>/dev/null)
  148.  then
  149.    echoE "$CommandName-$$: Failed to create temporary '$TempXAuthorityFileName' file. Aborting."
  150.    Exit 73
  151. fi
  152. if ! cp -f $XAUTHORITY $TempXAuthorityFile 2>/dev/null #Current file in $XAUTHORITY has 600 permissions and, therefore, is only readable by its owner
  153.  then
  154.    echoE "$CommandName-$$: Can't copy \$XAUTHORITY file. Aborting."
  155.    Exit 73
  156. fi
  157. if ! chmod 644 $TempXAuthorityFile 2>/dev/null # Read permissions to all
  158.  then
  159.    echoE "$CommandName-$$: Can't change permissions of temporary \$XAUTHORITY file. Aborting."
  160.    Exit 77
  161. fi
  162. #Temporary $XAUTHORITY file. END.
  163.  
  164. RunWithLoginEnvironmentScript=$(which -a RunWithLoginEnvironment 2>/dev/null) # which: Path/File needed
  165. if [ ! -f "$RunWithLoginEnvironmentScript" ]
  166.   then
  167.     echoE "$CommandName-$$: RunWithLoginEnvironmentScript 'RunWithLoginEnvironment' script not found. Aborting."
  168.     Exit 127
  169. fi
  170.  
  171. #Read strings and remove UserOption & MessageOption. BEGIN.
  172. OptionMessageValue="";OptionUserValue="";Parameters="";VariableToRead="";WaitingForString=false
  173. for Parameter in "$@"
  174.   do
  175.     if $WaitingForString
  176.       then
  177.         eval "$VariableToRead=\"$Parameter\""
  178.         VariableToRead=""
  179.         WaitingForString=false
  180.       else
  181.         if [ "$Parameter" == "$UserOption" ]
  182.           then
  183.             WaitingForString=true
  184.             VariableToRead="OptionUserValue"
  185.           else
  186.             if [ "$Parameter" == "$MessageOption" ]
  187.               then
  188.                 WaitingForString=true
  189.                 VariableToRead="OptionMessageValue"
  190.               else
  191.                 Parameters=${Parameters}"\"$Parameter\" "
  192.             fi
  193.         fi
  194.     fi
  195.   done
  196. if $WaitingForString && [ -n "$VariableToRead" ]
  197.   then
  198.     case "$VariableToRead" in
  199.       OptionUserValue) echoE "$CommandName-$$: $UserOptionMissingMessage";;
  200.       OptionMessageValue) echoE "$CommandName-$$: $MessageOptionMissingMessage";;
  201.       *) echoE "$CommandName-$$: $DefaultMissingMessage";;
  202.     esac
  203.     Exit 64
  204. fi
  205. eval "set -- $Parameters" # To interpret correctly parameter values with spaces
  206. #Read strings and remove UserOption & MessageOption. END.
  207.  
  208. Old_USER=$USER
  209. Old_HOME=$HOME
  210. if [ -z "$OptionUserValue" ]
  211.   then
  212.     OptionUserValue=root
  213. fi
  214. if IsRegisteredUser "$OptionUserValue"
  215.   then
  216.     export USER=$OptionUserValue
  217.   else
  218.     echoE "$CommandName-$$: '$OptionUserValue' is not a registered user. Aborting."
  219.     Exit 67
  220. fi
  221. if [ "$USER" == "$Old_USER" ]
  222.   then
  223.     echoE "$CommandName-$$: '$OptionUserValue' is already the current user. Aborting."
  224.     Exit 67
  225. fi
  226. if [ "$USER" == "root" ]
  227.   then
  228.     export HOME="/${USER}"
  229.   else
  230.     export HOME=${HomeBasePath}/${USER}
  231. fi
  232.  
  233. if [ ! -d "$HOME" ]
  234.   then
  235.     echoE "$CommandName-$$: ${USER}'s \$HOME not found. Aborting."
  236.     Exit 70
  237. fi
  238.  
  239. if [ $# -eq 0 ]
  240.   then
  241.     echoE "$CommandName-$$: No Command to run. Aborting."
  242.     Exit 127
  243. fi
  244.  
  245. if [ -n "$OptionMessageValue" ]
  246.   then
  247.     AskForPasswordMessage="$OptionMessageValue"
  248.   else
  249.     AskForPasswordMessage=${DefaultAskForPasswordMessage/$UserNamePlaceHolder/${USER}\'s}
  250. fi
  251.  
  252. if ! Password=$(Dialog_InputText --title "$CommandName-$$" --hide-entry-text "$AskForPasswordMessage" 2>/dev/null)
  253.   then
  254.     echoE "$CommandName-$$: Failed to read password. Aborting."
  255.     Exit 90
  256. fi
  257.  
  258. Old_XAUTHORITY=$XAUTHORITY
  259. export XAUTHORITY=$TempXAuthorityFile
  260. Old_LANG=$LANG
  261. Old_LANGUAGE=$LANGUAGE
  262. if [ -z "$Old_LANGUAGE" ]
  263.   then
  264.     Old_LANGUAGE=$Old_LANG
  265. fi
  266. Old_DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS
  267. export -n DBUS_SESSION_BUS_ADDRESS="" # Unset + export: Remove from environment. Some applications (I.E.: DefaultTerminalEmulator) refuse to start otherwise.
  268. LANG=$English_LANG      # expect expects English su's messages
  269. LANGUAGE=$English_LANGUAGE  # expect expects English su's messages
  270. ExpectOut=$(expect - "$@" <<HereDoc
  271. set force_conservative 1  ;# set to 1 to force conservative mode even if
  272.               ;# script wasn't run conservatively originally
  273. if {\$force_conservative} {
  274.   set send_slow {1 .1}
  275.   proc send {ignore arg} {
  276.     sleep .1
  277.     exp_send -s -- \$arg
  278.   }
  279. }
  280. set timeout -1
  281. set argsstring ""
  282. foreach a \$argv {
  283.   append argsstring "\"\${a}\" " ;# argsstring: "arg 1" "arg 2" ...
  284. }
  285. spawn \$env(SHELL)
  286. match_max 100000
  287. spawn -noecho su $USER -c "&>$TempXSessionErrorsFile LANG=$Old_LANG LANGUAGE=$Old_LANGUAGE $RunWithLoginEnvironmentScript \$argsstring"
  288. expect "assword:"
  289. send {ignore arg} "$Password\r"
  290. expect eof
  291. catch wait result
  292. exit [lindex \$result 3]
  293. HereDoc
  294. )
  295. ExitCode=$?
  296. if [ "$ExpectOut" != "${ExpectOut/${SuAuthenticationFailureMessage}/}" ] # $SuAuthenticationFailureMessage found in expect output
  297.   then
  298.     echoE "$CommandName-$$: $WrongPasswordMessage"
  299.     Exit 77
  300.   else
  301.     Exit $ExitCode # Necessary to remove temporary files.
  302. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement