diff options
-rw-r--r-- | obfs4proxy/obfs4proxy.go | 10 | ||||
-rw-r--r-- | obfs4proxy/pt_extra.go | 68 |
2 files changed, 78 insertions, 0 deletions
diff --git a/obfs4proxy/obfs4proxy.go b/obfs4proxy/obfs4proxy.go index ae18c5d..2e8a011 100644 --- a/obfs4proxy/obfs4proxy.go +++ b/obfs4proxy/obfs4proxy.go @@ -299,6 +299,16 @@ func clientSetup() (launched bool) { return } + ptClientProxy, err := ptGetProxy() + if err != nil { + log.Fatal(err) + return + } + if ptClientProxy != nil { + // XXX: Remove this once done. + ptProxyError("proxy are not supported yet") + } + for _, methodName := range ptClientInfo.MethodNames { switch methodName { case obfs4Method: diff --git a/obfs4proxy/pt_extra.go b/obfs4proxy/pt_extra.go index 889c7bd..4d629e8 100644 --- a/obfs4proxy/pt_extra.go +++ b/obfs4proxy/pt_extra.go @@ -30,6 +30,7 @@ package main import ( "errors" "fmt" + "net/url" "os" "git.torproject.org/pluggable-transports/goptlib" @@ -44,6 +45,17 @@ func ptEnvError(msg string) error { return errors.New(msg) } +func ptProxyError(msg string) error { + line := []byte(fmt.Sprintf("PROXY-ERROR %s\n", msg)) + pt.Stdout.Write(line) + return errors.New(msg) +} + +func ptProxyDone() { + line := []byte("PROXY DONE\n") + pt.Stdout.Write(line) +} + func ptMakeStateDir() (string, error) { dir := os.Getenv("TOR_PT_STATE_LOCATION") if dir == "" { @@ -65,3 +77,59 @@ func ptIsClient() (bool, error) { } return false, errors.New("not launched as a managed transport") } + +func ptGetProxy() (*url.URL, error) { + specString := os.Getenv("TOR_PT_PROXY") + if specString == "" { + return nil, nil + } + spec, err := url.Parse(specString) + if err != nil { + return nil, ptProxyError(fmt.Sprintf("failed to parse proxy config: %s", err)) + } + + // Validate the TOR_PT_PROXY uri. + if !spec.IsAbs() { + return nil, ptProxyError("proxy URI is relative, must be absolute") + } + if spec.Path != "" { + return nil, ptProxyError("proxy URI has a path defined") + } + if spec.RawQuery != "" { + return nil, ptProxyError("proxy URI has a query defined") + } + if spec.Fragment != "" { + return nil, ptProxyError("proxy URI has a fragment defined") + } + + switch spec.Scheme { + case "http": + // The most forgiving of proxies. + + case "socks4a": + if spec.User != nil { + _, isSet := spec.User.Password() + if isSet { + return nil, ptProxyError("proxy URI specified SOCKS4a and a password") + } + } + + case "socks5": + if spec.User != nil { + // UNAME/PASSWD both must be between 1 and 255 bytes long. (RFC1929) + user := spec.User.Username() + passwd, isSet := spec.User.Password() + if len(user) < 1 || len(user) > 255 { + return nil, ptProxyError("proxy URI specified a invalid SOCKS5 username") + } + if !isSet || len(passwd) < 1 || len(passwd) > 255 { + return nil, ptProxyError("proxy URI specified a invalid SOCKS5 password") + } + } + + default: + return nil, ptProxyError(fmt.Sprintf("proxy URI has invalid scheme: %s", spec.Scheme)) + } + + return spec, nil +} |