start-tor-browser 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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 test -r /proc/cpuinfo && ! grep -q '^flags\s*:.* sse2' /proc/cpuinfo; then
  87. complain "Tor Browser requires a CPU with SSE2 support. Exiting."
  88. exit 1
  89. fi
  90. tbb_usage () {
  91. printf "\nTor Browser Script Options\n"
  92. printf " --verbose Display Tor and Firefox output in the terminal\n"
  93. printf " --log [file] Record Tor and Firefox output in file (default: tor-browser.log)\n"
  94. printf " --detach Detach from terminal and run Tor Browser in the background.\n"
  95. printf " --register-app Register Tor Browser as a desktop app for this user\n"
  96. printf " --unregister-app Unregister Tor Browser as a desktop app for this user\n"
  97. }
  98. log_output=0
  99. show_output=0
  100. detach=0
  101. show_usage=0
  102. register_desktop_app=0
  103. logfile=/dev/null
  104. while :
  105. do
  106. case "$1" in
  107. --detach)
  108. detach=1
  109. shift
  110. ;;
  111. -v | --verbose | -d | --debug)
  112. show_output=1
  113. verbose_arg="$2"
  114. shift
  115. ;;
  116. -h | "-?" | --help | -help)
  117. show_usage=1
  118. show_output=1
  119. shift
  120. ;;
  121. -l | --log)
  122. if [ -z "$2" -o "${2:0:1}" == "-" ]; then
  123. printf "Logging Tor Browser debug information to tor-browser.log\n"
  124. logfile="../tor-browser.log"
  125. elif [ "${2:0:1}" == "/" -o "${2:0:1}" == "~" ]; then
  126. printf "Logging Tor Browser debug information to %s\n" "$2"
  127. logfile="$2"
  128. shift
  129. else
  130. printf "Logging Tor Browser debug information to %s\n" "$2"
  131. logfile="../$2"
  132. shift
  133. fi
  134. log_output=1
  135. shift
  136. ;;
  137. --register-app)
  138. register_desktop_app=1
  139. show_output=1
  140. shift
  141. ;;
  142. --unregister-app)
  143. register_desktop_app=-1
  144. show_output=1
  145. shift
  146. ;;
  147. *) # No more options
  148. break
  149. ;;
  150. esac
  151. done
  152. # We can't detach and show output at the same time..
  153. if [ "$show_output" -eq 1 -a "$detach" -eq 1 ]; then
  154. detach=0
  155. fi
  156. if [ "$show_output" -eq 0 ]; then
  157. # If the user hasn't requested 'debug mode' or --help, close stdout and stderr,
  158. # to keep Firefox and the stuff loaded by/for it (including the
  159. # system's shared-library loader) from printing messages to
  160. # $HOME/.xsession-errors or other files. (Users wouldn't have seen
  161. # messages there anyway.)
  162. exec > "$logfile"
  163. exec 2> "$logfile"
  164. fi
  165. # If XAUTHORITY is unset, set it to its default value of $HOME/.Xauthority
  166. # before we change HOME below. (See xauth(1) and #1945.) XDM and KDM rely
  167. # on applications using this default value.
  168. if [ -z "$XAUTHORITY" ]; then
  169. XAUTHORITY=~/.Xauthority
  170. export XAUTHORITY
  171. fi
  172. # If this script is being run through a symlink, we need to know where
  173. # in the filesystem the script itself is, not where the symlink is.
  174. myname="$0"
  175. if [ -L "$myname" ]; then
  176. # XXX readlink is not POSIX, but is present in GNU coreutils
  177. # and on FreeBSD. Unfortunately, the -f option (which follows
  178. # a whole chain of symlinks until it reaches a non-symlink
  179. # path name) is a GNUism, so we have to have a fallback for
  180. # FreeBSD. Fortunately, FreeBSD has realpath instead;
  181. # unfortunately, that's also non-POSIX and is not present in
  182. # GNU coreutils.
  183. #
  184. # If this launcher were a C program, we could just use the
  185. # realpath function, which *is* POSIX. Too bad POSIX didn't
  186. # make that function accessible to shell scripts.
  187. # If realpath is available, use it; it Does The Right Thing.
  188. possibly_my_real_name="`realpath "$myname" 2>/dev/null`"
  189. if [ "$?" -eq 0 ]; then
  190. myname="$possibly_my_real_name"
  191. else
  192. # realpath is not available; hopefully readlink -f works.
  193. myname="`readlink -f "$myname" 2>/dev/null`"
  194. if [ "$?" -ne 0 ]; then
  195. # Ugh.
  196. complain "start-tor-browser cannot be run using a symlink on this operating system."
  197. fi
  198. fi
  199. fi
  200. # Try to be agnostic to where we're being started from, chdir to where
  201. # the script is.
  202. mydir="`dirname "$myname"`"
  203. test -d "$mydir" && cd "$mydir"
  204. # If ${PWD} results in a zero length string, we can try something else...
  205. if [ ! "${PWD}" ]; then
  206. # "hacking around some braindamage"
  207. PWD="`pwd`"
  208. surveysays="This system has a messed up shell.\n"
  209. fi
  210. # This is a fix for an ibus issue on some Linux systems. See #9353 for more
  211. # details. The symlink needs to be created before we change HOME.
  212. if [ ! -d ".config/ibus" ]; then
  213. mkdir -p .config/ibus
  214. ln -nsf ~/.config/ibus/bus .config/ibus
  215. fi
  216. # Fix up .desktop Icon and Exec Paths, and update the .desktop file from the
  217. # canonical version if it was changed by the updater.
  218. cp start-tor-browser.desktop ../
  219. sed -i -e "s,^Name=.*,Name=Tor Browser,g" ../start-tor-browser.desktop
  220. sed -i -e "s,^Icon=.*,Icon=$PWD/browser/chrome/icons/default/default128.png,g" ../start-tor-browser.desktop
  221. 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
  222. if [ "$register_desktop_app" -eq 1 ]; then
  223. mkdir -p "$HOME/.local/share/applications/"
  224. cp ../start-tor-browser.desktop "$HOME/.local/share/applications/"
  225. update-desktop-database "$HOME/.local/share/applications/"
  226. printf "Tor Browser has been registered as a desktop app for this user in ~/.local/share/applications/\n"
  227. exit 0
  228. fi
  229. if [ "$register_desktop_app" -eq -1 ]; then
  230. if [ -e "$HOME/.local/share/applications/start-tor-browser.desktop" ]; then
  231. rm -f "$HOME/.local/share/applications/start-tor-browser.desktop"
  232. update-desktop-database "$HOME/.local/share/applications/"
  233. printf "Tor Browser has been removed as a user desktop app (from ~/.local/share/applications/)\n"
  234. else
  235. printf "Tor Browser does not appear to be a desktop app (not present in ~/.local/share/applications/)\n"
  236. fi
  237. exit 0
  238. fi
  239. HOME="${PWD}"
  240. export HOME
  241. SYSARCHITECTURE=$(getconf LONG_BIT)
  242. TORARCHITECTURE=$(expr "$(file TorBrowser/Tor/tor)" : '.*ELF \([[:digit:]]*\)')
  243. if [ $SYSARCHITECTURE -ne $TORARCHITECTURE ]; then
  244. complain "Wrong architecture? 32-bit vs. 64-bit."
  245. exit 1
  246. fi
  247. [% IF c("var/asan") -%]
  248. # We need to disable LSan which is enabled by default now. Otherwise we'll get
  249. # a crash during shutdown: https://bugs.torproject.org/10599#comment:59
  250. ASAN_OPTIONS="detect_leaks=0"
  251. export ASAN_OPTIONS
  252. [% END -%]
  253. function setControlPortPasswd() {
  254. local ctrlPasswd=$1
  255. if test -z "$ctrlPasswd" -o "$ctrlPasswd" = $'\"secret\"' ; then
  256. unset TOR_CONTROL_PASSWD
  257. return
  258. fi
  259. if test "${ctrlPasswd:0:1}" = $'\"'; then # First 2 chars were '"
  260. printf "Using system Tor process.\n"
  261. export TOR_CONTROL_PASSWD
  262. else
  263. complain "There seems to have been a quoting problem with your \
  264. TOR_CONTROL_PASSWD environment variable."
  265. echo "The Tor ControlPort password should be given inside double"
  266. echo "quotes, inside single quotes. That is, if the ControlPort"
  267. echo 'password is “secret” (without curly quotes) then we must'
  268. echo "start this script after setting the environment variable"
  269. echo "exactly like this:"
  270. echo
  271. echo " \$ TOR_CONTROL_PASSWD='\"secret\"' $myname"
  272. fi
  273. }
  274. # Using a system-installed Tor process with Tor Browser:
  275. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  276. # The Tor ControlPort password should be given inside double quotes, inside
  277. # single quotes, i.e. if the ControlPort password is “secret” (without
  278. # curly quotes) then we must set the environment variable *exactly* like
  279. # this:
  280. #
  281. # TOR_CONTROL_PASSWD='"secret"'
  282. #
  283. # Yes, the variable MUST be double-quoted, then single-quoted, exactly as
  284. # shown. This is used by TorButton and Tor Launcher to authenticate to Tor's
  285. # ControlPort, and is necessary for using TB with a system-installed Tor.
  286. #
  287. # Additionally, if using a system-installed Tor, the following about:config
  288. # options should be set (values in <> mean they are the value taken from your
  289. # torrc):
  290. #
  291. # SETTING NAME VALUE
  292. # network.security.ports.banned [...],<SocksPort>,<ControlPort>
  293. # network.proxy.socks 127.0.0.1
  294. # network.proxy.socks_port <SocksPort>
  295. # extensions.torbutton.inserted_button true
  296. # extensions.torbutton.launch_warning false
  297. # extensions.torbutton.loglevel 2
  298. # extensions.torbutton.logmethod 0
  299. # extensions.torlauncher.control_port <ControlPort>
  300. # extensions.torlauncher.loglevel 2
  301. # extensions.torlauncher.logmethod 0
  302. # extensions.torlauncher.prompt_at_startup false
  303. # extensions.torlauncher.start_tor false
  304. #
  305. # where the '[...]' in the banned_ports option means "leave anything that was
  306. # already in the preference alone, just append the things specified after it".
  307. # Either set `TOR_CONTROL_PASSWD` before running ./start-tor-browser, or put
  308. # your password in the following line where the word “secret” is:
  309. setControlPortPasswd ${TOR_CONTROL_PASSWD:='"secret"'}
  310. # Set up custom bundled fonts. See fonts-conf(5).
  311. export FONTCONFIG_PATH="${HOME}/TorBrowser/Data/fontconfig"
  312. export FONTCONFIG_FILE="fonts.conf"
  313. # Avoid overwriting user's dconf values. Fixes #27903.
  314. export GSETTINGS_BACKEND=memory
  315. cd "${HOME}"
  316. # We pass all additional command-line arguments we get to Firefox.
  317. #
  318. # The --class parameter was added to fix bug 11102.
  319. if [ "$show_usage" -eq 1 ]; then
  320. # Display Firefox help, then our help
  321. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  322. -profile TorBrowser/Data/Browser/profile.default --help 2>/dev/null
  323. tbb_usage
  324. elif [ "$detach" -eq 1 ] ; then
  325. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  326. -profile TorBrowser/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null &
  327. disown "$!"
  328. elif [ "$log_output" -eq 1 -a "$show_output" -eq 1 ]; then
  329. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  330. -profile TorBrowser/Data/Browser/profile.default "${@}" 2>&1 </dev/null | \
  331. tee "$logfile"
  332. elif [ "$show_output" -eq 1 ]; then
  333. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  334. -profile TorBrowser/Data/Browser/profile.default "${@}" < /dev/null
  335. else
  336. TOR_CONTROL_PASSWD=${TOR_CONTROL_PASSWD} ./firefox --class "Tor Browser" \
  337. -profile TorBrowser/Data/Browser/profile.default "${@}" > "$logfile" 2>&1 </dev/null
  338. fi
  339. exit $?