10-tbb 11.5 KB
Newer Older
1
2
#!/bin/sh

3
4
set -e
set -u
5
6
7

echo "Install the Tor Browser"

8
9
10
11
12
13
14
# Import the TBB_INSTALL, TBB_PROFILE, TBB_EXT and
# TOR_LAUNCHER_INSTALL variables, which contains the paths we will
# split TBB's actual browser (binaries etc), user data and extension
# into. While this differs from how the TBB organizes the files, the
# end result will be the same, and it's practical since when creating
# a new browser profile we can simply copy the profile directory
# without duplicating all extensions.
15
. /usr/local/lib/tails-shell-library/tor-browser.sh
16
17
# Import install_fake_package
. /usr/local/lib/tails-shell-library/build.sh
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

download_and_verify_files() {
    local base_url bundles destination apt_proxy
    base_url="${1}"
    bundles="${2}"
    destination="${3}"

    # Use the builder's caching APT proxy, if any
    apt_proxy="$(apt-config --format '%v' dump Acquire::http::Proxy)"
    if [ -n "${apt_proxy}" ]; then
        export HTTP_PROXY="${apt_proxy}"
        export http_proxy="${apt_proxy}"
        export HTTPS_PROXY="${apt_proxy}"
        export https_proxy="${apt_proxy}"
    fi

    echo "${bundles}" | while read expected_sha256 tarball; do
        (
            cd "${destination}"
            echo "Fetching ${base_url}/${tarball} ..."
38
            curl --retry 20 --remote-name "${base_url}/${tarball}"
39
40
41
42
43
44
45
46
47
        )
        actual_sha256="$(sha256sum "${destination}/${tarball}" | cut -d' ' -f1)"
        if [ "${actual_sha256}" != "${expected_sha256}" ]; then
            echo "SHA256 mismatch for ${tarball}" >&2
            exit 1
        fi
    done
}

48
install_tor_browser() {
49
    local bundle destination tmp prep torlauncher_xpi_path torlauncher_version
50
51
52
53
    bundle="${1}"
    destination="${2}"

    tmp="$(mktemp -d)"
54
55
56
57
58
59
60
61
62
63
    tar -xf "${bundle}" -C "${tmp}"
    if [ -d "${tmp}"/tor-browser_en-US ]; then
        prep="${tmp}"/tor-browser_en-US/Browser
    elif [ -d "${tmp}"/tor-browser ]; then
        # TBB nightly builds
        prep="${tmp}"/tor-browser/Browser
    else
        echo "The main bundle's top level directory is wrong" >&2
        exit 1
    fi
64
65
66
67

    # Enable our myspell/hunspell dictionaries. TBB only provides the
    # one for en-US, but Debian's seems more comprehensive, so we'll
    # only use Debian's dictionaries.
68
    rm -f "${prep}"/dictionaries/*
69
    for f in /usr/share/hunspell/*.aff /usr/share/hunspell/*.dic; do
Tails developers's avatar
Tails developers committed
70
        ln -s "${f}" "${prep}"/dictionaries/
71
72
    done

intrigeri's avatar
intrigeri committed
73
74
    # Let's use the libstdc++ that the Tor Browser is intended to be used with,
    # instead of the system one.
75
76
77
78
    cp "${prep}"/TorBrowser/Tor/libstdc++.so.6 "${prep}"

    # We don't need the Tor binary, the shared libraries Tor needs
    # (but Firefox doesn't) and documentation shipped in the TBB.
79
80
    rm -r "${prep}"/TorBrowser/Tor "${prep}"/TorBrowser/Docs

81
    # We don't want tor-launcher to be part of the regular browser
82
83
84
    # profile but we want to keep it as a standalone application
    # when Tails is started in "bridge mode".
    torlauncher_xpi_path="${prep}/TorBrowser/Data/Browser/profile.default/extensions/tor-launcher@torproject.org.xpi"
85
    7z x -o"${TOR_LAUNCHER_INSTALL}" "${torlauncher_xpi_path}"
86
87
    torlauncher_version="$(sed -n \
        's,^        <em:version>\([0-9\.]\+\)</em:version>,\1,p' \
88
89
        "${TOR_LAUNCHER_INSTALL}/install.rdf")"
    cat > "${TOR_LAUNCHER_INSTALL}/application.ini" << EOF
90
91
92
93
94
95
96
97
98
99
100
101
102
103
[App]
Vendor=TorProject
Name=TorLauncher
Version=${torlauncher_version}
BuildID=$(date +%Y%m%d)
ID=tor-launcher@torproject.org

[Gecko]
MinVersion=$(get_firefox_version "${prep}/application.ini")
MaxVersion=*.*.*

[Shell]
Icon=icon.png
EOF
104
    chmod -R a+rX "${TOR_LAUNCHER_INSTALL}"
105
    rm "${torlauncher_xpi_path}"
106
107

    # The Tor Browser will fail, complaining about an incomplete profile,
108
    # unless there's a readable TorBrowser/Data/Browser/Caches
109
    # in the directory where the firefox executable is located.
110
111
112
    mkdir -p "${prep}"/TorBrowser/Data/Browser/Caches

    mv "${prep}" "${destination}"
113
114
115
116

    rm -r "${tmp}"
}

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# TBB workes around the lack of code signing for its extensions by
# hacking in exceptions. We do the same!
apply_extension_code_signing_hacks () {
    local destination tmp
    destination="${1}"

    tmp="$(mktemp -d)"
    (
        cd "${tmp}"
        7z x -tzip "${TBB_INSTALL}/omni.ja" \
           modules/addons/XPIProvider.jsm \
           chrome/toolkit/content/mozapps/extensions/extensions.js
        patch -p1 <<EOF
diff -Naur a/chrome/toolkit/content/mozapps/extensions/extensions.js b/chrome/toolkit/content/mozapps/extensions/extensions.js
--- a/chrome/toolkit/content/mozapps/extensions/extensions.js 2000-01-01 00:00:00.000000000 +0000
+++ b/chrome/toolkit/content/mozapps/extensions/extensions.js 2000-01-01 00:00:00.000000000 +0000
@@ -282,7 +282,9 @@
   // they aren't the correct type for signing.
   if (aAddon.id == "torbutton@torproject.org" ||
       aAddon.id == "tor-launcher@torproject.org" ||
-      aAddon.id == "https-everywhere-eff@eff.org") {
+      aAddon.id == "https-everywhere-eff@eff.org" ||
+      aAddon.id == "branding@amnesia.boum.org" ||
+      aAddon.id == "uBlock0@raymondhill.net") {
     return true;
   }
   return aAddon.isCorrectlySigned !== false;
diff -Naur a/modules/addons/XPIProvider.jsm b/modules/addons/XPIProvider.jsm
--- a/modules/addons/XPIProvider.jsm 2000-01-01 00:00:00.000000000 +0000
+++ b/modules/addons/XPIProvider.jsm 2000-01-01 00:00:00.000000000 +0000
@@ -749,7 +749,9 @@
   if (aAddon.id == "torbutton@torproject.org" ||
       aAddon.id == "tor-launcher@torproject.org" ||
       aAddon.id == "https-everywhere-eff@eff.org" ||
-      aAddon.id == "meek-http-helper@bamsoftware.com") {
+      aAddon.id == "meek-http-helper@bamsoftware.com" ||
+      aAddon.id == "branding@amnesia.boum.org" ||
+      aAddon.id == "uBlock0@raymondhill.net") {
     return true;
   }
EOF
        7z u -tzip "${TBB_INSTALL}/omni.ja" \
           modules/addons/XPIProvider.jsm \
           chrome/toolkit/content/mozapps/extensions/extensions.js

        7z x -tzip "${TBB_INSTALL}/browser/omni.ja" \
           components/nsBrowserGlue.js
        patch -p1 <<EOF
diff -Naur x/components/nsBrowserGlue.js y/components/nsBrowserGlue.js
--- a/components/nsBrowserGlue.js 2000-01-01 00:00:00.000000000 +0000
+++ b/components/nsBrowserGlue.js 2000-01-01 00:00:00.000000000 +0000
@@ -1122,7 +1122,9 @@
           if ((addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) &&
               !(addon.id == "torbutton@torproject.org" ||
                 addon.id == "tor-launcher@torproject.org" ||
-                addon.id == "https-everywhere-eff@eff.org")) {
+                addon.id == "https-everywhere-eff@eff.org" ||
+                addon.id == "branding@amnesia.boum.org" ||
+                addon.id == "uBlock0@raymondhill.net")) {
             this._notifyUnsignedAddonsDisabled();
             break;
           }
EOF
        7z u -tzip "${TBB_INSTALL}/browser/omni.ja" \
           components/nsBrowserGlue.js
        # These binaries are generated from the above modified files
anonym's avatar
anonym committed
183
184
185
        # so we have to remove them. This will have a performance
        # impact that probably is unnoticeable for humans, but TBB 7.5
        # won't ship any of these binaries any way, so we'll converge.
186
187
188
189
190
191
192
        7z d -tzip "${TBB_INSTALL}/omni.ja" \
           jsloader/resource/gre/modules/addons/XPIProvider.jsm
        7z d -tzip "${TBB_INSTALL}/browser/omni.ja" \
           jsloader/resource/app/components/nsBrowserGlue.js
    )
}

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
install_langpacks_from_bundles() {
    local bundles_dir destination
    bundles_dir="${1}"
    destination="${2}"

    for tarball in "${bundles_dir}"/tor-browser-*.tar.xz; do
        locale="$(echo "${tarball}" | sed "s@^.*/tor-browser-.*_\(.*\)\.tar\.xz@\1@")"
        if [ "${locale}" = en-US ]; then
            continue
        fi
        xpi="tor-browser_${locale}/Browser/TorBrowser/Data/Browser/profile.default/extensions/langpack-${locale}@firefox.mozilla.org.xpi"
        (
            cd "${bundles_dir}"
            tar -xf "${tarball}" "${xpi}"
            mv "${xpi}" "${destination}"
        )
    done
}

212
213
214
215
216
217
218
219
get_firefox_version() {
    # The application.ini file
    local appini
    appini="${1}"
    sed -n 's/^Version=\(.*\)$/\1/p' "${appini}"
}

install_debian_extensions() {
220
221
    local destination
    destination="${1}"
222
    shift
223
    apt-get install --yes "${@}"
spriver's avatar
spriver committed
224
225
    ln -s /usr/share/xul-ext/ublock-origin/ \
          "${destination}"/'uBlock0@raymondhill.net'
226
227
}

228
create_default_profile() {
229
230
231
    local tbb_profile extensions_dir destination
    tbb_profile="${1}"
    tbb_extensions_dir="${2}"
232
233
234
    destination="${3}"

    rsync -a --exclude bookmarks.html --exclude extensions \
235
          "${tbb_profile}"/ "${destination}"/
236
237
238
239
240

    # Remove TBB's default bridges
    sed -i '/extensions\.torlauncher\.default_bridge\./d' "${destination}"/preferences/extension-overrides.js

    mkdir -p "${destination}"/extensions
241
    for ext in "${tbb_extensions_dir}"/*; do
242
243
244
245
        ln -s "${ext}" "${destination}"/extensions/
    done
}

Tails developers's avatar
Tails developers committed
246
TBB_SHA256SUMS_FILE=/usr/share/tails/tbb-sha256sums.txt
247
TBB_TARBALLS="$(grep "\<tor-browser-linux64-.*\.tar.xz$" "${TBB_SHA256SUMS_FILE}")"
248

Tails developers's avatar
Tails developers committed
249
250
# We'll use the en-US bundle as our basis; only langpacks will be
# installed from the other bundles.
251
252
253
254
255
256
257
258
MAIN_TARBALL="$(echo "${TBB_TARBALLS}" | grep -o "tor-browser-linux64-.*_en-US.tar.xz" || :)"
NIGHTLY_BUILD=
if [ -z "${MAIN_TARBALL}" ] && [ "$(echo $TBB_TARBALLS | awk '{ print $2 }')" = 'tor-browser-linux64-tbb-nightly_ALL.tar.xz' ]; then
    # Except for TBB nightly builds; then there is only one bundle
    # containing all langbacks
    MAIN_TARBALL='tor-browser-linux64-tbb-nightly_ALL.tar.xz'
    NIGHTLY_BUILD=yes
fi
Tails developers's avatar
Tails developers committed
259
TBB_DIST_URL_FILE=/usr/share/tails/tbb-dist-url.txt
260
TBB_TARBALLS_BASE_URL="$(cat "${TBB_DIST_URL_FILE}")"
261

262
263
# The Debian Iceweasel extensions we want to install and make
# available in the Tor Browser.
spriver's avatar
spriver committed
264
DEBIAN_EXT_PKGS="xul-ext-ublock-origin"
265

266
TMP="$(mktemp -d)"
Tails developers's avatar
Tails developers committed
267
download_and_verify_files "${TBB_TARBALLS_BASE_URL}" "${TBB_TARBALLS}" "${TMP}"
268

Tails developers's avatar
Tails developers committed
269
install_tor_browser "${TMP}/${MAIN_TARBALL}" "${TBB_INSTALL}"
270
apply_extension_code_signing_hacks "${TBB_INSTALL}"
271

272
mkdir -p "${TBB_EXT}"
273
274
275
if [ "${NIGHTLY_BUILD}" != yes ]; then
    install_langpacks_from_bundles "${TMP}" "${TBB_EXT}"
fi
276

277
278
rm -r "${TMP}"

Tails developers's avatar
Tails developers committed
279
# Let's put all the extensions from TBB in the global extensions
280
# directory...
281
282
mv "${TBB_INSTALL}"/TorBrowser/Data/Browser/profile.default/extensions/* "${TBB_EXT}"
rmdir "${TBB_INSTALL}"/TorBrowser/Data/Browser/profile.default/extensions
283

284
285
# ... and then install a few Iceweasel extension by using a fake
# Iceweasel equivs package to satisfy the dependencies.
286
FIREFOX_VERSION=$(get_firefox_version "${TBB_INSTALL}"/application.ini)
287
FAKE_ICEWEASEL_VERSION=${FIREFOX_VERSION}+fake1
288
install_fake_package iceweasel "${FAKE_ICEWEASEL_VERSION}" web
289
install_debian_extensions "${TBB_EXT}" ${DEBIAN_EXT_PKGS}
290

291
mkdir -p "${TBB_PROFILE}"
292
create_default_profile "${TBB_INSTALL}"/TorBrowser/Data/Browser/profile.default "${TBB_EXT}" "${TBB_PROFILE}"
293

294
295
296
297
# Create a copy of the Firefox binary, for use e.g. by Tor Launcher.
# It won't be subject to AppArmor confinement.
cp -a "${TBB_INSTALL}/firefox" "${TBB_INSTALL}/firefox-unconfined"

298
299
chown -R root:root "${TBB_INSTALL}" "${TBB_PROFILE}" "${TBB_EXT}"
chmod -R a+rX "${TBB_INSTALL}" "${TBB_PROFILE}" "${TBB_EXT}"
300

Tails developers's avatar
Tails developers committed
301
# Make the Tor Browser into the system's default web browser
302
303
update-alternatives --install /usr/bin/x-www-browser x-www-browser /usr/local/bin/tor-browser 99
update-alternatives --install /usr/bin/gnome-www-browser gnome-www-browser /usr/local/bin/tor-browser 99
304
sed 's/\<firefox-esr\.desktop\>/tor-browser.desktop/' \
305
306
307
    /usr/share/applications/gnome-mimeapps.list \
    > /etc/xdg/gnome-mimeapps.list
chmod 644 /etc/xdg/gnome-mimeapps.list