Я создал демоноподобную программу, которая запускает сеанс X11 для конкретного пользователя в его собственной среде после того, как он аутентифицируется.
Первым подходом было использование команды с использованием system()
, где я бы выдал себя за пользователя и запустил сеанс x11 следующим образом:
std::string cmd = "echo daemonuserpwd | sudo -S su " + unixUser + " -c 'xinit -- :4' &";
system(cmd.c_str());
Это работает безупречно и вызывает *Файл 1007 *, расположенный в домашнем каталоге пользователя, что является необходимым шагом, поскольку я использую его для запуска необходимых программ, которые мне нужны для приложения, в котором я работаю.
Однако я прочитал о проблемах.с system()
, поэтому я попытался пойти немного дальше и использовать fork для создания пользовательской среды и начать сеанс, используя execl()
, следующим образом:
int child = fork();
if(child == 0)
{
struct passwd * userInfo = getpwnam(unixUser.c_str());
setgid(userInfo->pw_gid);
setuid(userInfo->pw_uid);
system("whoami");
execl("/usr/bin/xinit", "xinit", "--", ":4", (char*)0);
//system("xinit -- :4");
}
Это также работает, команда отладки system("whoami");
говорит, что я правильный пользователь.Сеанс X11 запущен, однако файл .xinitrc
не вызывается при запуске сеанса из процесса fork.Я также попытался выполнить команду с системой, после настройки пользовательской среды, с тем же результатом (обе опции вызывают значение по умолчанию xinitrc
в /etc/X11/xinit/xinitrc
.
Я что-то упускаю в порядке .xinitrc
файл, который также будет вызываться при использовании подхода fork()
?
Отказ от ответственности: аутентификация пользователя выполняется с помощью libpam, и пользовательский ввод должным образом очищается для предотвращения инъекций.
РЕДАКТИРОВАТЬ: Окончательный обходной путь с использованием execle
, как предложено @LieRyan:
struct passwd * userInfo = getpwnam(unixUser.c_str());
char buf[0xff];
sprintf(buf, "HOME=%s", userInfo->pw_dir);
char *env[] = {buf, NULL};
execle("/usr/bin/sudo", "sudo", "-u", unixUser.c_str(), "xinit", "--", ":4", (char*)0, env);