| #!/bin/sh | |
| # Copyright 2018 The ChromiumOS Authors | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| # Perform login tasks for shill. This script is called by the "login" | |
| # init script. | |
| # Shill expects to find a user profile in /run/shill/user_profiles. We | |
| # link this path to the user profile in the user's cryptohome store so | |
| # if shill restarts while the user is logged in, shill can regain access | |
| # to the profile. | |
| set -e | |
| # The login init script calls this script with the login name of the | |
| # user whose profile is being loaded. | |
| user="$1" | |
| script_name="$(basename "$0")" | |
| profile_user="chronos" | |
| profile_name="~${profile_user}/shill" | |
| shill_state_root="/run/shill" | |
| profile_link_root="${shill_state_root}/user_profiles" | |
| profile_link_dir="${profile_link_root}/${profile_user}" | |
| username_hash="" | |
| if [ -z "${user}" ]; then | |
| logger -t "${script_name}" "Unexpected empty user" | |
| exit 1 | |
| fi | |
| # We should not load multiple network profiles. If a profile link | |
| # directory already exists, we should go no further. | |
| if [ -e "${profile_link_dir}" ]; then | |
| logger -t "${script_name}" "User already logged in; doing nothing." | |
| exit 0 | |
| fi | |
| system_path="$(cryptohome-path system "${user}")" | |
| profile_base="/run/daemon-store/shill" | |
| if [ ! -d "${profile_base}" ]; then | |
| logger -t "${script_name}" \ | |
| "Daemon-store dir ${profile_base} does not exist" | |
| exit 1 | |
| fi | |
| username_hash="$(basename "${system_path}")" | |
| profile_dir="${profile_base}/${username_hash}" | |
| profile="${profile_dir}/shill.profile" | |
| if [ ! -d "${profile_dir}" ]; then | |
| if ! mkdir -p --mode=700 "${profile_dir}"; then | |
| logger -t "${script_name}" \ | |
| "Failed to create shill user profile directory ${profile_dir}" | |
| exit 1 | |
| fi | |
| fi | |
| # We need to ensure this dir (and files within it) are owned by shill:shill, | |
| # regardless of whether we are creating it on this login or it already existed | |
| # before now. By default, the 'chown -R' command does not follow symlinks, so | |
| # there is no way shill can put a symlink in this dir as means of tricking the | |
| # system into making other files owned by 'shill'. Also, this being the "shill | |
| # user profile directory", it is fine to give shill ownership of all of its | |
| # contents. Although 'chown -R' doesn't follow symlinks, it does affect bind | |
| # mounts, so this code is only safe as long as shill runs without | |
| # CAP_SYS_ADMIN. Ideally we should have some kind of test to make sure shill | |
| # capabilities are never widened to include CAP_SYS_ADMIN -- filed | |
| # crbug.com/869170 to track this issue in the general sense for CrOS system | |
| # services. | |
| if ! chown -R shill:shill "${profile_dir}"; then | |
| logger -t "${script_name}" \ | |
| "Failed to chown shill user profile directory ${profile_dir}" | |
| exit 1 | |
| fi | |
| if ! mkdir -p --mode 0700 "${profile_link_root}"; then | |
| logger -t "${script_name}" \ | |
| "Unable to create shill user profile link directory" | |
| else | |
| if ! chown shill:shill "${profile_link_root}"; then | |
| logger -t "${script_name}" \ | |
| "Unable to chown shill user profile link directory" | |
| fi | |
| fi | |
| ln -s "${profile_dir}" "${profile_link_dir}" || | |
| logger -t "${script_name}" \ | |
| "Failed to create shill user cryptohome link ${profile_link_dir}" | |
| # wait_for_shill_dbus_services polls for the org.chromium.flimflam | |
| # in the org.freedesktop.DBus.ListNames list that has all connected | |
| # names on the Bus. | |
| wait_for_shill_dbus_services() { | |
| for _ in $(seq 1 15); do | |
| if dbus-send --system --print-reply --dest=org.freedesktop.DBus \ | |
| /org/freedesktop/DBus org.freedesktop.DBus.ListNames | | |
| grep -q '"org.chromium.flimflam"'; then | |
| return 0 | |
| fi | |
| sleep 0.2 | |
| done | |
| } | |
| # Technically, there's no guarantee that Shill has finished initializing | |
| # before a login event happens. In practice, we don't experience that | |
| # race unless Shill is actively crashing, but it does occur in tests | |
| # (where we may intentionally restart Shill). | |
| wait_for_shill_dbus_services | |
| if [ ! -f "${profile}" ]; then | |
| # If profile does not exist, ask shill to create one. | |
| dbus-send --system --dest=org.chromium.flimflam --print-reply / \ | |
| org.chromium.flimflam.Manager.CreateProfile string:"${profile_name}" || | |
| logger -t "${script_name}" "Failed to create ${profile_name} profile" | |
| fi | |
| # Push user's network profile | |
| dbus-send --system --dest=org.chromium.flimflam --print-reply / \ | |
| org.chromium.flimflam.Manager.InsertUserProfile \ | |
| string:"${profile_name}" string:"${username_hash}" || | |
| logger -t "${script_name}" "Failed to push ${profile_name} profile" |