diff options
author | Yawning Angel <yawning@schwanenlied.me> | 2014-05-25 08:01:11 +0000 |
---|---|---|
committer | Yawning Angel <yawning@schwanenlied.me> | 2014-05-25 08:01:11 +0000 |
commit | d5c3a25dec7f235ce34890fcc0f9eb9e7933c2b0 (patch) | |
tree | 13bc70351698066c7e0464a4dbd442defdd18a32 /obfs4proxy | |
parent | f04fd166ac0ff7cf362db2e1d1958a32b17be25f (diff) |
Parse TOR_PT_PROXY and support sending DONE/PROXY-ERROR.
Currently obfs4proxy is hardcoded to always PROXY-ERROR, despite a
valid proxy uri being passed in the env var. Once the dialer portion
of the code is done, this will be changed.
Part of issue #7.
Diffstat (limited to 'obfs4proxy')
-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 +} |