Sketch of Tor Authenticator
the build was successful Details

This commit is contained in:
Sarah Jamie Lewis 2020-06-25 13:44:44 -07:00
parent 94ce702214
commit afda040693
9 changed files with 131 additions and 15 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
.idea/
coverage.*
tor/tor/
vendor/
*.cover.out
tmp/

View File

@ -1,3 +1,53 @@
# connectivity
A library providing an ACN (Anonymous Communication Network) abstraction and a tor (for now) implementation.
A library providing an ACN (Anonymous Communication Network
) networking abstraction
## Supported ACNs
* Tor v3 Onion Services
## Requirements for ACN Support
* Reference an EndPoint via a string / hostname
* Maintain an endpoint via a PublicKey (the underlying crypto is the
responsibility of the implementation)
## Using
Each ACN implementation provides a specific start function that takes in the
required parameters to e.g. find a specific binary on the system, attempt to
talk to a specific system service or launch an in-memory networking manager:
acn, err := NewTorACN(".", "", 9051, HashedPasswordAuthenticator{"examplehasedpassword"})
if err != nil {
t.Error(err)
return
}
At this point the ACN is responsible for setting up the networking interface,
the result of which can be checked via the Status callback:
acn.SetStatusCallback(getStatusCallback(progChan))
progress := 0
for progress < 100 {
progress = <-progChan
}
Once initialized the ACN can be used to open new connections:
conn,err := acn.Open(hostname);
Or host a service on the ACN:
ls,err := acn.Listen(identity, port) ;
We also provide closing and restart functionality for managing the networking
service:
acn.Restart()
and
acn.Close()

4
acn.go
View File

@ -47,10 +47,6 @@ type ACN interface {
// Open takes a hostname and returns a net.conn to the derived endpoint
// Open allows a client to resolve various hostnames to connections
// The supported types are onions address are:
// * ricochet:jlq67qzo6s4yp3sp
// * jlq67qzo6s4yp3sp
// * 127.0.0.1:55555|jlq67qzo6s4yp3sp - Localhost Connection
Open(hostname string) (net.Conn, string, error)
// Listen takes a private key and a port and returns a ListenService for it

4
go.mod
View File

@ -4,7 +4,11 @@ go 1.13
require (
git.openprivacy.ca/openprivacy/log v1.0.0
github.com/client9/misspell v0.3.4 // indirect
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf // indirect
github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/tools v0.0.0-20200625195345-7480c7b4547d // indirect
)

23
go.sum
View File

@ -1,20 +1,43 @@
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf h1:vc7Dmrk4JwS0ZPS6WZvWlwDflgDTA26jItmbSj83nug=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200625195345-7480c7b4547d h1:V1BGE5ZHrUIYZYNEm0i7jrPwSo3ks0HSn1TrartSqME=
golang.org/x/tools v0.0.0-20200625195345-7480c7b4547d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1,5 +1,6 @@
SOCKSPort 9050
ControlPort 9051
CookieAuthentication 0
# "examplehashedpassword" - used for testing
HashedControlPassword 16:C15305F97789414B601259E3EC5E76B8E55FC56A9F562B713F3D2BA257
# Needed for integ tests
RunAsDaemon 1

View File

@ -47,6 +47,7 @@ type onionListenService struct {
}
type torProvider struct {
controlPort int
t *tor.Tor
dialer *tor.Dialer
appDirectory string
@ -56,6 +57,7 @@ type torProvider struct {
childListeners map[string]*onionListenService
statusCallback func(int, string)
lastRestartTime time.Time
authenticator Authenticator
}
func (ols *onionListenService) AddressFull() string {
@ -229,9 +231,9 @@ func (tp *torProvider) callStatusCallback(prog int, status string) {
tp.lock.Unlock()
}
// NewTorACN creates/starts a Tor ACN and returns a usable ACN object
func NewTorACN(appDirectory string, bundledTorPath string) (connectivity.ACN, error) {
tp, err := startTor(appDirectory, bundledTorPath)
// NewTorACNWithAuth creates/starts a Tor ACN and returns a usable ACN object
func NewTorACNWithAuth(appDirectory string, bundledTorPath string, controlPort int, authenticator Authenticator) (connectivity.ACN, error) {
tp, err := startTor(appDirectory, bundledTorPath, controlPort, authenticator)
if err == nil {
tp.dialer, err = tp.t.Dialer(nil, &tor.DialConf{})
if err == nil {
@ -241,6 +243,11 @@ func NewTorACN(appDirectory string, bundledTorPath string) (connectivity.ACN, er
return tp, err
}
// NewTorACN creates/starts a Tor ACN and returns a usable ACN object with a NullAuthenticator - this will fail.
func NewTorACN(appDirectory string, bundledTorPath string) (connectivity.ACN, error) {
return NewTorACNWithAuth(appDirectory, bundledTorPath, 9051, NullAuthenticator{})
}
// 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) {
@ -252,18 +259,18 @@ func newHideCmd(exePath string) process.Creator {
})
}
func startTor(appDirectory string, bundledTorPath string) (*torProvider, error) {
func startTor(appDirectory string, bundledTorPath string, controlPort int, authenticator Authenticator) (*torProvider, error) {
dataDir := path.Join(appDirectory, "tor")
os.MkdirAll(dataDir, 0700)
tp := &torProvider{appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool), statusCallback: nil, lastRestartTime: time.Now().Add(-restartCooldown)}
tp := &torProvider{authenticator: authenticator, controlPort: controlPort, appDirectory: appDirectory, bundeledTorPath: bundledTorPath, childListeners: make(map[string]*onionListenService), breakChan: make(chan bool), statusCallback: nil, lastRestartTime: time.Now().Add(-restartCooldown)}
// attempt connect to system tor
log.Debugf("dialing system tor control port\n")
controlport, err := dialControlPort(9051)
controlport, err := dialControlPort(tp.controlPort)
if err == nil {
// TODO: configurable auth
err := controlport.Authenticate("")
err := authenticator.Authenticate(controlport)
if err == nil {
log.Debugln("connected to control port")
pinfo, err := controlport.ProtocolInfo()
@ -352,7 +359,7 @@ func (tp *torProvider) restart() {
tp.t = nil
for {
newTp, err := startTor(tp.appDirectory, tp.bundeledTorPath)
newTp, err := startTor(tp.appDirectory, tp.bundeledTorPath, tp.controlPort, tp.authenticator)
if err == nil {
tp.t = newTp.t
tp.dialer, _ = tp.t.Dialer(nil, &tor.DialConf{})

View File

@ -14,7 +14,7 @@ func getStatusCallback(progChan chan int) func(int, string) {
func TestTorProvider(t *testing.T) {
progChan := make(chan int)
acn, err := NewTorACN(".", "")
acn, err := NewTorACNWithAuth(".", "", 9051, HashedPasswordAuthenticator{"examplehashedpassword"})
if err != nil {
t.Error(err)
return

View File

@ -2,6 +2,8 @@ package tor
import (
"encoding/base32"
"errors"
"github.com/cretz/bine/control"
"golang.org/x/crypto/ed25519"
"golang.org/x/crypto/sha3"
"strings"
@ -49,3 +51,33 @@ func IsValidHostname(address string) bool {
}
return false
}
// Authenticator provides a facade over various Tor control port authentication methods.
type Authenticator interface {
Authenticate(controlport *control.Conn) error
}
// HashedPasswordAuthenticator authenticates to a Tor control port using a hashed password.
// Note: This method is vulnerable to replay attacks by the host system (but so is cookie auth)
type HashedPasswordAuthenticator struct {
password string
}
// Authenticate uses the given hashed password to authenticate to the control port
func (h HashedPasswordAuthenticator) Authenticate(controlport *control.Conn) error {
return controlport.Authenticate(h.password)
}
// NewHashedPasswordAuthenticator creates a new hashed password authenticator
func NewHashedPasswordAuthenticator(password string) Authenticator {
return HashedPasswordAuthenticator{password: password}
}
// NullAuthenticator exists to force always authenticating to a system tor.
type NullAuthenticator struct {
}
// Authenticate on a NullAuthenticator always results in failure.
func (n NullAuthenticator) Authenticate(controlport *control.Conn) error {
return errors.New("null authenticator provided, this control port is unsafe, start a new tor process instead")
}