Compare commits

...

6 Commits

35 changed files with 93 additions and 55 deletions

View File

@ -30,7 +30,7 @@ import (
"net/http"
"time"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/tor"
)
func main() {
@ -67,9 +67,9 @@ func main() {
```
If in `main.go` it can simply be run with `go run main.go`. Of course this uses a separate `tor` process. To embed Tor
statically in the binary, follow the [embedded package docs](https://godoc.org/github.com/cretz/bine/process/embedded)
statically in the binary, follow the [embedded package docs](https://godoc.org/git.openprivacy.ca/openprivacy/bine/process/embedded)
which will require [building Tor statically](https://github.com/cretz/tor-static). Then with
`github.com/cretz/bine/process/embedded` imported, change the start line above to:
`git.openprivacy.ca/openprivacy/bine/process/embedded` imported, change the start line above to:
```go
t, err := tor.Start(nil, &tor.StartConf{ProcessCreator: embedded.NewCreator()})

View File

@ -3,7 +3,7 @@ package control
import (
"strings"
"github.com/cretz/bine/torutil"
"git.openprivacy.ca/openprivacy/bine/torutil"
)
// SetConf invokes SETCONF.

View File

@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/cretz/bine/torutil"
"git.openprivacy.ca/openprivacy/bine/torutil"
)
// EventCode represents an asynchronous event code (ref control spec 4.1).

View File

@ -1,9 +1,8 @@
package control
import (
"git.openprivacy.ca/openprivacy/bine/torutil"
"strings"
"github.com/cretz/bine/torutil"
)
// Signal invokes SIGNAL.

View File

@ -8,8 +8,8 @@ import (
"strconv"
"strings"
"github.com/cretz/bine/torutil"
"github.com/cretz/bine/torutil/ed25519"
"git.openprivacy.ca/openprivacy/bine/torutil"
"git.openprivacy.ca/openprivacy/bine/torutil/ed25519"
)
// KeyType is a key type for Key in AddOnion.

View File

@ -3,7 +3,7 @@ package control
import (
"strings"
"github.com/cretz/bine/torutil"
"git.openprivacy.ca/openprivacy/bine/torutil"
)
// ProtocolInfo is the protocol info result of Conn.ProtocolInfo.

View File

@ -10,8 +10,8 @@ import (
"path/filepath"
"time"
"github.com/cretz/bine/process/embedded"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/process/embedded"
"git.openprivacy.ca/openprivacy/bine/tor"
)
func main() {

View File

@ -5,7 +5,7 @@ import (
"fmt"
"log"
"github.com/cretz/bine/process/embedded"
"git.openprivacy.ca/openprivacy/bine/process/embedded"
)
func main() {

View File

@ -14,8 +14,8 @@ import (
"path/filepath"
"strings"
"github.com/cretz/bine/tor"
"github.com/cretz/bine/torutil"
"git.openprivacy.ca/openprivacy/bine/tor"
"git.openprivacy.ca/openprivacy/bine/torutil"
)
var verbose bool

View File

@ -9,7 +9,7 @@ import (
"strings"
"time"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/tor"
"golang.org/x/net/html"
)

View File

@ -7,7 +7,7 @@ import (
"net/http"
"time"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/tor"
)
func main() {

2
go.mod
View File

@ -3,7 +3,7 @@ module git.openprivacy.ca/openprivacy/bine
go 1.14
require (
github.com/cretz/bine v0.1.0
git.openprivacy.ca/openprivacy/log v1.0.3
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb

2
go.sum
View File

@ -1,5 +1,3 @@
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/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View File

@ -21,9 +21,9 @@
package embedded
import (
"github.com/cretz/bine/process"
"git.openprivacy.ca/openprivacy/bine/process"
tor035 "github.com/cretz/bine/process/embedded/tor-0.3.5"
tor035 "git.openprivacy.ca/openprivacy/bine/process/embedded/tor-0.3.5"
)
// NewCreator creates a process.Creator for statically-linked Tor embedded in

View File

@ -5,7 +5,7 @@ import (
"log"
"os"
tor033 "github.com/cretz/bine/process/embedded/tor-0.3.3"
tor033 "git.openprivacy.ca/openprivacy/bine/process/embedded/tor-0.3.3"
)
// Simply calls Tor will the same parameters

View File

@ -8,7 +8,7 @@ import (
"fmt"
"net"
"github.com/cretz/bine/process"
"git.openprivacy.ca/openprivacy/bine/process"
)
/*

View File

@ -7,8 +7,8 @@ import (
"net/textproto"
"os"
"github.com/cretz/bine/control"
tor035 "github.com/cretz/bine/process/embedded/tor-0.3.5"
"git.openprivacy.ca/openprivacy/bine/control"
tor035 "git.openprivacy.ca/openprivacy/bine/process/embedded/tor-0.3.5"
)
// Simply calls Tor will the same parameters, unless "embedconn" is the arg

View File

@ -9,7 +9,7 @@ import (
"net"
"os"
"github.com/cretz/bine/process"
"git.openprivacy.ca/openprivacy/bine/process"
)
/*

View File

@ -16,7 +16,7 @@ import (
"strconv"
"strings"
"github.com/cretz/bine/torutil"
"git.openprivacy.ca/openprivacy/bine/torutil"
)
// Process is the interface implemented by Tor processes.

View File

@ -7,7 +7,7 @@ import (
"testing"
"time"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/tor"
"github.com/stretchr/testify/require"
)

View File

@ -3,7 +3,7 @@ package tests
import (
"testing"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/tor"
)
func TestAuthenticateNull(t *testing.T) {

View File

@ -4,7 +4,7 @@ import (
"io/ioutil"
"testing"
"github.com/cretz/bine/control"
"git.openprivacy.ca/openprivacy/bine/control"
)
func TestGetSetAndResetConf(t *testing.T) {

View File

@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/cretz/bine/control"
"git.openprivacy.ca/openprivacy/bine/control"
)
func TestHSFetch(t *testing.T) {

View File

@ -8,7 +8,7 @@ import (
"testing"
"time"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/tor"
"golang.org/x/net/context/ctxhttp"
)

View File

@ -3,8 +3,8 @@ package tests
import (
"testing"
"github.com/cretz/bine/tor"
"github.com/cretz/bine/torutil/geoipembed"
"git.openprivacy.ca/openprivacy/bine/tor"
"git.openprivacy.ca/openprivacy/bine/torutil/geoipembed"
)
func TestEmbeddedGeoIPFile(t *testing.T) {

View File

@ -7,7 +7,7 @@ import (
"testing"
"time"
"github.com/cretz/bine/tor"
"git.openprivacy.ca/openprivacy/bine/tor"
"golang.org/x/net/proxy"
)

View File

@ -6,8 +6,8 @@ import (
"testing"
"time"
"github.com/cretz/bine/tor"
"github.com/cretz/bine/torutil"
"git.openprivacy.ca/openprivacy/bine/tor"
"git.openprivacy.ca/openprivacy/bine/torutil"
)
func TestListenSimpleHTTPV2(t *testing.T) {

View File

@ -3,6 +3,7 @@ package tor
import (
"context"
"fmt"
"git.openprivacy.ca/openprivacy/bine/control"
"net"
"strings"
@ -14,6 +15,11 @@ type Dialer struct {
proxy.Dialer
}
// Authenticator provides a facade over various Tor control port authentication methods.
type Authenticator interface {
Authenticate(controlport *control.Conn) error
}
// DialConf is the configuration used for Dialer.
type DialConf struct {
// ProxyAddress is the address for the SOCKS5 proxy. If empty, it is looked
@ -39,6 +45,8 @@ type DialConf struct {
// Forward is the dialer to forward to. If nil, just uses normal net dialer.
Forward proxy.Dialer
Authenticator Authenticator
}
// Dialer creates a new Dialer for the given configuration. Context can be nil.
@ -50,6 +58,9 @@ func (t *Tor) Dialer(ctx context.Context, conf *DialConf) (*Dialer, error) {
if conf == nil {
conf = &DialConf{}
}
conf.Authenticator.Authenticate(t.Control)
// Enable the network if requested
if !conf.SkipEnableNetwork {
if err := t.EnableNetwork(ctx, true); err != nil {
@ -67,12 +78,23 @@ func (t *Tor) Dialer(ctx context.Context, conf *DialConf) (*Dialer, error) {
if len(info) != 1 || info[0].Key != "net/listeners/socks" {
return nil, fmt.Errorf("Unable to get socks proxy address")
}
proxyAddress = info[0].Val
if strings.HasPrefix(proxyAddress, "unix:") {
proxyAddress = proxyAddress[5:]
proxyNetwork = "unix"
} else {
if strings.HasPrefix(info[0].Val, "\"") {
options := strings.Split(info[0].Val, " ")
// we get this kind of response from Tails / OnionGrater, multiple potential listeners
// formatted. Simply choose the first one.
// NOTE: This logic is probably not the best...
proxyAddress = options[0][1 : len(options[0])-1]
proxyNetwork = "tcp"
} else {
proxyAddress = info[0].Val
if strings.HasPrefix(proxyAddress, "unix:") {
proxyAddress = proxyAddress[5:]
proxyNetwork = "unix"
} else {
proxyNetwork = "tcp"
}
}
} else if proxyNetwork == "" {
proxyNetwork = "tcp"

View File

@ -21,7 +21,7 @@ type OnionService struct {
// Key is the private key for this service. It is either the set key, the
// generated key, or nil if asked to discard the key. If present, it is
// *crypto/rsa.PrivateKey (1024 bit) when Version3 is false or
// github.com/cretz/bine/torutil/ed25519.KeyPair when Version3 is true.
// git.openprivacy.ca/openprivacy/bine/torutil/ed25519.KeyPair when Version3 is true.
Key crypto.PrivateKey
// Version3 says whether or not this service is a V3 service.
@ -66,9 +66,9 @@ type ListenConf struct {
// Key is the private key to use. If not present, a key is generated based
// on whether Version3 is true or false. If present, it must be a
// *crypto/rsa.PrivateKey (1024 bit), a
// github.com/cretz/bine/torutil/ed25519.KeyPair, a
// git.openprivacy.ca/openprivacy/bine/torutil/ed25519.KeyPair, a
// golang.org/x/crypto/ed25519.PrivateKey, or a
// github.com/cretz/bine/control.Key.
// git.openprivacy.ca/openprivacy/bine/control.Key.
Key crypto.PrivateKey
// Version3 determines whether, when Key is nil, a version 2 or version 3

View File

@ -173,11 +173,25 @@ func Start(ctx context.Context, conf *StartConf) (*Tor, error) {
if err == nil {
err = tor.startProcess(ctx, conf)
}
time.Sleep(time.Second)
// Connect the controller
if err == nil {
err = tor.connectController(ctx, conf)
for attempts := 0; attempts < 10; attempts++ {
err = tor.connectController(ctx, conf)
if err == nil {
break
} else {
// backoff and retry
// max is 1 + 2 + 3 + 4 + 5...+10 = ~55 seconds
// After which point there is probably something else very wrong
// TODO: It might be worth breaking out the error here so that we can distinguish a
// slow socket (on e.g. Android) with a failed setup.
time.Sleep(time.Duration(int(time.Second) * attempts))
}
}
}
// Attempt eager auth w/ no password
if err == nil && !conf.DisableEagerAuth {
err = tor.Control.Authenticate("")
@ -364,6 +378,7 @@ func (t *Tor) EnableNetwork(ctx context.Context, wait bool) error {
if ctx == nil {
ctx = context.Background()
}
// Only enable if DisableNetwork is 1
if vals, err := t.Control.GetConf("DisableNetwork"); err != nil {
return err

View File

@ -12,7 +12,7 @@ import (
"errors"
"io"
"github.com/cretz/bine/torutil/ed25519/internal/edwards25519"
"git.openprivacy.ca/openprivacy/bine/torutil/ed25519/internal/edwards25519"
"golang.org/x/crypto/ed25519"
)

View File

@ -11,7 +11,7 @@ import (
"strings"
"testing"
"github.com/cretz/bine/torutil/ed25519/internal/edwards25519"
"git.openprivacy.ca/openprivacy/bine/torutil/ed25519/internal/edwards25519"
)
// Taken from https://github.com/golang/crypto/blob/1a580b3eff7814fc9b40602fd35256c63b50f491/ed25519/ed25519_test.go

View File

@ -9,7 +9,7 @@ import (
"fmt"
"strings"
"github.com/cretz/bine/torutil/ed25519"
"git.openprivacy.ca/openprivacy/bine/torutil/ed25519"
"golang.org/x/crypto/sha3"
)
@ -17,7 +17,7 @@ var serviceIDEncoding = base32.StdEncoding.WithPadding(base32.NoPadding)
// OnionServiceIDFromPrivateKey generates the onion service ID from the given
// private key. This panics if the private key is not a 1024-bit
// crypto/*rsa.PrivateKey or github.com/cretz/bine/torutil/ed25519.KeyPair.
// crypto/*rsa.PrivateKey or git.openprivacy.ca/openprivacy/bine/torutil/ed25519.KeyPair.
func OnionServiceIDFromPrivateKey(key crypto.PrivateKey) string {
switch k := key.(type) {
case *rsa.PrivateKey:
@ -30,7 +30,7 @@ func OnionServiceIDFromPrivateKey(key crypto.PrivateKey) string {
// OnionServiceIDFromPublicKey generates the onion service ID from the given
// public key. This panics if the public key is not a 1024-bit
// crypto/*rsa.PublicKey or github.com/cretz/bine/torutil/ed25519.PublicKey.
// crypto/*rsa.PublicKey or git.openprivacy.ca/openprivacy/bine/torutil/ed25519.PublicKey.
func OnionServiceIDFromPublicKey(key crypto.PublicKey) string {
switch k := key.(type) {
case *rsa.PublicKey:

View File

@ -7,7 +7,7 @@ import (
"math/big"
"testing"
"github.com/cretz/bine/torutil/ed25519"
"git.openprivacy.ca/openprivacy/bine/torutil/ed25519"
"github.com/stretchr/testify/require"
)

View File

@ -70,7 +70,11 @@ func UnescapeSimpleQuotedString(str string) (string, error) {
if len(str) < 2 || str[0] != '"' || str[len(str)-1] != '"' {
return "", fmt.Errorf("Missing quotes")
}
return UnescapeSimpleQuotedStringContents(str[1 : len(str)-1])
if str, err := UnescapeSimpleQuotedStringContents(str[1 : len(str)-1]); err == nil {
return str, nil
}
// Assume this wasn't quoted
return str, nil
}
// UnescapeSimpleQuotedStringContents unescapes backslashes, double quotes,