start-tor-browser 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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 test -r /proc/cpuinfo && ! 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/asan") -%]
  251. # We need to disable LSan which is enabled by default now. Otherwise we'll get
  252. # a crash during shutdown: https://bugs.torproject.org/10599#comment:59
  253. ASAN_OPTIONS="detect_leaks=0"
  254. export ASAN_OPTIONS
  255. [% END -%]
  256. function setControlPortPasswd() {
  257. local ctrlPasswd=$1
  258. if test -z "$ctrlPasswd" -o "$ctrlPasswd" = $'\"secret\"' ; then
  259. unset TOR_CONTROL_PASSWD
  260. return
  261. fi
  262. if test "${ctrlPasswd:0:1}" = $'\"'; then # First 2 chars were '"
  263. printf "Using system Tor process.\n"
  264. export TOR_CONTROL_PASSWD
  265. else
  266. complain "There seems to have been a quoting problem with your \
  267. TOR_CONTROL_PASSWD environment variable."
  268. echo "The Tor ControlPort password should be given inside double"
  269. echo "quotes, inside single quotes. That is, if the ControlPort"
  270. echo 'password is “secret” (without curly quotes) then we must'
  271. echo "start this script after setting the environment variable"
  272. echo "exactly like this:"
  273. echo
  274. echo " \$ TOR_CONTROL_PASSWD='\"secret\"' $myname"
  275. fi
  276. }
  277. # Using a system-installed Tor process with Tor Browser:
  278. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  279. # The Tor ControlPort password should be given inside double quotes, inside
  280. # single quotes, i.e. if the ControlPort password is “secret” (without
  281. # curly quotes) then we must set the environment variable *exactly* like
  282. # this:
  283. #
  284. # TOR_CONTROL_PASSWD='"secret"'
  285. #
  286. # Yes, the variable MUST be double-quoted, then single-quoted, exactly as
  287. # shown. This is used by TorButton and Tor Launcher to authenticate to Tor's
  288. # ControlPort, and is necessary for using TB with a system-installed Tor.
  289. #
  290. # Additionally, if using a system-installed Tor, the following about:config
  291. # options should be set (values in <> mean they are the value taken from your
  292. # torrc):
  293. #
  294. # SETTING NAME VALUE
  295. # network.security.ports.banned [...],<SocksPort>,<ControlPort>
  296. # network.proxy.socks 127.0.0.1
  297. # network.proxy.socks_port <SocksPort>
  298. # extensions.torbutton.inserted_button true
  299. # extensions.torbutton.launch_warning false
  300. # extensions.torbutton.loglevel 2
  301. # extensions.torbutton.logmethod 0
  302. # extensions.torlauncher.control_port <ControlPort>
  303. # extensions.torlauncher.loglevel 2
  304. # extensions.torlauncher.logmethod 0
  305. # extensions.torlauncher.prompt_at_startup false
  306. # extensions.torlauncher.start_tor false
  307. #
  308. # where the '[...]' in the banned_ports option means "leave anything that was
  309. # already in the preference alone, just append the things specified after it".
  310. # Either set `TOR_CONTROL_PASSWD` before running ./start-tor-browser, or put
  311. # your password in the following line where the word “secret” is:
  312. setControlPortPasswd ${TOR_CONTROL_PASSWD:='"secret"'}
  313. # Set up custom bundled fonts. See fonts-conf(5).
  314. export FONTCONFIG_PATH="${HOME}/TorBrowser/Data/fontconfig"
  315. export FONTCONFIG_FILE="fonts.conf"
  316. # Avoid overwriting user's dconf values. Fixes #27903.
  317. export GSETTINGS_BACKEND=memory
  318. # ARM requires the directory containing libssp.so.0 to be in LD_LIBRARY_PATH
  319. if grep -q 'ARM' /proc/cpuinfo; then
  320. export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${HOME}"
  321. fi
  322. cd "${HOME}"
  323. # We pass all additional command-line arguments we get to Firefox.
  324. #
  325. # The --class parameter was added to fix bug 11102.
  326. if [ "$show_usage" -eq 1 ]; then
  327. # Display Firefox help, then our help
  328. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  329. -profile TorBrowser/Data/Browser/profile.default --help 2>/dev/null
  330. tbb_usage
  331. elif [ "$detach" -eq 1 ] ; then
  332. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  333. -profile TorBrowser/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null &
  334. disown "$!"
  335. elif [ "$log_output" -eq 1 -a "$show_output" -eq 1 ]; then
  336. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  337. -profile TorBrowser/Data/Browser/profile.default "${@}" 2>&1 </dev/null | \
  338. tee "$logfile"
  339. elif [ "$show_output" -eq 1 ]; then
  340. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  341. -profile TorBrowser/Data/Browser/profile.default "${@}" < /dev/null
  342. else
  343. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  344. -profile TorBrowser/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null
  345. fi
  346. exit $?