forked from openprivacy/connectivity
Sketch of Tor Authenticator
This commit is contained in:
parent
94ce702214
commit
afda040693
|
@ -1,3 +1,6 @@
|
||||||
.idea/
|
.idea/
|
||||||
coverage.*
|
coverage.*
|
||||||
tor/tor/
|
tor/tor/
|
||||||
|
vendor/
|
||||||
|
*.cover.out
|
||||||
|
tmp/
|
||||||
|
|
52
README.md
52
README.md
|
@ -1,3 +1,53 @@
|
||||||
# connectivity
|
# 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
4
acn.go
|
@ -47,10 +47,6 @@ type ACN interface {
|
||||||
|
|
||||||
// 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
|
||||||
// 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)
|
Open(hostname string) (net.Conn, string, error)
|
||||||
|
|
||||||
// Listen takes a private key and a port and returns a ListenService for it
|
// Listen takes a private key and a port and returns a ListenService for it
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -4,7 +4,11 @@ go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0
|
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/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
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72
|
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
23
go.sum
|
@ -1,20 +1,43 @@
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
|
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
|
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 h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw=
|
||||||
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
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/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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/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 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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-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 h1:+ELyKg6m8UBf0nPFSqD0mi7zUfwPyXo23HNjMnXPz7w=
|
||||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
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 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
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-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 h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
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/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=
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
SOCKSPort 9050
|
SOCKSPort 9050
|
||||||
ControlPort 9051
|
ControlPort 9051
|
||||||
CookieAuthentication 0
|
# "examplehashedpassword" - used for testing
|
||||||
|
HashedControlPassword 16:C15305F97789414B601259E3EC5E76B8E55FC56A9F562B713F3D2BA257
|
||||||
# Needed for integ tests
|
# Needed for integ tests
|
||||||
RunAsDaemon 1
|
RunAsDaemon 1
|
|
@ -47,6 +47,7 @@ type onionListenService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type torProvider struct {
|
type torProvider struct {
|
||||||
|
controlPort int
|
||||||
t *tor.Tor
|
t *tor.Tor
|
||||||
dialer *tor.Dialer
|
dialer *tor.Dialer
|
||||||
appDirectory string
|
appDirectory string
|
||||||
|
@ -56,6 +57,7 @@ type torProvider struct {
|
||||||
childListeners map[string]*onionListenService
|
childListeners map[string]*onionListenService
|
||||||
statusCallback func(int, string)
|
statusCallback func(int, string)
|
||||||
lastRestartTime time.Time
|
lastRestartTime time.Time
|
||||||
|
authenticator Authenticator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ols *onionListenService) AddressFull() string {
|
func (ols *onionListenService) AddressFull() string {
|
||||||
|
@ -229,9 +231,9 @@ func (tp *torProvider) callStatusCallback(prog int, status string) {
|
||||||
tp.lock.Unlock()
|
tp.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTorACN creates/starts a Tor ACN and returns a usable ACN object
|
// NewTorACNWithAuth creates/starts a Tor ACN and returns a usable ACN object
|
||||||
func NewTorACN(appDirectory string, bundledTorPath string) (connectivity.ACN, error) {
|
func NewTorACNWithAuth(appDirectory string, bundledTorPath string, controlPort int, authenticator Authenticator) (connectivity.ACN, error) {
|
||||||
tp, err := startTor(appDirectory, bundledTorPath)
|
tp, err := startTor(appDirectory, bundledTorPath, controlPort, authenticator)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tp.dialer, err = tp.t.Dialer(nil, &tor.DialConf{})
|
tp.dialer, err = tp.t.Dialer(nil, &tor.DialConf{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -241,6 +243,11 @@ func NewTorACN(appDirectory string, bundledTorPath string) (connectivity.ACN, er
|
||||||
return tp, err
|
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
|
// newHideCmd creates a Creator function for bine which generates a cmd that one windows will hide the dosbox
|
||||||
func newHideCmd(exePath string) process.Creator {
|
func newHideCmd(exePath string) process.Creator {
|
||||||
return process.CmdCreatorFunc(func(ctx context.Context, args ...string) (*exec.Cmd, error) {
|
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")
|
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), 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
|
// attempt connect to system tor
|
||||||
log.Debugf("dialing system tor control port\n")
|
log.Debugf("dialing system tor control port\n")
|
||||||
controlport, err := dialControlPort(9051)
|
controlport, err := dialControlPort(tp.controlPort)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// TODO: configurable auth
|
// TODO: configurable auth
|
||||||
err := controlport.Authenticate("")
|
err := authenticator.Authenticate(controlport)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Debugln("connected to control port")
|
log.Debugln("connected to control port")
|
||||||
pinfo, err := controlport.ProtocolInfo()
|
pinfo, err := controlport.ProtocolInfo()
|
||||||
|
@ -352,7 +359,7 @@ func (tp *torProvider) restart() {
|
||||||
tp.t = nil
|
tp.t = nil
|
||||||
|
|
||||||
for {
|
for {
|
||||||
newTp, err := startTor(tp.appDirectory, tp.bundeledTorPath)
|
newTp, err := startTor(tp.appDirectory, tp.bundeledTorPath, tp.controlPort, tp.authenticator)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tp.t = newTp.t
|
tp.t = newTp.t
|
||||||
tp.dialer, _ = tp.t.Dialer(nil, &tor.DialConf{})
|
tp.dialer, _ = tp.t.Dialer(nil, &tor.DialConf{})
|
||||||
|
|
|
@ -14,7 +14,7 @@ func getStatusCallback(progChan chan int) func(int, string) {
|
||||||
|
|
||||||
func TestTorProvider(t *testing.T) {
|
func TestTorProvider(t *testing.T) {
|
||||||
progChan := make(chan int)
|
progChan := make(chan int)
|
||||||
acn, err := NewTorACN(".", "")
|
acn, err := NewTorACNWithAuth(".", "", 9051, HashedPasswordAuthenticator{"examplehashedpassword"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,6 +2,8 @@ package tor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
|
"errors"
|
||||||
|
"github.com/cretz/bine/control"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -49,3 +51,33 @@ func IsValidHostname(address string) bool {
|
||||||
}
|
}
|
||||||
return false
|
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")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue