From f435de4b71c786f9dcb14f6b1ba5b8cd46f03957 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Sun, 1 Jul 2018 11:43:05 -0700 Subject: [PATCH] Testing Tor Manager + Some bug fixes --- app/app.go | 43 +++++++++++++++++++++--- connectivity/tor/tormanager.go | 51 +++++++++-------------------- connectivity/tor/tormanager_test.go | 27 +++++++++++++++ peer/cwtch_peer.go | 38 +++++++++++---------- testing/tests.sh | 1 + 5 files changed, 102 insertions(+), 58 deletions(-) create mode 100644 connectivity/tor/tormanager_test.go diff --git a/app/app.go b/app/app.go index d18326e..c9a3a7c 100644 --- a/app/app.go +++ b/app/app.go @@ -3,7 +3,11 @@ package app import ( "cwtch.im/cwtch/connectivity/tor" "cwtch.im/cwtch/peer" + "fmt" "log" + "os" + "os/user" + "path" ) // Application is a facade over a cwtchPeer that provides some wrapping logic. @@ -19,11 +23,10 @@ func (app *Application) NewProfile(name string, filename string, password string err := profile.Save(filename) if err == nil { - _, err := tor.NewTorManager(9050, 9051) + err := app.startTor() if err != nil { return err } - go func() { err := app.Peer.Listen() if err != nil { @@ -34,6 +37,38 @@ func (app *Application) NewProfile(name string, filename string, password string return err } +func (app *Application) startTor() error { + + // Creating a local cwtch tor server config for the user + usr, err := user.Current() + if err != nil { + return err + } + + // creating /home//.cwtch/torrc file + // SOCKSPort socksPort + // ControlPort controlPort + torrc := path.Join(usr.HomeDir, ".cwtch", "torrc") + if _, err := os.Stat(torrc); os.IsNotExist(err) { + + os.MkdirAll(path.Join(usr.HomeDir, ".cwtch"), 0700) + + file, err := os.Create(torrc) + if err != nil { + return err + } + fmt.Fprintf(file, "SOCKSPort %d\nControlPort %d\n", 9050, 9051) + file.Close() + } + + tm, err := tor.NewTorManager(9050, 9051, torrc) + if err != nil { + return err + } + app.TorManager = tm + return nil +} + // SetProfile loads an existing profile from the given filename. func (app *Application) SetProfile(filename string, password string) error { profile, err := peer.LoadCwtchPeer(filename, password) @@ -43,12 +78,10 @@ func (app *Application) SetProfile(filename string, password string) error { app.Peer = profile if err == nil { - tm, err := tor.NewTorManager(9050, 9051) + err := app.startTor() if err != nil { return err } - app.TorManager = tm - go func() { err := app.Peer.Listen() if err != nil { diff --git a/connectivity/tor/tormanager.go b/connectivity/tor/tormanager.go index ec58591..63c1c83 100644 --- a/connectivity/tor/tormanager.go +++ b/connectivity/tor/tormanager.go @@ -8,15 +8,12 @@ import ( "net" "net/http" "net/url" - "os" "os/exec" - "os/user" - "path" "strings" "time" ) -// Manager checks connectivity of the Tor process used to support Cwtch/ +// Manager checks connectivity of the Tor process used to support Cwtch type Manager struct { socksPort int controlPort int @@ -24,44 +21,28 @@ type Manager struct { } // NewTorManager Instantiates a new connection manager, returns non-nil error if it fails to connect to a tor daemon on the given ports. -func NewTorManager(socksPort int, controlPort int) (*Manager, error) { +func NewTorManager(socksPort int, controlPort int, torrc string) (*Manager, error) { torManager := new(Manager) torManager.socksPort = socksPort torManager.controlPort = controlPort err := torManager.TestConnection() - if err != nil { - - usr, err := user.Current() - if err != nil { - return nil, err - } - - torrc := path.Join(usr.HomeDir, ".cwtch", "torrc") - if _, err := os.Stat(torrc); os.IsNotExist(err) { - - os.MkdirAll(path.Join(usr.HomeDir, ".cwtch"), 0700) - - file, err := os.Create(torrc) - if err != nil { - return nil, err - } - fmt.Fprintf(file, "SOCKSPort %d\nControlPort %d\n", socksPort, controlPort) - file.Close() - } - - cmd := exec.Command("tor", "-f", torrc) - err = cmd.Start() - if err != nil { - return nil, err - } - fmt.Printf("\nWaiting to connect to Tor Proxy...\n") - time.Sleep(time.Second * 5) - torManager.process = cmd - err = torManager.TestConnection() - return torManager, err + if err == nil { + log.Printf("using existing tor proxy") + return torManager, nil } + // try to start tor + cmd := exec.Command("tor", "-f", torrc) + log.Printf("starting local tor proxy") + err = cmd.Start() + if err != nil { + log.Printf("starting tor failed %v", err) + return nil, err + } + time.Sleep(time.Second * 5) + torManager.process = cmd + err = torManager.TestConnection() return torManager, err } diff --git a/connectivity/tor/tormanager_test.go b/connectivity/tor/tormanager_test.go new file mode 100644 index 0000000..80a5c85 --- /dev/null +++ b/connectivity/tor/tormanager_test.go @@ -0,0 +1,27 @@ +package tor + +import ( + "fmt" + "os" + "testing" +) + +func TestTorManager(t *testing.T) { + + os.Remove("/tmp/torrc") + file, _ := os.Create("/tmp/torrc") + fmt.Fprintf(file, "SOCKSPort %d\nControlPort %d\nDataDirectory /tmp/tor\n", 10050, 10051) + file.Close() + tm, err := NewTorManager(10050, 10051, "/tmp/torrc") + if err != nil { + t.Errorf("creating a new tor manager failed: %v", err) + } else { + + tm2, err := NewTorManager(10050, 10051, "/tmp/torrc") + if err != nil { + t.Errorf("creating a new tor manager failed: %v", err) + } + tm2.Shutdown() // should not noop + } + tm.Shutdown() +} diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 6101b60..b4d50c6 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -170,26 +170,28 @@ func (cp *cwtchPeer) Save(profilefile string) error { // LoadCwtchPeer loads an existing cwtchPeer from a file. func LoadCwtchPeer(profilefile string, password string) (CwtchPeerInterface, error) { - encryptedbytes, _ := ioutil.ReadFile(profilefile) + encryptedbytes, err := ioutil.ReadFile(profilefile) - var dkr [32]byte - var salty [128]byte - - //Separate the salt from the encrypted bytes, then generate the derived key - salt, encryptedbytes := encryptedbytes[0:128], encryptedbytes[128:] - dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512) - - //cast to arrays - copy(dkr[:], dk) - copy(salty[:], salt) - - cp, err := decryptProfile(encryptedbytes, dkr) if err == nil { - cp.setup() - cp.profilefile = profilefile - cp.key = dkr - cp.salt = salty - return cp, nil + var dkr [32]byte + var salty [128]byte + + //Separate the salt from the encrypted bytes, then generate the derived key + salt, encryptedbytes := encryptedbytes[0:128], encryptedbytes[128:] + dk := pbkdf2.Key([]byte(password), salt, 4096, 32, sha3.New512) + + //cast to arrays + copy(dkr[:], dk) + copy(salty[:], salt) + + cp, err := decryptProfile(encryptedbytes, dkr) + if err == nil { + cp.setup() + cp.profilefile = profilefile + cp.key = dkr + cp.salt = salty + return cp, nil + } } return nil, err } diff --git a/testing/tests.sh b/testing/tests.sh index 2ce493c..ba55761 100755 --- a/testing/tests.sh +++ b/testing/tests.sh @@ -16,6 +16,7 @@ go test ${1} -coverprofile=server.listen.cover.out -v ./server/listen go test ${1} -coverprofile=server.send.cover.out -v ./server/send go test ${1} -coverprofile=server.metrics.cover.out -v ./server/metrics go test ${1} -coverprofile=server.cover.out -v ./server +go test ${1} -coverprofile=tor.cover.out -v ./connectivity/tor echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \ awk '{if($1 != last) {print $0;last=$1}}' >> coverage.out rm -rf *.cover.out