Compare commits

...

20 Commits

Author SHA1 Message Date
Sarah Jamie Lewis f82c2f9da4 Merge branch 'windows' of openprivacy/libricochet-go into master 2020-01-27 11:24:29 -08:00
Dan Ballard 7c828d3916 Use new Bine CmdCreatorFunc to make a ProcessCreator to hide Tor dos window.
Also hide it in checkTorVersion
2020-01-24 18:19:36 -05:00
Dan Ballard 79a1ff9161 Merge branch 'race' of openprivacy/libricochet-go into master 2019-11-07 16:26:35 -08:00
Sarah Jamie Lewis 5a1fc1b94d Fixing Race Conditions 2019-11-07 16:21:15 -08:00
Dan Ballard 9ba39b93b7 Merge branch 'restart-new' of openprivacy/libricochet-go into master 2019-11-06 12:07:47 -08:00
Sarah Jamie Lewis 29540dcf71 Expose Reboot 2019-11-06 11:59:29 -08:00
Dan Ballard 0fdcfd1553 drone liny 2019-11-06 11:57:14 -08:00
Dan Ballard ac4993adb7 drone get/download 2019-11-06 11:52:22 -08:00
Dan Ballard 881ca5c6c2 drone use go mod instead of list xargs for fetch 2019-11-06 11:50:25 -08:00
Dan Ballard 61f89d7b2c drone force modules 2019-11-06 11:40:58 -08:00
Sarah Jamie Lewis 725f64020a Merge branch 'logfile' of dan/libricochet-go into master 2019-08-12 14:47:10 -07:00
Dan Ballard b7cca3fa83 log now suports creating a logger around a file 2019-08-12 14:17:17 -07:00
Sarah Jamie Lewis 07747c4dd2 Merge branch 'torFix' of dan/libricochet-go into master 2019-07-31 15:09:46 -07:00
Dan Ballard 59ea2902e8 move .Dial outside of lock to stop throtteling one conn per time; get Dialer once only 2019-07-31 14:41:07 -07:00
Sarah Jamie Lewis 4ccdc79526 Merge branch 'torStatus' of dan/libricochet-go into master 2019-07-10 13:16:21 -07:00
Dan Ballard 6517665498 ACN and tor provider: take callback for status change 2019-07-10 13:08:49 -07:00
Sarah Jamie Lewis cd872e9e0a Merge branch 'logExclude' of dan/libricochet-go into master 2019-06-21 15:41:32 -07:00
Dan Ballard b534ecd04e add log exclude 2019-06-21 15:34:46 -07:00
Sarah Jamie Lewis aca0f63dd2 Merge branch 'nonewnym' of dan/libricochet-go into master 2019-02-20 19:45:31 +00:00
Dan Ballard bf57db657a stop issueing tor NEWNYM commands on errrors on open() 2019-02-20 11:36:42 -08:00
15 changed files with 219 additions and 75 deletions

View File

@ -5,27 +5,35 @@ workspace:
pipeline: pipeline:
fetch: fetch:
image: golang image: golang
environment:
- GO111MODULE=on
commands: commands:
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/tor - wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/tor
- wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/torrc - wget https://git.openprivacy.ca/openprivacy/buildfiles/raw/master/tor/torrc
- chmod a+x tor - chmod a+x tor
- go list ./... | xargs go get - go get -u golang.org/x/lint/golint
- go get -u github.com/golang/lint/golint - go mod download
quality: quality:
image: golang image: golang
environment:
- GO111MODULE=on
commands: commands:
- go list ./... | xargs go vet - go list ./... | xargs go vet
- go list ./... | grep -v "/wire/" | xargs golint -set_exit_status - go list ./... | grep -v "/wire/" | xargs golint -set_exit_status
units-tests: units-tests:
image: golang image: golang
environment:
- GO111MODULE=on
commands: commands:
- sh testing/tests.sh - sh testing/tests.sh
integ-test: integ-test:
image: golang image: golang
environment:
- GO111MODULE=on
commands: commands:
- ./tor -f ./torrc - ./tor -f ./torrc
- sleep 15 - sleep 15
- go test -v git.openprivacy.ca/openprivacy/libricochet-go/testing - go test -race -v git.openprivacy.ca/openprivacy/libricochet-go/testing
notify-email: notify-email:
image: drillster/drone-email image: drillster/drone-email
host: build.openprivacy.ca host: build.openprivacy.ca

View File

@ -144,7 +144,9 @@ func (ra *RicochetApplication) Run(ls connectivity.ListenService) {
if !ra.v3identity.Initialized() || ra.contactManager == nil { if !ra.v3identity.Initialized() || ra.contactManager == nil {
return return
} }
ra.lock.Lock()
ra.ls = ls ra.ls = ls
ra.lock.Unlock()
var err error var err error
for err == nil { for err == nil {
conn, err := ra.ls.Accept() conn, err := ra.ls.Accept()

View File

@ -32,8 +32,9 @@ type Connection struct {
messageBuilder utils.MessageBuilder messageBuilder utils.MessageBuilder
closed bool closed bool
closing bool closingLock sync.Mutex
closing bool
// This mutex is exclusively for preventing races during blocking // This mutex is exclusively for preventing races during blocking
// interactions with Process; specifically Do and Break. Don't use // interactions with Process; specifically Do and Break. Don't use
// it for anything else. See those functions for an explanation. // it for anything else. See those functions for an explanation.
@ -311,6 +312,8 @@ func (rc *Connection) Process(handler Handler) error {
go func() { go func() {
rc.processBlockMutex.Lock() rc.processBlockMutex.Lock()
defer rc.processBlockMutex.Unlock() defer rc.processBlockMutex.Unlock()
rc.closingLock.Lock()
defer rc.closingLock.Unlock()
rc.closed = true rc.closed = true
close(closedChan) close(closedChan)
}() }()
@ -468,5 +471,7 @@ func (rc *Connection) Close() {
// Kill the Ricochet Connection. // Kill the Ricochet Connection.
log.Debugf("Closing Ricochet Connection for %v", rc.RemoteHostname) log.Debugf("Closing Ricochet Connection for %v", rc.RemoteHostname)
rc.conn.Close() rc.conn.Close()
rc.closingLock.Lock()
rc.closed = true rc.closed = true
rc.closingLock.Unlock()
} }

View File

@ -53,6 +53,9 @@ func TestProcessAuthAs3DHServer(t *testing.T) {
t.Errorf("Error while testing ProcessAuthAsServer: %v", err) t.Errorf("Error while testing ProcessAuthAsServer: %v", err)
} }
// Wait for server to finish
time.Sleep(time.Second * 2)
// Test Close // Test Close
rc.Close() rc.Close()
} }

View File

@ -25,6 +25,11 @@ type ACN interface {
GetBootstrapStatus() (int, string) GetBootstrapStatus() (int, string)
// WaitTillBootstrapped Blocks until underlying network is bootstrapped // WaitTillBootstrapped Blocks until underlying network is bootstrapped
WaitTillBootstrapped() WaitTillBootstrapped()
// Sets the calback function to be called when ACN status changes
SetStatusCallback(callback func(int, string))
// Restarts the underlying connection
Restart()
// Open takes a hostname and returns a net.conn to the derived endpoint // Open takes a hostname and returns a net.conn to the derived endpoint
// Open allows a client to resolve various hostnames to connections // Open allows a client to resolve various hostnames to connections

View File

@ -34,6 +34,10 @@ func (lp *localProvider) GetBootstrapStatus() (int, string) {
return 100, "Done" return 100, "Done"
} }
func (lp *localProvider) SetStatusCallback(callback func(int, string)) {
// nop
}
// WaitTillBootstrapped Blocks until underlying network is bootstrapped // WaitTillBootstrapped Blocks until underlying network is bootstrapped
func (lp *localProvider) WaitTillBootstrapped() { func (lp *localProvider) WaitTillBootstrapped() {
} }
@ -59,6 +63,10 @@ func (lp *localProvider) Open(hostname string) (net.Conn, string, error) {
} }
func (lp *localProvider) Restart() {
//noop
}
func (lp *localProvider) Close() { func (lp *localProvider) Close() {
} }

View File

@ -0,0 +1,9 @@
// +build !windows
package connectivity
import (
"syscall"
)
var sysProcAttr = &syscall.SysProcAttr{}

View File

@ -0,0 +1,9 @@
// +build windows
package connectivity
import (
"syscall"
)
var sysProcAttr = &syscall.SysProcAttr{HideWindow: true}

View File

@ -1,10 +1,12 @@
package connectivity package connectivity
import ( import (
"context"
"errors" "errors"
"git.openprivacy.ca/openprivacy/libricochet-go/log" "git.openprivacy.ca/openprivacy/libricochet-go/log"
"git.openprivacy.ca/openprivacy/libricochet-go/utils" "git.openprivacy.ca/openprivacy/libricochet-go/utils"
"github.com/cretz/bine/control" "github.com/cretz/bine/control"
"github.com/cretz/bine/process"
"github.com/cretz/bine/tor" "github.com/cretz/bine/tor"
bineed255192 "github.com/cretz/bine/torutil/ed25519" bineed255192 "github.com/cretz/bine/torutil/ed25519"
"golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519"
@ -30,6 +32,11 @@ const (
CannotDialRicochetAddressError = utils.Error("CannotDialRicochetAddressError") CannotDialRicochetAddressError = utils.Error("CannotDialRicochetAddressError")
) )
const (
minStatusIntervalMs = 200
maxStatusIntervalMs = 2000
)
type onionListenService struct { type onionListenService struct {
os *tor.OnionService os *tor.OnionService
tp *torProvider tp *torProvider
@ -37,11 +44,13 @@ type onionListenService struct {
type torProvider struct { type torProvider struct {
t *tor.Tor t *tor.Tor
dialer *tor.Dialer
appDirectory string appDirectory string
bundeledTorPath string bundeledTorPath string
lock sync.Mutex lock sync.Mutex
breakChan chan bool breakChan chan bool
childListeners map[string]*onionListenService childListeners map[string]*onionListenService
statusCallback func(int, string)
} }
func (ols *onionListenService) AddressFull() string { func (ols *onionListenService) AddressFull() string {
@ -61,14 +70,14 @@ func (ols *onionListenService) Close() {
ols.os.Close() ols.os.Close()
} }
// GetBootstrapStatus returns an int 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message // GetBootstrapStatus returns an int -1 on error or 0-100 on the percent the bootstrapping of the underlying network is at and an optional string message
func (tp *torProvider) GetBootstrapStatus() (int, string) { func (tp *torProvider) GetBootstrapStatus() (int, string) {
if tp.t == nil { if tp.t == nil {
return 0, "error: no tor, trying to restart..." return -1, "error: no tor, trying to restart..."
} }
kvs, err := tp.t.Control.GetInfo("status/bootstrap-phase") kvs, err := tp.t.Control.GetInfo("status/bootstrap-phase")
if err != nil { if err != nil {
return 0, "error" return -1, "error"
} }
progress := 0 progress := 0
status := "" status := ""
@ -103,6 +112,9 @@ func (tp *torProvider) Listen(identity PrivateKey, port int) (ListenService, err
var onion = "" var onion = ""
var privkey ed25519.PrivateKey var privkey ed25519.PrivateKey
tp.lock.Lock()
defer tp.lock.Unlock()
if tp.t == nil { if tp.t == nil {
return nil, errors.New("Tor Provider closed") return nil, errors.New("Tor Provider closed")
} }
@ -125,14 +137,8 @@ func (tp *torProvider) Listen(identity PrivateKey, port int) (ListenService, err
localport += 1024 localport += 1024
} }
if tp.t == nil {
return nil, errors.New("Tor is offline")
}
localListener, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(localport)) localListener, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(localport))
tp.lock.Lock()
defer tp.lock.Unlock()
conf := &tor.ListenConf{NoWait: true, Version3: true, Key: identity, RemotePorts: []int{port}, Detach: true, DiscardKey: true, LocalListener: localListener} conf := &tor.ListenConf{NoWait: true, Version3: true, Key: identity, RemotePorts: []int{port}, Detach: true, DiscardKey: true, LocalListener: localListener}
os, err := tp.t.Listen(nil, conf) os, err := tp.t.Listen(nil, conf)
if err != nil && strings.Contains(err.Error(), "550 Unspecified Tor error: Onion address collision") { if err != nil && strings.Contains(err.Error(), "550 Unspecified Tor error: Onion address collision") {
@ -151,30 +157,29 @@ func (tp *torProvider) Listen(identity PrivateKey, port int) (ListenService, err
return ols, nil return ols, nil
} }
func (tp *torProvider) Restart() {
if tp.statusCallback != nil {
tp.statusCallback(0, "rebooting")
}
tp.restart()
}
func (tp *torProvider) Open(hostname string) (net.Conn, string, error) { func (tp *torProvider) Open(hostname string) (net.Conn, string, error) {
tp.lock.Lock() tp.lock.Lock()
defer tp.lock.Unlock()
if tp.t == nil { if tp.t == nil {
tp.lock.Unlock()
return nil, hostname, errors.New("Tor is offline") return nil, hostname, errors.New("Tor is offline")
} }
torDailer, err := tp.t.Dialer(nil, &tor.DialConf{}) tp.lock.Unlock()
if err != nil {
return nil, "", err
}
resolvedHostname := hostname resolvedHostname := hostname
if strings.HasPrefix(hostname, "ricochet:") { if strings.HasPrefix(hostname, "ricochet:") {
addrParts := strings.Split(hostname, ":") addrParts := strings.Split(hostname, ":")
resolvedHostname = addrParts[1] resolvedHostname = addrParts[1]
} }
conn, err := torDailer.Dial("tcp", resolvedHostname+".onion:9878") conn, err := tp.dialer.Dial("tcp", resolvedHostname+".onion:9878")
// if there was an error, we may have been cycling too fast
// clear the tor cache and try one more time
if err != nil {
tp.t.Control.Signal("NEWNYM")
conn, err = torDailer.Dial("tcp", resolvedHostname+".onion:9878")
}
return conn, resolvedHostname, err return conn, resolvedHostname, err
} }
@ -192,11 +197,39 @@ func (tp *torProvider) Close() {
} }
} }
func (tp *torProvider) SetStatusCallback(callback func(int, string)) {
tp.lock.Lock()
defer tp.lock.Unlock()
tp.statusCallback = callback
}
// StartTor creates/starts a Tor ACN and returns a usable ACN object // StartTor creates/starts a Tor ACN and returns a usable ACN object
func StartTor(appDirectory string, bundledTorPath string) (ACN, error) { func StartTor(appDirectory string, bundledTorPath string) (ACN, error) {
tp, err := startTor(appDirectory, bundledTorPath)
if err == nil {
tp.dialer, err = tp.t.Dialer(nil, &tor.DialConf{})
if err == nil {
go tp.monitorRestart()
}
}
return tp, err
}
// newHideCmd creates a Creator function for bine which generates a cmd that one windows will hide the dosbox
func newHideCmd(exePath string) process.Creator {
return process.CmdCreatorFunc(func(ctx context.Context, args ...string) (*exec.Cmd, error) {
cmd := exec.CommandContext(ctx, exePath, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.SysProcAttr = sysProcAttr
return cmd, nil
})
}
func startTor(appDirectory string, bundledTorPath string) (*torProvider, error) {
dataDir := path.Join(appDirectory, "tor") dataDir := path.Join(appDirectory, "tor")
os.MkdirAll(dataDir, 0700) os.MkdirAll(dataDir, 0700)
tp := &torProvider{appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool)} tp := &torProvider{appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool), statusCallback: nil}
// attempt connect to system tor // attempt connect to system tor
log.Debugf("dialing system tor control port\n") log.Debugf("dialing system tor control port\n")
@ -211,7 +244,6 @@ func StartTor(appDirectory string, bundledTorPath string) (ACN, error) {
if err == nil && minTorVersionReqs(pinfo.TorVersion) { if err == nil && minTorVersionReqs(pinfo.TorVersion) {
log.Debugln("OK version " + pinfo.TorVersion) log.Debugln("OK version " + pinfo.TorVersion)
tp.t = createFromExisting(controlport, dataDir) tp.t = createFromExisting(controlport, dataDir)
go tp.monitorRestart()
return tp, nil return tp, nil
} }
controlport.Close() controlport.Close()
@ -220,10 +252,9 @@ func StartTor(appDirectory string, bundledTorPath string) (ACN, error) {
// if not, try running system tor // if not, try running system tor
if checkCmdlineTorVersion("tor") { if checkCmdlineTorVersion("tor") {
t, err := tor.Start(nil, &tor.StartConf{EnableNetwork: true, DataDir: dataDir, DebugWriter: nil}) t, err := tor.Start(nil, &tor.StartConf{EnableNetwork: true, DataDir: dataDir, DebugWriter: nil, ProcessCreator: newHideCmd("tor")})
if err == nil { if err == nil {
tp.t = t tp.t = t
go tp.monitorRestart()
return tp, nil return tp, nil
} }
log.Debugf("Error connecting to self-run system tor: %v\n", err) log.Debugf("Error connecting to self-run system tor: %v\n", err)
@ -232,14 +263,11 @@ func StartTor(appDirectory string, bundledTorPath string) (ACN, error) {
// try running bundledTor // try running bundledTor
if bundledTorPath != "" && checkCmdlineTorVersion(bundledTorPath) { if bundledTorPath != "" && checkCmdlineTorVersion(bundledTorPath) {
log.Debugln("using bundled tor '" + bundledTorPath + "'") log.Debugln("using bundled tor '" + bundledTorPath + "'")
t, err := tor.Start(nil, &tor.StartConf{EnableNetwork: true, DataDir: dataDir, ExePath: bundledTorPath, DebugWriter: nil}) t, err := tor.Start(nil, &tor.StartConf{EnableNetwork: true, DataDir: dataDir, ExePath: bundledTorPath, DebugWriter: nil, ProcessCreator: newHideCmd(bundledTorPath)})
if err != nil { if err != nil {
log.Debugf("Error running bundled tor: %v\n", err) log.Debugf("Error running bundled tor: %v\n", err)
} }
tp.t = t tp.t = t
if err == nil {
go tp.monitorRestart()
}
return tp, err return tp, err
} }
return nil, errors.New("Could not connect to or start Tor that met requirments (min Tor version 0.3.5.x)") return nil, errors.New("Could not connect to or start Tor that met requirments (min Tor version 0.3.5.x)")
@ -252,41 +280,56 @@ func (tp *torProvider) unregisterListener(id string) {
} }
func (tp *torProvider) monitorRestart() { func (tp *torProvider) monitorRestart() {
lastBootstrapProgress := 0
interval := minStatusIntervalMs
for { for {
select { select {
case <-time.After(time.Duration(30 * time.Second)): case <-time.After(time.Millisecond * time.Duration(interval)):
tp.lock.Lock() prog, status := tp.GetBootstrapStatus()
if tp.t != nil {
_, err := tp.t.Control.GetInfo("version")
if err != nil { if prog == -1 && tp.t != nil {
tp.lock.Unlock() if tp.statusCallback != nil {
for _, child := range tp.childListeners { tp.statusCallback(prog, status)
child.Close() }
} tp.restart()
tp.lock.Lock() interval = minStatusIntervalMs
tp.t.Close() } else if prog != lastBootstrapProgress {
tp.t = nil if tp.statusCallback != nil {
tp.statusCallback(prog, status)
}
interval = minStatusIntervalMs
} else {
if interval < maxStatusIntervalMs {
interval *= 2
} }
} }
lastBootstrapProgress = prog
if tp.t == nil {
newACN, err := StartTor(tp.appDirectory, tp.bundeledTorPath)
if err == nil {
switch newTp := newACN.(type) {
case *torProvider:
tp.t = newTp.t
// startTor will have started a new monitorRestart thread
tp.lock.Unlock()
return
}
}
}
tp.lock.Unlock()
case <-tp.breakChan: case <-tp.breakChan:
return return
} }
}
}
func (tp *torProvider) restart() {
for _, child := range tp.childListeners {
child.Close()
}
tp.lock.Lock()
defer tp.lock.Unlock()
tp.t.Close()
tp.t = nil
for {
newTp, err := startTor(tp.appDirectory, tp.bundeledTorPath)
if err == nil {
tp.t = newTp.t
tp.dialer, _ = tp.t.Dialer(nil, &tor.DialConf{})
return
}
} }
} }
@ -311,6 +354,7 @@ func createFromExisting(controlport *control.Conn, datadir string) *tor.Tor {
func checkCmdlineTorVersion(torCmd string) bool { func checkCmdlineTorVersion(torCmd string) bool {
cmd := exec.Command(torCmd, "--version") cmd := exec.Command(torCmd, "--version")
cmd.SysProcAttr = sysProcAttr
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
re := regexp.MustCompile("[0-1]\\.[0-9]\\.[0-9]\\.[0-9]") re := regexp.MustCompile("[0-1]\\.[0-9]\\.[0-9]\\.[0-9]")
sysTorVersion := re.Find(out) sysTorVersion := re.Find(out)

View File

@ -3,21 +3,27 @@ package connectivity
import ( import (
"fmt" "fmt"
"testing" "testing"
"time"
) )
func getStatusCallback(progChan chan int) func(int, string) {
return func(prog int, status string) {
fmt.Printf("%v %v\n", prog, status)
progChan <- prog
}
}
func TestTorProvider(t *testing.T) { func TestTorProvider(t *testing.T) {
progChan := make(chan int)
acn, err := StartTor(".", "") acn, err := StartTor(".", "")
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return
} }
acn.SetStatusCallback(getStatusCallback(progChan))
progress := 0 progress := 0
status := ""
for progress < 100 { for progress < 100 {
progress, status = acn.GetBootstrapStatus() progress = <-progChan
fmt.Printf("%v %v\n", progress, status)
time.Sleep(100)
} }
acn.Close() acn.Close()

4
go.mod
View File

@ -2,10 +2,12 @@ module git.openprivacy.ca/openprivacy/libricochet-go
require ( require (
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412
github.com/cretz/bine v0.1.0 github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca
github.com/golang/protobuf v1.2.0 github.com/golang/protobuf v1.2.0
github.com/stretchr/testify v1.3.0 // indirect github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/crypto v0.0.0-20190128193316-c7b33c32a30b golang.org/x/crypto v0.0.0-20190128193316-c7b33c32a30b
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
) )
go 1.13

2
go.sum
View File

@ -2,6 +2,8 @@ github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7I
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/cretz/bine v0.1.0 h1:1/fvhLE+fk0bPzjdO5Ci+0ComYxEMuB1JhM4X5skT3g= github.com/cretz/bine v0.1.0 h1:1/fvhLE+fk0bPzjdO5Ci+0ComYxEMuB1JhM4X5skT3g=
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw=
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=

View File

@ -31,6 +31,7 @@ type Logger struct {
level Level level Level
nothingExceptPatterns []string nothingExceptPatterns []string
everythingFromPatterns []string everythingFromPatterns []string
excludeFromPatterns []string
} }
// New returns a new Logger with a filter set to the supplied level // New returns a new Logger with a filter set to the supplied level
@ -38,8 +39,23 @@ func New(level Level) *Logger {
return &Logger{logger: golog.New(os.Stderr, "", golog.Ldate|golog.Ltime), level: level, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0)} return &Logger{logger: golog.New(os.Stderr, "", golog.Ldate|golog.Ltime), level: level, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0)}
} }
// NewFile returns a new Logger that logs to the supplied file with a filter set to the supplied level
func NewFile(level Level, filename string) (*Logger, error) {
logfile, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
return nil, err
}
return &Logger{logger: golog.New(logfile, "", golog.Ldate|golog.Ltime), level: level, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0)}, nil
}
var std = New(LevelWarn) var std = New(LevelWarn)
// SetStd sets the default logger all other functions use
func SetStd(logger *Logger) {
std = logger
}
// filter // filter
func (l *Logger) filter(level Level) bool { func (l *Logger) filter(level Level) bool {
@ -48,6 +64,12 @@ func (l *Logger) filter(level Level) bool {
file = "???" file = "???"
} }
for _, pattern := range l.excludeFromPatterns {
if strings.Contains(file, pattern) {
return false
}
}
for _, pattern := range l.everythingFromPatterns { for _, pattern := range l.everythingFromPatterns {
if strings.Contains(file, pattern) { if strings.Contains(file, pattern) {
return true return true
@ -81,11 +103,16 @@ func (l *Logger) AddNothingExceptFilter(pattern string) {
l.nothingExceptPatterns = append(l.nothingExceptPatterns, pattern) l.nothingExceptPatterns = append(l.nothingExceptPatterns, pattern)
} }
// AddEverythingFromPattern adds a pattern to skip log level filtering, guaranteeing all logs matching hte pattern are seen // AddEverythingFromPattern adds a pattern to skip log level filtering, guaranteeing all logs matching the pattern are seen
func (l *Logger) AddEverythingFromPattern(pattern string) { func (l *Logger) AddEverythingFromPattern(pattern string) {
l.everythingFromPatterns = append(l.everythingFromPatterns, pattern) l.everythingFromPatterns = append(l.everythingFromPatterns, pattern)
} }
// ExcludeFromPattern adds a pattern to exclude logs from
func (l *Logger) ExcludeFromPattern(pattern string) {
l.excludeFromPatterns = append(l.excludeFromPatterns, pattern)
}
func (l *Logger) header(level Level) string { func (l *Logger) header(level Level) string {
_, file, _, ok := runtime.Caller(3) _, file, _, ok := runtime.Caller(3)
if !ok { if !ok {
@ -131,11 +158,16 @@ func AddNothingExceptFilter(pattern string) {
std.AddNothingExceptFilter(pattern) std.AddNothingExceptFilter(pattern)
} }
// AddEverythingFromPattern adds a pattern to skip log level filtering, guaranteeing all logs matching hte pattern are seen // AddEverythingFromPattern adds a pattern to skip log level filtering, guaranteeing all logs matching the pattern are seen
func AddEverythingFromPattern(pattern string) { func AddEverythingFromPattern(pattern string) {
std.AddEverythingFromPattern(pattern) std.AddEverythingFromPattern(pattern)
} }
// ExcludeFromPattern adds a pattern to exclude logs from
func ExcludeFromPattern(pattern string) {
std.ExcludeFromPattern(pattern)
}
// Printf outputs the format with variables assuming it passes the filter level // Printf outputs the format with variables assuming it passes the filter level
func Printf(level Level, format string, v ...interface{}) { func Printf(level Level, format string, v ...interface{}) {
std.Printf(level, format, v...) std.Printf(level, format, v...)

View File

@ -4,13 +4,14 @@
set -e set -e
pwd pwd
go test ${1} -coverprofile=model.cover.out -v ./utils GORACE="haltonerror=1"
go test ${1} -coverprofile=channels.cover.out -v ./channels go test -race ${1} -coverprofile=utils.cover.out -v ./utils
go test ${1} -coverprofile=channels.v3.inbound.cover.out -v ./channels/v3/inbound go test -race ${1} -coverprofile=channels.cover.out -v ./channels
go test ${1} -coverprofile=connection.cover.out -v ./connection go test -race ${1} -coverprofile=channels.v3.inbound.cover.out -v ./channels/v3/inbound
go test ${1} -coverprofile=policies.cover.out -v ./policies go test -race ${1} -coverprofile=connection.cover.out -v ./connection
go test ${1} -coverprofile=identity.cover.out -v ./identity go test -race ${1} -coverprofile=policies.cover.out -v ./policies
go test ${1} -coverprofile=root.cover.out -v ./ go test -race ${1} -coverprofile=identity.cover.out -v ./identity
go test -race ${1} -coverprofile=root.cover.out -v ./
echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \ echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \
awk '{if($1 != last) {print $0;last=$1}}' >> coverage.out awk '{if($1 != last) {print $0;last=$1}}' >> coverage.out
rm -rf *.cover.out rm -rf *.cover.out

View File

@ -8,6 +8,7 @@ import (
"git.openprivacy.ca/openprivacy/libricochet-go/log" "git.openprivacy.ca/openprivacy/libricochet-go/log"
"golang.org/x/crypto/nacl/secretbox" "golang.org/x/crypto/nacl/secretbox"
"io" "io"
"sync"
) )
const ( const (
@ -43,10 +44,13 @@ type RicochetNetwork struct {
// Derived ephemeral session key for connection // Derived ephemeral session key for connection
key [32]byte key [32]byte
encrypt bool encrypt bool
lock sync.Mutex
} }
// SetEncryptionKey sets the ephemeral encryption key for this session. // SetEncryptionKey sets the ephemeral encryption key for this session.
func (rn *RicochetNetwork) SetEncryptionKey(key [32]byte) { func (rn *RicochetNetwork) SetEncryptionKey(key [32]byte) {
rn.lock.Lock()
defer rn.lock.Unlock()
log.Debugf("turning on ephemeral session encryption for connection") log.Debugf("turning on ephemeral session encryption for connection")
copy(rn.key[:], key[:]) copy(rn.key[:], key[:])
@ -67,6 +71,7 @@ func (rn *RicochetNetwork) SendRicochetPacket(dst io.Writer, channel int32, data
binary.BigEndian.PutUint16(packet[2:4], uint16(channel)) binary.BigEndian.PutUint16(packet[2:4], uint16(channel))
copy(packet[4:], data[:]) copy(packet[4:], data[:])
rn.lock.Lock()
if rn.encrypt { if rn.encrypt {
var nonce [24]byte var nonce [24]byte
if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
@ -77,6 +82,7 @@ func (rn *RicochetNetwork) SendRicochetPacket(dst io.Writer, channel int32, data
binary.BigEndian.PutUint16(packet[0:2], uint16(len(encrypted)+2)) binary.BigEndian.PutUint16(packet[0:2], uint16(len(encrypted)+2))
packet = append(packet[0:2], encrypted...) packet = append(packet[0:2], encrypted...)
} }
rn.lock.Unlock()
for pos := 0; pos < len(packet); { for pos := 0; pos < len(packet); {
n, err := dst.Write(packet[pos:]) n, err := dst.Write(packet[pos:])
@ -112,6 +118,7 @@ func (rn *RicochetNetwork) RecvRicochetPacket(reader io.Reader) (RicochetData, e
return packet, err return packet, err
} }
rn.lock.Lock()
if rn.encrypt { if rn.encrypt {
var decryptNonce [24]byte var decryptNonce [24]byte
if len(packetBytes) > 24 { if len(packetBytes) > 24 {
@ -127,6 +134,7 @@ func (rn *RicochetNetwork) RecvRicochetPacket(reader io.Reader) (RicochetData, e
return packet, errors.New("ciphertext length was too short") return packet, errors.New("ciphertext length was too short")
} }
} }
rn.lock.Unlock()
packet.Channel = int32(binary.BigEndian.Uint16(packetBytes[0:2])) packet.Channel = int32(binary.BigEndian.Uint16(packetBytes[0:2]))
packet.Data = make([]byte, len(packetBytes)-2) packet.Data = make([]byte, len(packetBytes)-2)