Commit cbef6677 authored by rkjnsn's avatar rkjnsn Committed by Commit bot

Add PAM session wrapper

Adds a wrapper to launch me2me script in a proper PAM session.

BUG=616962

Review-Url: https://codereview.chromium.org/2323153002
Cr-Commit-Position: refs/heads/master@{#435044}
parent b7153161
......@@ -80,6 +80,7 @@ action("remoting_me2me_host_deb_installer") {
"//remoting/host:remoting_native_messaging_manifests",
"//remoting/host:remoting_start_host",
"//remoting/host/it2me:remote_assistance_host",
"//remoting/host/linux:remoting_user_session",
"//remoting/resources",
"//third_party/icu:icudata",
]
......
......@@ -19,6 +19,8 @@ ME2ME_PROGNAME = $(BUILD_DIR)/remoting_me2me_host
ME2ME_DEBUGFILE = $(ME2ME_PROGNAME).debug
START_PROGNAME = $(BUILD_DIR)/remoting_start_host
START_DEBUGFILE = $(START_PROGNAME).debug
SESSION_WRAPPER_PROGNAME = $(BUILD_DIR)/remoting_user_session
SESSION_WRAPPER_DEBUGFILE = $(SESSION_WRAPPER_PROGNAME).debug
ME2ME_NM_PROGNAME = $(BUILD_DIR)/remoting_native_messaging_host
ME2ME_NM_DEBUGFILE = $(ME2ME_NM_PROGNAME).debug
REMOTE_ASSISTANCE_PROGNAME = $(BUILD_DIR)/remote_assistance_host
......@@ -53,6 +55,9 @@ install:
eu-strip -f "$(START_DEBUGFILE)" "$(START_PROGNAME)"
install "$(START_PROGNAME)" "$(INSTALL_DIR)/start-host"
eu-strip -f "$(SESSION_WRAPPER_DEBUGFILE)" "$(SESSION_WRAPPER_PROGNAME)"
install "$(SESSION_WRAPPER_PROGNAME)" "$(INSTALL_DIR)/user-session"
eu-strip -f "$(ME2ME_NM_DEBUGFILE)" "$(ME2ME_NM_PROGNAME)"
install "$(ME2ME_NM_PROGNAME)" "$(INSTALL_DIR)/native-messaging-host"
......
......@@ -12,6 +12,7 @@
# /etc/init.d/chrome-remote-desktop: Start and stop Chrome Remote Desktop host daemon.
HOST_PATH=/opt/google/chrome-remote-desktop/chrome-remote-desktop
USER_SESSION_PATH=/opt/google/chrome-remote-desktop/user-session
# Group of users for which Chrome Remote Desktop is enabled. Users are added
# to that group when they start the host for the first time.
......@@ -46,47 +47,46 @@ run_with_timeout() {
return 1
}
# Usage: run_and_ignore_error [--login] user program [args...]
# --login:
# Run program in a clean login shell. This requires backgrounding, since
# the user's .profile or .login script might be run, which might contain
# blocking commands.
# Usage: run_and_ignore_error user action
# Carries out the specified action, ignoring any errors.
# action:
# --start is handled specially using the user-session wrapper to start a
# clean log-in session. In any other case, the host script is called through
# sudo with the specified action flag.
run_and_ignore_error() {
login_options=""
if [ "$1" = "--login" ]; then
login_options="-b -i"
shift
fi
user=$1
shift
user="$1"
action="$2"
set +e
sudo -u "$user" $login_options "$@"
if [ "$action" = "--start" ]; then
"$USER_SESSION_PATH" --user="$user" --me2me-script="$HOST_PATH"
else
sudo -u "$user" "$HOST_PATH" "$action"
fi
}
do_start() {
log_begin_msg "Starting Chrome Remote Desktop host for $1..."
run_and_ignore_error --login $1 "$HOST_PATH" --start
run_and_ignore_error $1 --start
log_end_msg $?
}
do_stop() {
log_begin_msg "Stopping Chrome Remote Desktop host for $1..."
run_with_timeout run_and_ignore_error $1 "$HOST_PATH" --stop
run_with_timeout run_and_ignore_error $1 --stop
log_end_msg $?
}
do_reload() {
log_begin_msg "Reloading Chrome Remote Desktop host configuration for $1..."
run_and_ignore_error $1 "$HOST_PATH" --reload
run_and_ignore_error $1 --reload
log_end_msg $?
}
do_restart() {
log_begin_msg "Restarting Chrome Remote Desktop host for $1..."
run_and_ignore_error $1 "$HOST_PATH" --stop
run_and_ignore_error --login $1 "$HOST_PATH" --start
run_and_ignore_error $1 --stop
run_and_ignore_error $1 --start
log_end_msg $?
}
......
......@@ -5,4 +5,9 @@
@include common-auth
@include common-account
@include common-password
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
session required pam_limits.so
@include common-session
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
session required pam_env.so readenv=1
session required pam_env.so readenv=1 user_readenv=1 envfile=/etc/default/locale
......@@ -9,6 +9,18 @@ group("all_tests") {
}
if (enable_me2me_host) {
executable("remoting_user_session") {
sources = [
"remoting_user_session.cc",
]
deps = [
"//base",
]
libs = [ "pam" ]
}
copy("remoting_me2me_host_copy_script") {
sources = [
"linux_me2me_host.py",
......
......@@ -359,54 +359,62 @@ class Desktop:
display += 1
return display
def _init_child_env(self):
# Create clean environment for new session, so it is cleanly separated from
# the user's console X session.
self.child_env = {}
for key in [
"HOME",
"LANG",
"LOGNAME",
"PATH",
"SHELL",
"USER",
"USERNAME",
LOG_FILE_ENV_VAR]:
if key in os.environ:
self.child_env[key] = os.environ[key]
def _init_child_env(self, keep_env):
if keep_env:
self.child_env = dict(os.environ)
else:
# Create clean environment for new session, so it is cleanly separated
# from the user's console X session.
self.child_env = {}
for key in [
"HOME",
"LANG",
"LOGNAME",
"PATH",
"SHELL",
"USER",
"USERNAME",
LOG_FILE_ENV_VAR]:
if key in os.environ:
self.child_env[key] = os.environ[key]
# Initialize the environment from files that would normally be read in a
# PAM-authenticated session.
for env_filename in [
"/etc/environment",
"/etc/default/locale",
os.path.expanduser("~/.pam_environment")]:
if not os.path.exists(env_filename):
continue
try:
with open(env_filename, "r") as env_file:
for line in env_file:
line = line.rstrip("\n")
# Split at the first "=", leaving any further instances in the
# value.
key_value_pair = line.split("=", 1)
if len(key_value_pair) == 2:
key, value = tuple(key_value_pair)
# The file stores key=value assignments, but the value may be
# quoted, so strip leading & trailing quotes from it.
value = value.strip("'\"")
self.child_env[key] = value
except IOError:
logging.error("Failed to read file: %s" % env_filename)
# Ensure that the software-rendering GL drivers are loaded by the desktop
# session, instead of any hardware GL drivers installed on the system.
self.child_env["LD_LIBRARY_PATH"] = (
library_path = (
"/usr/lib/%(arch)s-linux-gnu/mesa:"
"/usr/lib/%(arch)s-linux-gnu/dri:"
"/usr/lib/%(arch)s-linux-gnu/gallium-pipe" %
{ "arch": platform.machine() })
# Initialize the environment from files that would normally be read in a
# PAM-authenticated session.
for env_filename in [
"/etc/environment",
"/etc/default/locale",
os.path.expanduser("~/.pam_environment")]:
if not os.path.exists(env_filename):
continue
try:
with open(env_filename, "r") as env_file:
for line in env_file:
line = line.rstrip("\n")
# Split at the first "=", leaving any further instances in the
# value.
key_value_pair = line.split("=", 1)
if len(key_value_pair) == 2:
key, value = tuple(key_value_pair)
# The file stores key=value assignments, but the value may be
# quoted, so strip leading & trailing quotes from it.
value = value.strip("'\"")
self.child_env[key] = value
except IOError:
logging.error("Failed to read file: %s" % env_filename)
if "LD_LIBRARY_PATH" in self.child_env:
library_path += ":" + self.child_env["LD_LIBRARY_PATH"]
self.child_env["LD_LIBRARY_PATH"] = library_path
def _setup_pulseaudio(self):
self.pulseaudio_pipe = None
......@@ -649,8 +657,8 @@ class Desktop:
if not self.session_proc.pid:
raise Exception("Could not start X session")
def launch_session(self, x_args):
self._init_child_env()
def launch_session(self, keep_env, x_args):
self._init_child_env(keep_env)
self._setup_pulseaudio()
self._setup_gnubby()
self._launch_x_server(x_args)
......@@ -1236,6 +1244,9 @@ Web Store: https://chrome.google.com/remotedesktop"""
action="store", metavar="USER",
help="Adds the specified user to the chrome-remote-desktop "
"group (must be run as root).")
parser.add_option("", "--keep-parent-env", dest="keep_env", default=False,
action="store_true",
help=optparse.SUPPRESS_HELP)
parser.add_option("", "--watch-resolution", dest="watch_resolution",
type="int", nargs=2, default=False, action="store",
help=optparse.SUPPRESS_HELP)
......@@ -1469,7 +1480,7 @@ Web Store: https://chrome.google.com/remotedesktop"""
relaunch_times.append(x_server_inhibitor.earliest_relaunch_time)
else:
logging.info("Launching X server and X session.")
desktop.launch_session(args)
desktop.launch_session(options.keep_env, args)
x_server_inhibitor.record_started(MINIMUM_PROCESS_LIFETIME,
backoff_time)
allow_relaunch_self = True
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment