10-tbb 12.3 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
        "${TOR_LAUNCHER_INSTALL}/install.rdf")"
89
    SOURCE_DATE_YYYYMMDD=$(date --utc --date="@$SOURCE_DATE_EPOCH" '+%Y%m%d')
90
    cat > "${TOR_LAUNCHER_INSTALL}/application.ini" << EOF
91
92
93
94
[App]
Vendor=TorProject
Name=TorLauncher
Version=${torlauncher_version}
95
BuildID=${SOURCE_DATE_YYYYMMDD}
96
97
98
99
100
101
102
103
104
ID=tor-launcher@torproject.org

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

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

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

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

    rm -r "${tmp}"
}

intrigeri's avatar
intrigeri committed
118
# TBB works around the lack of code signing for its extensions by
119
120
# hacking in exceptions. We do the same!
apply_extension_code_signing_hacks () {
121
    local destination tmp tbb_timestamp
122
123
    destination="${1}"

124
125
126
127
    # For consistency we'll set timestamps of files we modify to the
    # same one used by the Tor Browser instead of SOURCE_DATE_EPOCH.
    tbb_timestamp="$(date --date='2000-01-01 00:00:00' +%s)"

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
    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
163
164
165
        touch --date="@${tbb_timestamp}" modules/addons/XPIProvider.jsm \
              chrome/toolkit/content/mozapps/extensions/extensions.js
        7z u -mtc=off -tzip "${TBB_INSTALL}/omni.ja" \
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
           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
187
188
        touch --date="@${tbb_timestamp}" components/nsBrowserGlue.js
        7z u -mtc=off -tzip "${TBB_INSTALL}/browser/omni.ja" \
189
190
           components/nsBrowserGlue.js
        # These binaries are generated from the above modified files
anonym's avatar
anonym committed
191
192
193
        # 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.
194
        7z d -mtc=off -tzip "${TBB_INSTALL}/omni.ja" \
195
           jsloader/resource/gre/modules/addons/XPIProvider.jsm
196
        7z d -mtc=off -tzip "${TBB_INSTALL}/browser/omni.ja" \
197
           jsloader/resource/app/components/nsBrowserGlue.js
198
199
200
201
        for archive in "${TBB_INSTALL}/omni.ja" "${TBB_INSTALL}/browser/omni.ja"; do
            strip_nondeterminism_wrapper --type zip --timestamp "${tbb_timestamp}" \
                                         "${archive}" 2>/dev/null
        done
202
203
204
    )
}

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
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
}

224
225
226
227
228
229
230
231
get_firefox_version() {
    # The application.ini file
    local appini
    appini="${1}"
    sed -n 's/^Version=\(.*\)$/\1/p' "${appini}"
}

install_debian_extensions() {
232
233
    local destination
    destination="${1}"
234
    shift
235
    apt-get install --yes "${@}"
spriver's avatar
spriver committed
236
237
    ln -s /usr/share/xul-ext/ublock-origin/ \
          "${destination}"/'uBlock0@raymondhill.net'
238
239
}

240
create_default_profile() {
241
242
243
    local tbb_profile extensions_dir destination
    tbb_profile="${1}"
    tbb_extensions_dir="${2}"
244
245
246
    destination="${3}"

    rsync -a --exclude bookmarks.html --exclude extensions \
247
          "${tbb_profile}"/ "${destination}"/
248
249
250
251
252

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

    mkdir -p "${destination}"/extensions
253
    for ext in "${tbb_extensions_dir}"/*; do
254
255
256
257
        ln -s "${ext}" "${destination}"/extensions/
    done
}

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

Tails developers's avatar
Tails developers committed
261
262
# We'll use the en-US bundle as our basis; only langpacks will be
# installed from the other bundles.
263
264
265
266
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
intrigeri's avatar
intrigeri committed
267
    # containing all langpacks
268
269
270
    MAIN_TARBALL='tor-browser-linux64-tbb-nightly_ALL.tar.xz'
    NIGHTLY_BUILD=yes
fi
Tails developers's avatar
Tails developers committed
271
TBB_DIST_URL_FILE=/usr/share/tails/tbb-dist-url.txt
272
TBB_TARBALLS_BASE_URL="$(cat "${TBB_DIST_URL_FILE}")"
273

274
275
# The Debian Iceweasel extensions we want to install and make
# available in the Tor Browser.
spriver's avatar
spriver committed
276
DEBIAN_EXT_PKGS="xul-ext-ublock-origin"
277

278
TMP="$(mktemp -d)"
Tails developers's avatar
Tails developers committed
279
download_and_verify_files "${TBB_TARBALLS_BASE_URL}" "${TBB_TARBALLS}" "${TMP}"
280

Tails developers's avatar
Tails developers committed
281
install_tor_browser "${TMP}/${MAIN_TARBALL}" "${TBB_INSTALL}"
282
apply_extension_code_signing_hacks "${TBB_INSTALL}"
283

284
mkdir -p "${TBB_EXT}"
285
286
287
if [ "${NIGHTLY_BUILD}" != yes ]; then
    install_langpacks_from_bundles "${TMP}" "${TBB_EXT}"
fi
288

289
290
rm -r "${TMP}"

Tails developers's avatar
Tails developers committed
291
# Let's put all the extensions from TBB in the global extensions
292
# directory...
293
294
mv "${TBB_INSTALL}"/TorBrowser/Data/Browser/profile.default/extensions/* "${TBB_EXT}"
rmdir "${TBB_INSTALL}"/TorBrowser/Data/Browser/profile.default/extensions
295

296
297
# ... and then install a few Iceweasel extension by using a fake
# Iceweasel equivs package to satisfy the dependencies.
298
FIREFOX_VERSION=$(get_firefox_version "${TBB_INSTALL}"/application.ini)
299
FAKE_ICEWEASEL_VERSION=${FIREFOX_VERSION}+fake1
300
install_fake_package iceweasel "${FAKE_ICEWEASEL_VERSION}" web
301
install_debian_extensions "${TBB_EXT}" ${DEBIAN_EXT_PKGS}
302

303
mkdir -p "${TBB_PROFILE}"
304
create_default_profile "${TBB_INSTALL}"/TorBrowser/Data/Browser/profile.default "${TBB_EXT}" "${TBB_PROFILE}"
305

306
307
308
309
# 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"

310
311
chown -R root:root "${TBB_INSTALL}" "${TBB_PROFILE}" "${TBB_EXT}"
chmod -R a+rX "${TBB_INSTALL}" "${TBB_PROFILE}" "${TBB_EXT}"
312

Tails developers's avatar
Tails developers committed
313
# Make the Tor Browser into the system's default web browser
314
315
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
316
sed 's/\<firefox-esr\.desktop\>/tor-browser.desktop/' \
317
318
319
    /usr/share/applications/gnome-mimeapps.list \
    > /etc/xdg/gnome-mimeapps.list
chmod 644 /etc/xdg/gnome-mimeapps.list