start-tor-browser 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. #!/usr/bin/env bash
  2. #
  3. # GNU/Linux does not really require something like RelativeLink.c
  4. # However, we do want to have the same look and feel with similar features.
  5. #
  6. # Copyright 2017 The Tor Project. See LICENSE for licensing information.
  7. complain_dialog_title="Tor Browser"
  8. # First, make sure DISPLAY is set. If it isn't, we're hosed; scream
  9. # at stderr and die.
  10. if [ "x$DISPLAY" = "x" ]; then
  11. echo "$complain_dialog_title must be run within the X Window System." >&2
  12. echo "Exiting." >&2
  13. exit 1
  14. fi
  15. # Second, make sure this script wasn't started as 'sh start-tor-browser' or
  16. # similar.
  17. if [ "x$BASH" = "x" ]; then
  18. echo "$complain_dialog_title should be started as './start-tor-browser'"
  19. echo "Exiting." >&2
  20. exit 1;
  21. fi
  22. # Do not (try to) connect to the session manager
  23. unset SESSION_MANAGER
  24. # Complain about an error, by any means necessary.
  25. # Usage: complain message
  26. # message must not begin with a dash.
  27. complain () {
  28. # Trim leading newlines, to avoid breaking formatting in some dialogs.
  29. complain_message="`echo "$1" | sed '/./,$!d'`"
  30. # If we're being run in debug/verbose mode, complain to stderr.
  31. if [ "$show_output" -eq 1 ]; then
  32. echo "$complain_message" >&2
  33. return
  34. fi
  35. # Otherwise, we're being run by a GUI program of some sort;
  36. # try to pop up a message in the GUI in the nicest way
  37. # possible.
  38. #
  39. # In mksh, non-existent commands return 127; I'll assume all
  40. # other shells set the same exit code if they can't run a
  41. # command. (xmessage returns 1 if the user clicks the WM
  42. # close button, so we do need to look at the exact exit code,
  43. # not just assume the command failed to display a message if
  44. # it returns non-zero.)
  45. # First, try zenity.
  46. zenity --error \
  47. --title="$complain_dialog_title" \
  48. --text="$complain_message"
  49. if [ "$?" -ne 127 ]; then
  50. return
  51. fi
  52. # Try kdialog.
  53. kdialog --title "$complain_dialog_title" \
  54. --error "$complain_message"
  55. if [ "$?" -ne 127 ]; then
  56. return
  57. fi
  58. # Try xmessage.
  59. xmessage -title "$complain_dialog_title" \
  60. -center \
  61. -buttons OK \
  62. -default OK \
  63. -xrm '*message.scrollVertical: Never' \
  64. "$complain_message"
  65. if [ "$?" -ne 127 ]; then
  66. return
  67. fi
  68. # Try gxmessage. This one isn't installed by default on
  69. # Debian with the default GNOME installation, so it seems to
  70. # be the least likely program to have available, but it might
  71. # be used by one of the 'lightweight' Gtk-based desktop
  72. # environments.
  73. gxmessage -title "$complain_dialog_title" \
  74. -center \
  75. -buttons GTK_STOCK_OK \
  76. -default OK \
  77. "$complain_message"
  78. if [ "$?" -ne 127 ]; then
  79. return
  80. fi
  81. }
  82. if [ "`id -u`" -eq 0 ]; then
  83. complain "The Tor Browser Bundle should not be run as root. Exiting."
  84. exit 1
  85. fi
  86. if ! grep -q 'ARM' /proc/cpuinfo; then
  87. # Assume we're on an x86 machine, so check for SSE2.
  88. if ! grep -q '^flags\s*:.* sse2' /proc/cpuinfo; then
  89. complain "Tor Browser requires a CPU with SSE2 support. Exiting."
  90. exit 1
  91. fi
  92. fi
  93. tbb_usage () {
  94. printf "\nTor Browser Script Options\n"
  95. printf " --verbose Display Tor and Firefox output in the terminal\n"
  96. printf " --log [file] Record Tor and Firefox output in file (default: tor-browser.log)\n"
  97. printf " --detach Detach from terminal and run Tor Browser in the background.\n"
  98. printf " --register-app Register Tor Browser as a desktop app for this user\n"
  99. printf " --unregister-app Unregister Tor Browser as a desktop app for this user\n"
  100. }
  101. log_output=0
  102. show_output=0
  103. detach=0
  104. show_usage=0
  105. register_desktop_app=0
  106. logfile=/dev/null
  107. while :
  108. do
  109. case "$1" in
  110. --detach)
  111. detach=1
  112. shift
  113. ;;
  114. -v | --verbose | -d | --debug)
  115. show_output=1
  116. verbose_arg="$2"
  117. shift
  118. ;;
  119. -h | "-?" | --help | -help)
  120. show_usage=1
  121. show_output=1
  122. shift
  123. ;;
  124. -l | --log)
  125. if [ -z "$2" -o "${2:0:1}" == "-" ]; then
  126. printf "Logging Tor Browser debug information to tor-browser.log\n"
  127. logfile="../tor-browser.log"
  128. elif [ "${2:0:1}" == "/" -o "${2:0:1}" == "~" ]; then
  129. printf "Logging Tor Browser debug information to %s\n" "$2"
  130. logfile="$2"
  131. shift
  132. else
  133. printf "Logging Tor Browser debug information to %s\n" "$2"
  134. logfile="../$2"
  135. shift
  136. fi
  137. log_output=1
  138. shift
  139. ;;
  140. --register-app)
  141. register_desktop_app=1
  142. show_output=1
  143. shift
  144. ;;
  145. --unregister-app)
  146. register_desktop_app=-1
  147. show_output=1
  148. shift
  149. ;;
  150. *) # No more options
  151. break
  152. ;;
  153. esac
  154. done
  155. # We can't detach and show output at the same time..
  156. if [ "$show_output" -eq 1 -a "$detach" -eq 1 ]; then
  157. detach=0
  158. fi
  159. if [ "$show_output" -eq 0 ]; then
  160. # If the user hasn't requested 'debug mode' or --help, close stdout and stderr,
  161. # to keep Firefox and the stuff loaded by/for it (including the
  162. # system's shared-library loader) from printing messages to
  163. # $HOME/.xsession-errors or other files. (Users wouldn't have seen
  164. # messages there anyway.)
  165. exec > "$logfile"
  166. exec 2> "$logfile"
  167. fi
  168. # If XAUTHORITY is unset, set it to its default value of $HOME/.Xauthority
  169. # before we change HOME below. (See xauth(1) and #1945.) XDM and KDM rely
  170. # on applications using this default value.
  171. if [ -z "$XAUTHORITY" ]; then
  172. XAUTHORITY=~/.Xauthority
  173. export XAUTHORITY
  174. fi
  175. # If this script is being run through a symlink, we need to know where
  176. # in the filesystem the script itself is, not where the symlink is.
  177. myname="$0"
  178. if [ -L "$myname" ]; then
  179. # XXX readlink is not POSIX, but is present in GNU coreutils
  180. # and on FreeBSD. Unfortunately, the -f option (which follows
  181. # a whole chain of symlinks until it reaches a non-symlink
  182. # path name) is a GNUism, so we have to have a fallback for
  183. # FreeBSD. Fortunately, FreeBSD has realpath instead;
  184. # unfortunately, that's also non-POSIX and is not present in
  185. # GNU coreutils.
  186. #
  187. # If this launcher were a C program, we could just use the
  188. # realpath function, which *is* POSIX. Too bad POSIX didn't
  189. # make that function accessible to shell scripts.
  190. # If realpath is available, use it; it Does The Right Thing.
  191. possibly_my_real_name="`realpath "$myname" 2>/dev/null`"
  192. if [ "$?" -eq 0 ]; then
  193. myname="$possibly_my_real_name"
  194. else
  195. # realpath is not available; hopefully readlink -f works.
  196. myname="`readlink -f "$myname" 2>/dev/null`"
  197. if [ "$?" -ne 0 ]; then
  198. # Ugh.
  199. complain "start-tor-browser cannot be run using a symlink on this operating system."
  200. fi
  201. fi
  202. fi
  203. # Try to be agnostic to where we're being started from, chdir to where
  204. # the script is.
  205. mydir="`dirname "$myname"`"
  206. test -d "$mydir" && cd "$mydir"
  207. # If ${PWD} results in a zero length string, we can try something else...
  208. if [ ! "${PWD}" ]; then
  209. # "hacking around some braindamage"
  210. PWD="`pwd`"
  211. surveysays="This system has a messed up shell.\n"
  212. fi
  213. # This is a fix for an ibus issue on some Linux systems. See #9353 for more
  214. # details. The symlink needs to be created before we change HOME.
  215. if [ ! -d ".config/ibus" ]; then
  216. mkdir -p .config/ibus
  217. ln -nsf ~/.config/ibus/bus .config/ibus
  218. fi
  219. # Fix up .desktop Icon and Exec Paths, and update the .desktop file from the
  220. # canonical version if it was changed by the updater.
  221. cp start-tor-browser.desktop ../
  222. sed -i -e "s,^Name=.*,Name=Tor Browser,g" ../start-tor-browser.desktop
  223. sed -i -e "s,^Icon=.*,Icon=$PWD/browser/chrome/icons/default/default128.png,g" ../start-tor-browser.desktop
  224. sed -i -e "s,^Exec=.*,Exec=sh -c '\"$PWD/start-tor-browser\" --detach || ([ ! -x \"$PWD/start-tor-browser\" ] \&\& \"\$(dirname \"\$*\")\"/Browser/start-tor-browser --detach)' dummy %k,g" ../start-tor-browser.desktop
  225. if [ "$register_desktop_app" -eq 1 ]; then
  226. mkdir -p "$HOME/.local/share/applications/"
  227. cp ../start-tor-browser.desktop "$HOME/.local/share/applications/"
  228. update-desktop-database "$HOME/.local/share/applications/"
  229. printf "Tor Browser has been registered as a desktop app for this user in ~/.local/share/applications/\n"
  230. exit 0
  231. fi
  232. if [ "$register_desktop_app" -eq -1 ]; then
  233. if [ -e "$HOME/.local/share/applications/start-tor-browser.desktop" ]; then
  234. rm -f "$HOME/.local/share/applications/start-tor-browser.desktop"
  235. update-desktop-database "$HOME/.local/share/applications/"
  236. printf "Tor Browser has been removed as a user desktop app (from ~/.local/share/applications/)\n"
  237. else
  238. printf "Tor Browser does not appear to be a desktop app (not present in ~/.local/share/applications/)\n"
  239. fi
  240. exit 0
  241. fi
  242. HOME="${PWD}"
  243. export HOME
  244. SYSARCHITECTURE=$(getconf LONG_BIT)
  245. TORARCHITECTURE=$(expr "$(file TorBrowser/Tor/tor)" : '.*ELF \([[:digit:]]*\)')
  246. if [ $SYSARCHITECTURE -ne $TORARCHITECTURE ]; then
  247. complain "Wrong architecture? 32-bit vs. 64-bit."
  248. exit 1
  249. fi
  250. [% IF ! c("var/release") %]
  251. export SELFRANDO_write_layout_file=
  252. [% END %]
  253. [% IF c("var/asan") -%]
  254. # We need to disable LSan which is enabled by default now. Otherwise we'll get
  255. # a crash during shutdown: https://bugs.torproject.org/10599#comment:59
  256. ASAN_OPTIONS="detect_leaks=0"
  257. export ASAN_OPTIONS
  258. [% END -%]
  259. function setControlPortPasswd() {
  260. local ctrlPasswd=$1
  261. if test -z "$ctrlPasswd" -o "$ctrlPasswd" = $'\"secret\"' ; then
  262. unset TOR_CONTROL_PASSWD
  263. return
  264. fi
  265. if test "${ctrlPasswd:0:1}" = $'\"'; then # First 2 chars were '"
  266. printf "Using system Tor process.\n"
  267. export TOR_CONTROL_PASSWD
  268. else
  269. complain "There seems to have been a quoting problem with your \
  270. TOR_CONTROL_PASSWD environment variable."
  271. cat <<EOF
  272. The Tor ControlPort password should be given inside double quotes, inside single
  273. quotes, i.e. if the ControlPort password is “secret” (without curly quotes) then
  274. we must start this script after setting the environment variable exactly like
  275. this:
  276. \$ TOR_CONTROL_PASSWD='"secret"' $myname
  277. EOF
  278. fi
  279. }
  280. # Using a system-installed Tor process with Tor Browser:
  281. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  282. # The Tor ControlPort password should be given inside double quotes, inside
  283. # single quotes, i.e. if the ControlPort password is “secret” (without
  284. # curly quotes) then we must set the environment variable *exactly* like
  285. # this:
  286. #
  287. # TOR_CONTROL_PASSWD='"secret"'
  288. #
  289. # Yes, the variable MUST be double-quoted, then single-quoted, exactly as
  290. # shown. This is used by TorButton and Tor Launcher to authenticate to Tor's
  291. # ControlPort, and is necessary for using TB with a system-installed Tor.
  292. #
  293. # Additionally, if using a system-installed Tor, the following about:config
  294. # options should be set (values in <> mean they are the value taken from your
  295. # torrc):
  296. #
  297. # SETTING NAME VALUE
  298. # network.security.ports.banned [...],<SocksPort>,<ControlPort>
  299. # network.proxy.socks 127.0.0.1
  300. # network.proxy.socks_port <SocksPort>
  301. # extensions.torbutton.inserted_button true
  302. # extensions.torbutton.launch_warning false
  303. # extensions.torbutton.loglevel 2
  304. # extensions.torbutton.logmethod 0
  305. # extensions.torlauncher.control_port <ControlPort>
  306. # extensions.torlauncher.loglevel 2
  307. # extensions.torlauncher.logmethod 0
  308. # extensions.torlauncher.prompt_at_startup false
  309. # extensions.torlauncher.start_tor false
  310. #
  311. # where the '[...]' in the banned_ports option means "leave anything that was
  312. # already in the preference alone, just append the things specified after it".
  313. # Either set `TOR_CONTROL_PASSWD` before running ./start-tor-browser, or put
  314. # your password in the following line where the word “secret” is:
  315. setControlPortPasswd ${TOR_CONTROL_PASSWD:='"secret"'}
  316. # Set up custom bundled fonts. See fonts-conf(5).
  317. export FONTCONFIG_PATH="${HOME}/TorBrowser/Data/fontconfig"
  318. export FONTCONFIG_FILE="fonts.conf"
  319. # ARM requires the directory containing libssp.so.0 to be in LD_LIBRARY_PATH
  320. if grep -q 'ARM' /proc/cpuinfo; then
  321. export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOME}"
  322. fi
  323. cd "${HOME}"
  324. # We pass all additional command-line arguments we get to Firefox.
  325. #
  326. # The --class parameter was added to fix bug 11102.
  327. if [ "$show_usage" -eq 1 ]; then
  328. # Display Firefox help, then our help
  329. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  330. -profile TorBrowser/Data/Browser/profile.default --help 2>/dev/null
  331. tbb_usage
  332. elif [ "$detach" -eq 1 ] ; then
  333. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  334. -profile TorBrowser/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null &
  335. disown "$!"
  336. elif [ "$log_output" -eq 1 -a "$show_output" -eq 1 ]; then
  337. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  338. -profile TorBrowser/Data/Browser/profile.default "${@}" 2>&1 </dev/null | \
  339. tee "$logfile"
  340. elif [ "$show_output" -eq 1 ]; then
  341. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  342. -profile TorBrowser/Data/Browser/profile.default "${@}" < /dev/null
  343. else
  344. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  345. -profile TorBrowser/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null
  346. fi
  347. exit $?