commit 7cba0a659c3abd4b92eb289b20263726d1c6d610 Author: David Fifield david@bamsoftware.com Date: Sun Apr 6 10:07:33 2014 -0700
Add meek-client-torbrowser program.
This program starts firefox with the meek-http-helper profile and then starts meek-client set up to talk to it. --- .gitignore | 1 + meek-client-torbrowser/Makefile | 18 +++++ meek-client-torbrowser/linux.go | 10 +++ meek-client-torbrowser/mac.go | 10 +++ meek-client-torbrowser/main.go | 160 +++++++++++++++++++++++++++++++++++++ meek-client-torbrowser/windows.go | 10 +++ 6 files changed, 209 insertions(+)
diff --git a/.gitignore b/.gitignore index e085380..3d5729c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /meek-client/meek-client +/meek-client-torbrowser/meek-client-torbrowser /meek-server/meek-server diff --git a/meek-client-torbrowser/Makefile b/meek-client-torbrowser/Makefile new file mode 100644 index 0000000..7ce013b --- /dev/null +++ b/meek-client-torbrowser/Makefile @@ -0,0 +1,18 @@ +DESTDIR = +PREFIX = /usr/local +BINDIR = $(PREFIX)/bin + +GOBUILDFLAGS = + +all: meek-client + +meek-client: *.go + go build $(GOBUILDFLAGS) + +clean: + rm -f meek-client-torbrowser + +fmt: + go fmt + +.PHONY: all install clean fmt diff --git a/meek-client-torbrowser/linux.go b/meek-client-torbrowser/linux.go new file mode 100644 index 0000000..73e363a --- /dev/null +++ b/meek-client-torbrowser/linux.go @@ -0,0 +1,10 @@ +// +build linux +// This file is compiled only on linux. It contains paths used by the linux +// browser bundle. +// http://golang.org/pkg/go/build/#hdr-Build_Constraints + +package main + +var firefoxPath = "Browser/firefox" +var firefoxProfilePath = "Data/Browser/profile.meek-http-helper" +var meekClientPath = "Tor/PluggableTransports/meek-client" diff --git a/meek-client-torbrowser/mac.go b/meek-client-torbrowser/mac.go new file mode 100644 index 0000000..6830da1 --- /dev/null +++ b/meek-client-torbrowser/mac.go @@ -0,0 +1,10 @@ +// +build darwin +// This file is compiled only on mac. It contains paths used by the mac +// browser bundle. +// http://golang.org/pkg/go/build/#hdr-Build_Constraints + +package main + +var firefoxPath = "../Contents/MacOS/TorBrowser.app/Contents/MacOS/firefox" +var firefoxProfilePath = "../Data/Browser/profile.meek-http-helper" +var meekClientPath = "PluggableTransports/meek-client" diff --git a/meek-client-torbrowser/main.go b/meek-client-torbrowser/main.go new file mode 100644 index 0000000..8890f6d --- /dev/null +++ b/meek-client-torbrowser/main.go @@ -0,0 +1,160 @@ +// The meek-client-torbrowser program starts a copy of Tor Browser running +// meek-http-helper in a special profile, and then starts meek-client set up to +// use the browser helper. +// +// Arguments to this program are passed unmodified to meek-client, with the +// addition of a --helper option pointing to the browser helper. +package main + +import ( + "bufio" + "io" + "io/ioutil" + "log" + "os" + "os/exec" + "os/signal" + "path/filepath" + "regexp" + "syscall" +) + +var helperAddrPattern *regexp.Regexp + +// Log a call to os.Process.Kill. +func logKill(p *os.Process) error { + log.Printf("killing PID %d", p.Pid) + err := p.Kill() + if err != nil { + log.Print(err) + } + return err +} + +// Log a call to os.Process.Signal. +func logSignal(p *os.Process, sig os.Signal) error { + log.Printf("sending signal %s to PID %d", sig, p.Pid) + err := p.Signal(sig) + if err != nil { + log.Print(err) + } + return err +} + +// Run firefox and return its exec.Cmd and stdout pipe. +func runFirefox() (cmd *exec.Cmd, stdout io.Reader, err error) { + var profilePath string + // Mac OS X needs an absolute profile path. + profilePath, err = filepath.Abs(firefoxProfilePath) + if err != nil { + return + } + cmd = exec.Command(firefoxPath, "-no-remote", "-profile", profilePath) + cmd.Stderr = os.Stderr + stdout, err = cmd.StdoutPipe() + if err != nil { + return + } + log.Printf("running firefox command %q", cmd.Args) + err = cmd.Start() + if err != nil { + return + } + log.Printf("firefox started with pid %d", cmd.Process.Pid) + return cmd, stdout, nil +} + +// Look for the magic meek-http-helper address string in the Reader, and return +// the address it contains. Start a goroutine to continue reading and discarding +// output of the Reader before returning. +func grepHelperAddr(r io.Reader) (string, error) { + var helperAddr string + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + if m := helperAddrPattern.FindStringSubmatch(line); m != nil { + helperAddr = m[1] + break + } + } + err := scanner.Err() + if err != nil { + return "", err + } + // Ran out of input before finding the pattern. + if helperAddr == "" { + return "", io.EOF + } + // Keep reading from the browser to avoid its output buffer filling. + go io.Copy(ioutil.Discard, r) + return helperAddr, nil +} + +// Run meek-client and return its exec.Cmd. +func runMeekClient(helperAddr string) (cmd *exec.Cmd, err error) { + args := os.Args[1:] + args = append(args, []string{"--helper", helperAddr}...) + cmd = exec.Command(meekClientPath, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Printf("running meek-client command %q", cmd.Args) + err = cmd.Start() + if err != nil { + return + } + log.Printf("meek-client started with pid %d", cmd.Process.Pid) + return cmd, nil +} + +func main() { + var err error + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + // This magic string is emitted by meek-http-helper. + helperAddrPattern, err = regexp.Compile(`^meek-http-helper: listen (127.0.0.1:\d+)$`) + if err != nil { + log.Fatal(err) + } + + // Start firefox. + firefoxCmd, stdout, err := runFirefox() + if err != nil { + log.Print(err) + return + } + defer logKill(firefoxCmd.Process) + + // Find out the helper's listening address. + helperAddr, err := grepHelperAddr(stdout) + if err != nil { + log.Print(err) + return + } + + // Start meek-client with the helper address. + meekClientCmd, err := runMeekClient(helperAddr) + if err != nil { + log.Print(err) + return + } + defer logKill(meekClientCmd.Process) + + sig := <-sigChan + log.Printf("sig %s", sig) + err = logSignal(meekClientCmd.Process, sig) + if err != nil { + log.Print(err) + } + + // If SIGINT, wait for a second SIGINT. + if sig == syscall.SIGINT { + sig := <-sigChan + log.Printf("sig %s", sig) + err = logSignal(meekClientCmd.Process, sig) + if err != nil { + log.Print(err) + } + } +} diff --git a/meek-client-torbrowser/windows.go b/meek-client-torbrowser/windows.go new file mode 100644 index 0000000..ed590d8 --- /dev/null +++ b/meek-client-torbrowser/windows.go @@ -0,0 +1,10 @@ +// +build windows +// This file is compiled only on windows. It contains paths used by the windows +// browser bundle. +// http://golang.org/pkg/go/build/#hdr-Build_Constraints + +package main + +var firefoxPath string = "Browser/firefox.exe" +var firefoxProfilePath = "Data/Browser/profile.meek-http-helper" +var meekClientPath = "Tor/PluggableTransports/meek-client.exe"
tor-commits@lists.torproject.org