chroot-browser.sh 7.9 KB
Newer Older
1 2
#!/bin/sh

3 4
# This shell library is meant to be used with `set -e`.

5 6 7 8 9
if [ "$(whoami)" != "root" ]; then
    echo "This library is useless for non-root users. Exiting..." >&2
    exit 1
fi

10 11
# Import the TBB_INSTALL, TBB_PROFILE and TBB_EXT variables, and
# configure_xulrunner_app_locale().
12 13
. /usr/local/lib/tails-shell-library/tor-browser.sh

14 15 16
# Import windows_camouflage_is_enabled()
. /usr/local/lib/tails-shell-library/tails-greeter.sh

Tails developers's avatar
Tails developers committed
17 18 19
# Import try_for().
. /usr/local/lib/tails-shell-library/common.sh

20 21 22 23 24
# Break down the chroot and kill all of its processes
try_cleanup_browser_chroot () {
    local chroot="${1}"
    local cow="${2}"
    local user="${3}"
25
    try_for 10 "pkill -u ${user} 1>/dev/null 2>&1" 0.1 || \
26
        pkill -9 -u "${user}" 1>/dev/null 2>&1 || :
27
    for mnt in "${chroot}"/dev "${chroot}"/proc "${chroot}" "${cow}"; do
28
        try_for 10 "umount ${mnt} 2>/dev/null" 0.1
29
    done
30
    rmdir "${cow}" "${chroot}" 2>/dev/null
31
}
32 33 34 35 36

# Setup a chroot on a clean aufs "fork" of the root filesystem.
setup_browser_chroot () {
    local chroot="${1}"
    local cow="${2}"
37 38
    local user="${3}"

39 40 41
    # FIXME: When LXC matures to the point where it becomes a viable option
    # for creating isolated jails, the chroot can be used as its rootfs.

42 43
    local cleanup_cmd="try_cleanup_browser_chroot \"${chroot}\" \"${cow}\" \"${user}\""
    trap "${cleanup_cmd}" INT EXIT
44 45

    local rootfs_dir
46 47
    local rootfs_dirs_path="/lib/live/mount/rootfs"
    local tails_module_path="/lib/live/mount/medium/live/Tails.module"
48 49 50 51 52 53 54 55 56 57 58 59 60
    local aufs_dirs=

    # We have to pay attention to the order we stack the filesystems;
    # newest must be first, and remember that the .module file lists
    # oldest first, newest last.
    while read rootfs_dir; do
        rootfs_dir="${rootfs_dirs_path}/${rootfs_dir}"
        mountpoint -q "${rootfs_dir}" && \
        aufs_dirs="${rootfs_dir}=rr+wh:${aufs_dirs}"
    done < "${tails_module_path}"
    # But our copy-on-write dir must be at the very top.
    aufs_dirs="${cow}=rw:${aufs_dirs}"

61 62 63 64 65
    mkdir -p "${cow}" "${chroot}" && \
    mount -t tmpfs tmpfs "${cow}" && \
    mount -t aufs -o "noatime,noxino,dirs=${aufs_dirs}" aufs "${chroot}" && \
    mount -t proc proc "${chroot}"/proc && \
    mount --bind /dev "${chroot}"/dev || \
66
        return 1
67 68

    # Workaround for #6110
69
    chmod -t "${cow}"
70
}
71

72 73 74 75 76 77 78 79 80 81 82 83
chroot_browser_conf_dir () {
    local chroot="${1}"
    local browser_name="${2}"
    local browser_user="${3}"
    echo "${chroot}/home/${browser_user}/.${browser_name}"
}

chroot_browser_profile_dir () {
    local conf_dir="$(chroot_browser_conf_dir "${@}")"
    echo "${conf_dir}/profile.default"
}

84 85
set_chroot_browser_locale () {
    local chroot="${1}"
86 87 88
    local browser_name="${2}"
    local browser_user="${3}"
    local locale="${4}"
89
    local browser_profile="$(chroot_browser_profile_dir "${chroot}" "${browser_name}" "${browser_user}")"
90 91 92
    configure_xulrunner_app_locale "${browser_profile}" "${locale}"
}

93 94 95 96
set_chroot_browser_name () {
    local chroot="${1}"
    local name="${2}"
    local locale="${3}"
97
    local ext_dir="${chroot}/${TBB_EXT}"
98
    local pack top rest
99
    if [ "${locale}" != "en-US" ]; then
100
        pack="${ext_dir}/langpack-${locale}@firefox.mozilla.org.xpi"
101 102
        top="browser/chrome"
        rest="${locale}/locale"
103 104
    else
        pack="${chroot}/${TBB_INSTALL}/browser/omni.ja"
105 106
        top="chrome"
        rest="en-US/locale"
107
    fi
108
    local tmp="$(mktemp -d)"
109 110 111 112 113 114 115 116 117
    local branding="${top}/${rest}/branding/brand.dtd"
    # Non-zero exit code due to non-standard ZIP archive.
    # The following steps will fail soon if the extraction failed anyway.
    7z x -o"${tmp}" "${pack}" "${branding}" || true
    sed -i "s/<"'!'"ENTITY\s\+brand\(Full\|Short\)Name.*$/<"'!'"ENTITY brand\1Name \"${name}\">/" "${tmp}/${branding}"
    (cd ${tmp} ; 7z u -tzip "${pack}" .)
    chmod a+r "${pack}"
    rm -Rf "${tmp}"
}
118 119

# Start the browser in the chroot
120
run_browser_in_chroot () {
121
    local chroot="${1}"
122 123 124
    local browser_name="${2}"
    local chroot_user="${3}"
    local local_user="${4}"
125 126 127 128 129

    sudo -u ${local_user} xhost +SI:localuser:${chroot_user} 2>/dev/null
    chroot ${chroot} sudo -u ${chroot_user} /bin/sh -c \
        '. /usr/local/lib/tails-shell-library/tor-browser.sh && \
         exec_firefox -DISPLAY=:0.0 \
130
                      -profile '"/home/${chroot_user}/.${browser_name}/profile.default"
131 132
    sudo -u ${local_user} xhost -SI:localuser:${chroot_user} 2>/dev/null
}
133 134 135 136 137 138

# TorButton forces the Browser name to Tor Browser unless we alter its
# branding files a bit.
set_chroot_torbutton_browser_name () {
    local chroot="${1}"
    local name="${2}"
139 140 141 142 143 144 145
    local locale="${3}"
    local torbutton_locale_dir="${chroot}"/usr/share/xul-ext/torbutton/chrome/locale/${locale}
    if [ ! -d "${torbutton_locale_dir}" ]; then
        # Surprisingly, the default locale is en, not en-US
        torbutton_locale_dir="${chroot}"/usr/share/xul-ext/torbutton/chrome/locale/en
    fi
    sed -i "s/<"'!'"ENTITY\s\+brand\(Full\|Short\)Name.*$/<"'!'"ENTITY brand\1Name \"${name}\">/" "${torbutton_locale_dir}/brand.dtd"
146
}
147 148 149 150 151 152 153 154

# Set the chroot's DNS servers (IPv4 only)
configure_chroot_dns_servers () {
    local chroot="${1}" ; shift
    local ip4_nameservers="${@}"

    rm -f ${chroot}/etc/resolv.conf
    for ns in ${ip4_nameservers}; do
155
        echo "nameserver ${ns}" >> "${chroot}/etc/resolv.conf"
156 157 158 159 160 161
    done
    chmod a+r ${chroot}/etc/resolv.conf
}

set_chroot_browser_permissions () {
    local chroot="${1}"
162 163
    local browser_name="${2}"
    local browser_user="${3}"
164
    local browser_conf="$(chroot_browser_conf_dir "${chroot}" "${browser_name}" "${browser_user}")"
165
    chown -R "${browser_user}:${browser_user}" "${browser_conf}"
166 167 168 169 170 171 172
}

configure_chroot_browser () {
    local chroot="${1}" ; shift
    local browser_name="${1}" ; shift
    local browser_user="${1}" ; shift
    local startpage="${1}" ; shift
173 174
    # Now $@ is a list of paths (that must be valid after chrooting)
    # to extensions to enable.
175 176

    # Prevent sudo from complaining about failing to resolve the 'amnesia' host
177
    echo "127.0.0.1 localhost amnesia" > "${chroot}/etc/hosts"
178 179

    # Create a fresh browser profile for the clearnet user
180 181
    local browser_conf="$(chroot_browser_conf_dir "${chroot}" "${browser_name}" "${browser_user}")"
    local browser_profile="$(chroot_browser_profile_dir "${chroot}" "${browser_name}" "${browser_user}")"
182
    local browser_ext="${browser_profile}/extensions"
183 184 185
    mkdir -p "${browser_profile}" "${browser_ext}"

    # Select extensions to enable
186 187 188 189 190
    local extension
    while [ -n "${*}" ]; do
        extension="${1}" ; shift
        ln -s "${extension}" "${browser_ext}"
    done
191 192

    # Set preferences
193
    local browser_prefs="${browser_profile}/preferences/prefs.js"
194
    mkdir -p "$(dirname "${browser_prefs}")"
195
    cp /usr/share/tails/"${browser_name}/prefs.js" "${browser_prefs}"
196 197

    # Set start page to something that explains what's going on
198 199 200 201
    if [ -n "${startpage}" ]; then
        echo 'user_pref("browser.startup.homepage", "'"${startpage}"'");' >> \
            "${browser_prefs}"
    fi
202 203 204 205

    # Customize the GUI
    local browser_chrome="${browser_profile}/chrome/userChrome.css"
    mkdir -p "$(dirname "${browser_chrome}")"
206
    cp /usr/share/tails/"${browser_name}"/userChrome.css "${browser_chrome}"
207 208

    # Remove all bookmarks
Tails developers's avatar
Tails developers committed
209
    rm "${chroot}/${TBB_PROFILE}/bookmarks.html"
210 211 212 213 214 215 216 217

    # Set an appropriate theme, except if we're using Windows
    # camouflage.
    if ! windows_camouflage_is_enabled; then
        cat /usr/share/tails/"${browser_name}"/theme.js >> "${browser_prefs}"
    else
        # The tails-activate-win8-theme script requires that the
        # browser profile is writable by the user running the script.
218
        set_chroot_browser_permissions "${chroot}" "${browser_user}"
219 220
        # The camouflage activation script requires a dbus server for
        # properly configuring GNOME, so we start one in the chroot
221
        chroot "${chroot}" sudo -H -u "${browser_user}" sh -c 'eval `dbus-launch --auto-syntax`; tails-activate-win8-theme' || :
222 223
    fi
}