среда, 11 апреля 2012 г.

Запуск GUI-приложения от имени другого пользователя

1.) Способ - самодельный велосипед
 
#!/bin/bash
# Коды завершения
UA_REQUEST=60  # Прервано пользователем
NO_REQUEST=61  # Нет одного или нескольких параметров
NU_REQUEST=62  # Указан несуществующий пользователь
NEH_REQUEST=63  # Не удалось создать папку пользователя
FCXA_REQUEST=64  # Не удалось создать файл авторизации
SUDOFAIL_REQUEST=65 # Ошибка авторизации супер-пользователя
UE_REQUEST=69  # Непредвиденная ошибка
HELP_REQUEST=70  # HELP
# Справка
if [ "$1" = "-h"  -o "$1" = "--help" ]     # Request help.
then
 echo; echo "Порядок использования: $0 user [option] command"
 echo "   $0 [-h|--help] - выводит эту справку"; echo
 sed --silent -e '/DOCUMENTATIONHELP$/,/^DOCUMENTATIONHELP/p' "$0" |
 sed -e '/DOCUMENTATIONHELP/d';
 exit $HELP_REQUEST;
fi

: << DOCUMENTATIONHELP
Запускает GUI-приложение от имени другого пользователя
Для правильной работы ваша система должна пробрасывать переменную XAUTHORITY через sudo
и вы должны иметь права на sudo - вам потребуется ввести свой пароль
 user - пользователь от имени которого необходимо выполнить command
 option - однобуквенный ключ указывающий в каком домашнем каталоге выполнять command
 если ключ опущен, то для пользователей с uid < 1000 будет созданн временный каталог в /tmp,
 а для пользователей с uid > 999 будет использоваться каталог указанный в /etc/passwd,
  h - выполнить в домашнем каталоге пользователя указанном в /etc/passwd
  t - создать временныый каталог для выполнения этой задачи
Коды завершения:
 60 - Прервано пользователем
 61 - Нет одного или нескольких параметров
 62 - Указан несуществующий пользователь
 63 - Не удалось создать папку позьзователя
 64 - Не удалось создать файл авторизации
 65 - Ошибка авторизации супер-пользователя
 69 - Непредвиденная ошибка
 70 - HELP
  
by dr.Faust aka Suntechnic
GNU/GPL 3 (2010)
DOCUMENTATIONHELP

# Обработка естественных ошибок
# Проверка параметров
if [ "$1" = "" -o "$2" = "" ]
then
 echo "$0: пропущен операнд"
 echo "Попробуйте '$0 --help' для получения более подробного описания."
 exit $NO_REQUEST
fi
# Проверка пользователя
PSWDNT=`cat /etc/passwd | grep "$1:x:"` # Запись о пользователе в /etc/passwd
if [ "$PSWDNT" = "" ]
then
 echo "$0: неизвестный пользователь: $1"
 exit $NU_REQUEST
fi

# Получаем переменные и устанавливаем home
# Окружение
DSPL=$DISPLAY
MYXA=$XAUTHORITY

TMPUSER=$1 # Пользователь
PLACE=$2 # Предположительно ключ home
# CMND=$3 # Команда

# Устанавливаем переменные
case $PLACE in
 ["h"])
  # Выполняем операцию в домашнем каталоге из /etc/passwd
  # Получаем информацию о пользователе
  CMNDAWK=`echo 'BEGIN{ FS = ":" }{ print $6 }'`
   LCHOME=`echo $PSWDNT | awk "$CMNDAWK"`
  CMNDAWK=`echo 'BEGIN{ FS = ":" }{ print $3 }'`
   LCUID=`echo $PSWDNT | awk "$CMNDAWK"`
  if [ "$LCUID" -lt "1000" ]
  then
   # Операция в домашнем каталоге пользователя с UID < 1000
   echo "Вы пытаетесь выполнить '$CMND' от имени пользователя '$TMPUSER' (UID: $LCUID) в его домашнем каталоге: $LCHOME"
   read -p "Всё равно продолжить? (Да - только 'y') [y/n]: " myyn
   if [ "$myyn" != "y" ]
   then
    echo "Прервано пользователем"
    exit $UA_REQUEST
   fi
  fi
  shift
  shift
  CMND=$@
 ;;
 ["t"])
  # Выполняем операцию во временном домашнем каталоге
  LCHOME=/tmp/tudo-$TMPUSER
  shift
  shift
  CMND=$@
 ;;
 *)
  # Выполняем операцию в каком-то домашнем каталоге... ;)
  # Получаем UID
  CMNDAWK=`echo 'BEGIN{ FS = ":" }{ print $3 }'`
  LCUID=`echo $PSWDNT | awk "$CMNDAWK"`
  if [ "$LCUID" -lt "1000" ]
  then
   PLACE="t"
   LCHOME=/tmp/tudo-$TMPUSER
  else
   PLACE="h"
   CMNDAWK=`echo 'BEGIN{ FS = ":" }{ print $6 }'`
   LCHOME=`echo $PSWDNT | awk "$CMNDAWK"`
  fi
  shift
  CMND=$@
esac
# Проверяем теперь уже окончательную команду
if [ "$CMND" = "" ]
then
 echo "$0: пропущен операнд"
 echo "Попробуйте '$0 --help' для получения более подробного описания."
 exit $NO_REQUEST
fi

# Собственно рабочий код
# Тут нам потребуется судо
sudo true
if [ "$?" != "0" ]
then
 echo "$0: провал авторизации"
 exit $SUDOFAIL_REQUEST
fi

if [ "$PLACE" = "t" ]
then
 # Необходима временная домашняя папка
 # Создаём временный домашний каталог
 sudo mkdir $LCHOME
 if [ "$?" = "0" ]
 then
  # Если мы действительно создали временный домашний каталог, запишем путь к нему в файл - это потребуется в дальнейшем для безопасного его удаления
  LCLCHOME="$LCHOME""_lc"
  # Указатель на удачное создание каталога
  sudo echo "$LCHOME" >> $LCLCHOME
  sudo chmod 0777 $LCLCHOME
 fi 
 sudo chown $TMPUSER $LCHOME
else
 if [ ! -d $LCHOME ]
 then
  # а каталога-то и нет...
  sudo mkdir $LCHOME
  if [ "$?" = "0" ]
  then
   $PLACE="ht"
  else
   echo "Домашний каталог '$LCHOME' не существует, а попытка его создания завершилась провалом"
   exit $NEH_REQUEST
  fi
  sudo chown $TMPUSER $LCHOME
 fi
fi
# Проверяем получили ли мы каталог
if [ ! -d $LCHOME ]
then
 echo "Домашний каталог '$LCHOME' не существует или его не удалось создать"
 exit $NEH_REQUEST
fi

# Отдаём файл авторизации
LXA=$LCHOME/.xauthority-tudo
sudo cp $MYXA $LXA
sudo chown $TMPUSER $LXA
# Проверяем получили ли файл авторизации
if [ ! -e $LXA ]
then
 echo "Не удалось создать файл авторизации"
 exit $FCXA_REQUEST
fi
# На всякий случай проверяем переменные
# Так как хомяк и файл авторизации будут удалятся, да ещё и от root - проверим что путь к хомяку не "" и не "/"
if [ "$LCHOME" = "" -o "$LCHOME" = "/" ]
then
 echo "Что-то пошло не так..."
 exit $UE_REQUEST
fi
# Экспортируем переменные
export XAUTHORITY=$LXA
export DISPLAY=$DSPL
export HOME=$LCHOME
# Запускаемся
echo "'$CMND' выполняется в следующем окружении:"
sudo -u $TMPUSER env
echo "------------ далее следует вывод выполняемой команды ------------"
sudo -u $TMPUSER $CMND
CMDEXIT_REQUEST=$?
echo "---------------- конец вывода выполняемой команды ----------------"
echo "'$CMND' завершилась с кодом: $CMDEXIT_REQUEST"
# Удаляем файл авторизации
# Тут нам потребуется судо
sudo true
if [ "$?" != "0" ]
then
 echo "$0: провал авторизации"
 echo "Файл авторизации X-сервера ($LXA) не будет удалён"
 if [ "$PLACE" = "t" ]
 then
  echo "Временная домашняя директория ($LCHOME) не будет удалёна"
  echo "Файл-указатель ($LCLCHOME) не будет удалён"
 fi
 exit $SUDOFAIL_REQUEST
fi
sudo rm -f "$LXA"

if [ "$PLACE" = "t" ]
then 
 # Удаляем домашний каталог
 sleep 8
 # Мы должны быть уверены что:
  # 1 Переменная $LCHOME всё ещё указывает на созданный нами каталог
  # 2 Нет больше ни одной копии tudo которая его использует
 if [ -e "$LCLCHOME" -a  -e "$LCHOME" ]
 then
  LCLCHOMECNT=`cat "$LCLCHOME"`
  if [ "$LCHOME" = "$LCLCHOMECNT" -a "$LCHOME" != "" ]
  then
   sudo rm -rf "$LCHOME"
   rm -f "$LCLCHOME"
  else
   echo "Что-то пошло не так при попытке удалить временный домашний каталог '$LCHOME' ..."
   echo "Удалите '$LCHOME' вручную если он действительно не нужен."
   exit $UE_REQUEST
  fi
 else
  echo "Что-то пошло не так при попытке удалить временный домашний каталог '$LCHOME' ..."
  echo "Удалите '$LCHOME' вручную если он действительно не нужен."
  exit $UE_REQUEST
 fi
fi
exit $CMDEXIT_REQUEST
 
Кидаем его в /usr/sbin, обозвав tudo.
Синтаксис такой: tudo от_кого опиция что_запустить
 
2.) Способ
sudo apt-get install sux
sux от_кого что_запустить :-) 

Комментариев нет:

Отправить комментарий