From 67fe5d263d10c6f5f763d6dc3677e02a0a30df52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ken-H=C3=A5vard=20Lieng?= Date: Tue, 16 Jun 2020 03:04:27 +0200 Subject: [PATCH] Add SOCKS5 proxy support --- assets/bindata.go | 60 ++-- commands/dispatch.go | 7 + config.default.toml | 9 + config/config.go | 10 + pkg/irc/client.go | 10 +- pkg/irc/conn.go | 36 +- pkg/irc/dcc.go | 9 +- server/irc.go | 23 ++ server/irc_handler.go | 4 +- server/server.go | 3 +- .../golang.org/x/net/internal/socks/client.go | 168 ++++++++++ .../golang.org/x/net/internal/socks/socks.go | 317 ++++++++++++++++++ vendor/golang.org/x/net/proxy/dial.go | 54 +++ vendor/golang.org/x/net/proxy/direct.go | 31 ++ vendor/golang.org/x/net/proxy/per_host.go | 155 +++++++++ vendor/golang.org/x/net/proxy/proxy.go | 149 ++++++++ vendor/golang.org/x/net/proxy/socks5.go | 42 +++ vendor/modules.txt | 2 + 18 files changed, 1035 insertions(+), 54 deletions(-) create mode 100644 vendor/golang.org/x/net/internal/socks/client.go create mode 100644 vendor/golang.org/x/net/internal/socks/socks.go create mode 100644 vendor/golang.org/x/net/proxy/dial.go create mode 100644 vendor/golang.org/x/net/proxy/direct.go create mode 100644 vendor/golang.org/x/net/proxy/per_host.go create mode 100644 vendor/golang.org/x/net/proxy/proxy.go create mode 100644 vendor/golang.org/x/net/proxy/socks5.go diff --git a/assets/bindata.go b/assets/bindata.go index f41055da..7d164767 100644 --- a/assets/bindata.go +++ b/assets/bindata.go @@ -101,7 +101,7 @@ func _1014cd838551d3e3a690e3JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "10.14cd838551d3e3a690e3.js.br", size: 1598, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "10.14cd838551d3e3a690e3.js.br", size: 1598, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -121,7 +121,7 @@ func _67e2a42f8c15040ebc898JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "6.7e2a42f8c15040ebc898.js.br", size: 5591, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "6.7e2a42f8c15040ebc898.js.br", size: 5591, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -141,7 +141,7 @@ func _6D79bd6b64acff8a30833JsLicenseTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "6.d79bd6b64acff8a30833.js.LICENSE.txt", size: 363, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "6.d79bd6b64acff8a30833.js.LICENSE.txt", size: 363, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -161,7 +161,7 @@ func _772571641ae0eb79d7df7JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "7.72571641ae0eb79d7df7.js.br", size: 1596, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "7.72571641ae0eb79d7df7.js.br", size: 1596, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -181,7 +181,7 @@ func _8740b3764cbd22e073071JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "8.740b3764cbd22e073071.js.br", size: 4299, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "8.740b3764cbd22e073071.js.br", size: 4299, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -201,7 +201,7 @@ func _904bf3b947671461a2fc0JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "9.04bf3b947671461a2fc0.js.br", size: 4782, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "9.04bf3b947671461a2fc0.js.br", size: 4782, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -221,12 +221,12 @@ func boot3bbbaee908a8c0496383JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "boot.3bbbaee908a8c0496383.js.br", size: 151, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "boot.3bbbaee908a8c0496383.js.br", size: 151, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _configDefaultToml = "\x23\x20\x49\x50\x20\x61\x64\x64\x72\x65\x73\x73\x20\x74\x6f\x20\x6c\x69\x73\x74\x65\x6e\x20\x6f\x6e\x2c\x20\x6c\x65\x61\x76\x65\x20\x65\x6d\x70\x74\x79\x20\x74\x6f\x20\x6c\x69\x73\x74\x65\x6e\x20\x6f\x6e\x20\x61\x6e\x79\x74\x68\x69\x6e\x67\x0a\x61\x64\x64\x72\x65\x73\x73\x20\x3d\x20\x22\x22\x0a\x70\x6f\x72\x74\x20\x3d\x20\x38\x30\x0a\x23\x20\x48\x65\x78\x20\x65\x6e\x63\x6f\x64\x65\x20\x74\x68\x65\x20\x75\x73\x65\x72\x73\x20\x49\x50\x20\x61\x6e\x64\x20\x75\x73\x65\x20\x69\x74\x20\x61\x73\x20\x74\x68\x65\x20\x69\x64\x65\x6e\x74\x0a\x68\x65\x78\x49\x50\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x76\x65\x72\x69\x66\x79\x5f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x3d\x20\x74\x72\x75\x65\x0a\x0a\x23\x20\x44\x65\x66\x61\x75\x6c\x74\x73\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x63\x6c\x69\x65\x6e\x74\x20\x63\x6f\x6e\x6e\x65\x63\x74\x20\x66\x6f\x72\x6d\x0a\x5b\x64\x65\x66\x61\x75\x6c\x74\x73\x5d\x0a\x6e\x61\x6d\x65\x20\x3d\x20\x22\x66\x72\x65\x65\x6e\x6f\x64\x65\x22\x0a\x68\x6f\x73\x74\x20\x3d\x20\x22\x63\x68\x61\x74\x2e\x66\x72\x65\x65\x6e\x6f\x64\x65\x2e\x6e\x65\x74\x22\x0a\x70\x6f\x72\x74\x20\x3d\x20\x36\x36\x39\x37\x0a\x63\x68\x61\x6e\x6e\x65\x6c\x73\x20\x3d\x20\x5b\x0a\x20\x20\x22\x23\x64\x69\x73\x70\x61\x74\x63\x68\x22\x0a\x5d\x0a\x73\x65\x72\x76\x65\x72\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x3d\x20\x22\x22\x0a\x73\x73\x6c\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x4f\x6e\x6c\x79\x20\x61\x6c\x6c\x6f\x77\x20\x61\x20\x6e\x69\x63\x6b\x20\x74\x6f\x20\x62\x65\x20\x66\x69\x6c\x6c\x65\x64\x20\x69\x6e\x0a\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x23\x20\x53\x68\x6f\x77\x20\x73\x65\x72\x76\x65\x72\x20\x61\x6e\x64\x20\x63\x68\x61\x6e\x6e\x65\x6c\x20\x69\x6e\x66\x6f\x20\x77\x68\x65\x6e\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x69\x73\x20\x65\x6e\x61\x62\x6c\x65\x64\x0a\x73\x68\x6f\x77\x5f\x64\x65\x74\x61\x69\x6c\x73\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x0a\x5b\x68\x74\x74\x70\x73\x5d\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x0a\x70\x6f\x72\x74\x20\x3d\x20\x34\x34\x33\x0a\x23\x20\x50\x61\x74\x68\x20\x74\x6f\x20\x79\x6f\x75\x72\x20\x63\x65\x72\x74\x20\x61\x6e\x64\x20\x70\x72\x69\x76\x61\x74\x65\x20\x6b\x65\x79\x20\x69\x66\x20\x79\x6f\x75\x20\x61\x72\x65\x20\x6e\x6f\x74\x20\x75\x73\x69\x6e\x67\x0a\x23\x20\x74\x68\x65\x20\x4c\x65\x74\x27\x73\x20\x45\x6e\x63\x72\x79\x70\x74\x20\x69\x6e\x74\x65\x67\x72\x61\x74\x69\x6f\x6e\x0a\x63\x65\x72\x74\x20\x3d\x20\x22\x22\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x6c\x65\x74\x73\x65\x6e\x63\x72\x79\x70\x74\x5d\x0a\x23\x20\x59\x6f\x75\x72\x20\x64\x6f\x6d\x61\x69\x6e\x20\x6f\x72\x20\x73\x75\x62\x64\x6f\x6d\x61\x69\x6e\x2c\x20\x69\x66\x20\x6e\x6f\x74\x20\x73\x65\x74\x20\x61\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x77\x69\x6c\x6c\x20\x62\x65\x0a\x23\x20\x66\x65\x74\x63\x68\x65\x64\x20\x66\x6f\x72\x20\x77\x68\x61\x74\x65\x76\x65\x72\x20\x64\x6f\x6d\x61\x69\x6e\x20\x64\x69\x73\x70\x61\x74\x63\x68\x20\x67\x65\x74\x73\x20\x61\x63\x63\x65\x73\x73\x65\x64\x20\x74\x68\x72\x6f\x75\x67\x68\x0a\x64\x6f\x6d\x61\x69\x6e\x20\x3d\x20\x22\x22\x0a\x23\x20\x41\x6e\x20\x65\x6d\x61\x69\x6c\x20\x61\x64\x64\x72\x65\x73\x73\x20\x6c\x65\x74\x73\x20\x79\x6f\x75\x20\x72\x65\x63\x6f\x76\x65\x72\x20\x79\x6f\x75\x72\x20\x61\x63\x63\x6f\x75\x6e\x74\x73\x20\x70\x72\x69\x76\x61\x74\x65\x20\x6b\x65\x79\x0a\x65\x6d\x61\x69\x6c\x20\x3d\x20\x22\x22\x0a\x0a\x23\x20\x4e\x6f\x74\x20\x69\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x65\x64\x0a\x5b\x61\x75\x74\x68\x5d\x0a\x23\x20\x41\x6c\x6c\x6f\x77\x20\x75\x73\x61\x67\x65\x20\x77\x69\x74\x68\x6f\x75\x74\x20\x62\x65\x69\x6e\x67\x20\x6c\x6f\x67\x67\x65\x64\x20\x69\x6e\x2c\x20\x61\x6c\x6c\x20\x63\x68\x61\x6e\x6e\x65\x6c\x73\x20\x61\x6e\x64\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x67\x65\x74\x0a\x23\x20\x74\x72\x61\x6e\x73\x66\x65\x72\x72\x65\x64\x20\x77\x68\x65\x6e\x20\x6c\x6f\x67\x67\x69\x6e\x67\x20\x69\x6e\x20\x6f\x72\x20\x72\x65\x67\x69\x73\x74\x65\x72\x69\x6e\x67\x0a\x61\x6e\x6f\x6e\x79\x6d\x6f\x75\x73\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x45\x6e\x61\x62\x6c\x65\x20\x75\x73\x65\x72\x6e\x61\x6d\x65\x2f\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x6c\x6f\x67\x69\x6e\x0a\x6c\x6f\x67\x69\x6e\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x45\x6e\x61\x62\x6c\x65\x20\x75\x73\x65\x72\x6e\x61\x6d\x65\x2f\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x72\x65\x67\x69\x73\x74\x72\x61\x74\x69\x6f\x6e\x0a\x72\x65\x67\x69\x73\x74\x72\x61\x74\x69\x6f\x6e\x20\x3d\x20\x74\x72\x75\x65\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x67\x69\x74\x68\x75\x62\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x66\x61\x63\x65\x62\x6f\x6f\x6b\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x67\x6f\x6f\x67\x6c\x65\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x74\x77\x69\x74\x74\x65\x72\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x64\x63\x63\x5d\x0a\x23\x20\x52\x65\x63\x65\x69\x76\x65\x20\x66\x69\x6c\x65\x73\x20\x74\x68\x72\x6f\x75\x67\x68\x20\x44\x43\x43\x2c\x20\x74\x68\x65\x20\x75\x73\x65\x72\x20\x67\x65\x74\x73\x20\x74\x6f\x20\x63\x68\x6f\x6f\x73\x65\x20\x69\x66\x20\x74\x68\x65\x79\x20\x77\x61\x6e\x74\x20\x74\x6f\x20\x61\x63\x63\x65\x70\x74\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x2c\x0a\x23\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x74\x68\x65\x6e\x20\x67\x65\x74\x73\x20\x73\x74\x72\x65\x61\x6d\x65\x64\x20\x74\x6f\x20\x74\x68\x65\x20\x75\x73\x65\x72\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x0a\x0a\x5b\x64\x63\x63\x2e\x61\x75\x74\x6f\x67\x65\x74\x5d\x0a\x23\x20\x49\x6e\x73\x74\x65\x61\x64\x20\x6f\x66\x20\x73\x74\x72\x65\x61\x6d\x69\x6e\x67\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x74\x6f\x20\x74\x68\x65\x20\x75\x73\x65\x72\x2c\x20\x64\x69\x73\x70\x61\x74\x63\x68\x20\x61\x75\x74\x6f\x6d\x61\x74\x69\x63\x61\x6c\x6c\x79\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x73\x0a\x23\x20\x44\x43\x43\x20\x66\x69\x6c\x65\x73\x20\x61\x6e\x64\x20\x73\x65\x6e\x64\x73\x20\x61\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x20\x6c\x69\x6e\x6b\x20\x74\x6f\x20\x74\x68\x65\x20\x75\x73\x65\x72\x20\x6f\x6e\x63\x65\x20\x69\x74\x73\x20\x64\x6f\x6e\x65\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x23\x20\x44\x65\x6c\x65\x74\x65\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x61\x66\x74\x65\x72\x20\x74\x68\x65\x20\x75\x73\x65\x72\x20\x68\x61\x73\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x65\x64\x20\x69\x74\x20\x6f\x6e\x63\x65\x0a\x64\x65\x6c\x65\x74\x65\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x44\x65\x6c\x65\x74\x65\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x61\x66\x74\x65\x72\x20\x61\x20\x63\x65\x72\x74\x61\x69\x6e\x20\x74\x69\x6d\x65\x20\x70\x65\x72\x69\x6f\x64\x20\x6f\x66\x20\x69\x6e\x61\x63\x74\x69\x76\x69\x74\x79\x2c\x20\x6e\x6f\x74\x20\x69\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x65\x64\x20\x79\x65\x74\x0a\x64\x65\x6c\x65\x74\x65\x5f\x61\x66\x74\x65\x72\x20\x3d\x20\x22\x33\x30\x6d\x22\x0a\x0a\x23\x20\x53\x74\x72\x69\x63\x74\x2d\x54\x72\x61\x6e\x73\x70\x6f\x72\x74\x2d\x53\x65\x63\x75\x72\x69\x74\x79\x0a\x5b\x68\x74\x74\x70\x73\x2e\x68\x73\x74\x73\x5d\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x6d\x61\x78\x5f\x61\x67\x65\x20\x3d\x20\x33\x31\x35\x33\x36\x30\x30\x30\x0a\x69\x6e\x63\x6c\x75\x64\x65\x5f\x73\x75\x62\x64\x6f\x6d\x61\x69\x6e\x73\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x70\x72\x65\x6c\x6f\x61\x64\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x0a\x23\x20\x41\x64\x64\x20\x79\x6f\x75\x72\x20\x6f\x77\x6e\x20\x48\x54\x54\x50\x20\x68\x65\x61\x64\x65\x72\x73\x20\x74\x6f\x20\x74\x68\x65\x20\x69\x6e\x64\x65\x78\x20\x70\x61\x67\x65\x0a\x5b\x68\x65\x61\x64\x65\x72\x73\x5d\x0a\x23\x20\x58\x2d\x45\x78\x61\x6d\x70\x6c\x65\x20\x3d\x20\x22\x52\x61\x69\x6e\x62\x6f\x77\x73\x22\x0a" +var _configDefaultToml = "\x23\x20\x49\x50\x20\x61\x64\x64\x72\x65\x73\x73\x20\x74\x6f\x20\x6c\x69\x73\x74\x65\x6e\x20\x6f\x6e\x2c\x20\x6c\x65\x61\x76\x65\x20\x65\x6d\x70\x74\x79\x20\x74\x6f\x20\x6c\x69\x73\x74\x65\x6e\x20\x6f\x6e\x20\x61\x6e\x79\x74\x68\x69\x6e\x67\x0a\x61\x64\x64\x72\x65\x73\x73\x20\x3d\x20\x22\x22\x0a\x70\x6f\x72\x74\x20\x3d\x20\x38\x30\x0a\x23\x20\x48\x65\x78\x20\x65\x6e\x63\x6f\x64\x65\x20\x74\x68\x65\x20\x75\x73\x65\x72\x73\x20\x49\x50\x20\x61\x6e\x64\x20\x75\x73\x65\x20\x69\x74\x20\x61\x73\x20\x74\x68\x65\x20\x69\x64\x65\x6e\x74\x0a\x68\x65\x78\x49\x50\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x23\x20\x41\x75\x74\x6f\x6d\x61\x74\x69\x63\x61\x6c\x6c\x79\x20\x72\x65\x70\x6c\x79\x20\x74\x6f\x20\x63\x6f\x6d\x6d\x6f\x6e\x20\x43\x54\x43\x50\x20\x6d\x65\x73\x73\x61\x67\x65\x73\x0a\x61\x75\x74\x6f\x5f\x63\x74\x63\x70\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x56\x65\x72\x69\x66\x79\x20\x74\x68\x65\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x63\x68\x61\x69\x6e\x20\x70\x72\x65\x73\x65\x6e\x74\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x49\x52\x43\x20\x73\x65\x72\x76\x65\x72\x2c\x20\x69\x66\x20\x74\x68\x69\x73\x20\x63\x68\x65\x63\x6b\x20\x66\x61\x69\x6c\x73\x0a\x23\x20\x74\x68\x65\x20\x75\x73\x65\x72\x20\x77\x69\x6c\x6c\x20\x62\x65\x20\x61\x62\x6c\x65\x20\x74\x6f\x20\x63\x68\x6f\x6f\x73\x65\x20\x74\x6f\x20\x73\x74\x69\x6c\x6c\x20\x63\x6f\x6e\x6e\x65\x63\x74\x0a\x76\x65\x72\x69\x66\x79\x5f\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x3d\x20\x74\x72\x75\x65\x0a\x0a\x23\x20\x44\x65\x66\x61\x75\x6c\x74\x73\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x63\x6c\x69\x65\x6e\x74\x20\x63\x6f\x6e\x6e\x65\x63\x74\x20\x66\x6f\x72\x6d\x0a\x5b\x64\x65\x66\x61\x75\x6c\x74\x73\x5d\x0a\x6e\x61\x6d\x65\x20\x3d\x20\x22\x66\x72\x65\x65\x6e\x6f\x64\x65\x22\x0a\x68\x6f\x73\x74\x20\x3d\x20\x22\x63\x68\x61\x74\x2e\x66\x72\x65\x65\x6e\x6f\x64\x65\x2e\x6e\x65\x74\x22\x0a\x70\x6f\x72\x74\x20\x3d\x20\x36\x36\x39\x37\x0a\x63\x68\x61\x6e\x6e\x65\x6c\x73\x20\x3d\x20\x5b\x0a\x20\x20\x22\x23\x64\x69\x73\x70\x61\x74\x63\x68\x22\x0a\x5d\x0a\x73\x65\x72\x76\x65\x72\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x3d\x20\x22\x22\x0a\x73\x73\x6c\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x4f\x6e\x6c\x79\x20\x61\x6c\x6c\x6f\x77\x20\x61\x20\x6e\x69\x63\x6b\x20\x74\x6f\x20\x62\x65\x20\x66\x69\x6c\x6c\x65\x64\x20\x69\x6e\x0a\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x23\x20\x53\x68\x6f\x77\x20\x73\x65\x72\x76\x65\x72\x20\x61\x6e\x64\x20\x63\x68\x61\x6e\x6e\x65\x6c\x20\x69\x6e\x66\x6f\x20\x77\x68\x65\x6e\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x69\x73\x20\x65\x6e\x61\x62\x6c\x65\x64\x0a\x73\x68\x6f\x77\x5f\x64\x65\x74\x61\x69\x6c\x73\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x0a\x5b\x68\x74\x74\x70\x73\x5d\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x0a\x70\x6f\x72\x74\x20\x3d\x20\x34\x34\x33\x0a\x23\x20\x50\x61\x74\x68\x20\x74\x6f\x20\x79\x6f\x75\x72\x20\x63\x65\x72\x74\x20\x61\x6e\x64\x20\x70\x72\x69\x76\x61\x74\x65\x20\x6b\x65\x79\x20\x69\x66\x20\x79\x6f\x75\x20\x61\x72\x65\x20\x6e\x6f\x74\x20\x75\x73\x69\x6e\x67\x0a\x23\x20\x74\x68\x65\x20\x4c\x65\x74\x27\x73\x20\x45\x6e\x63\x72\x79\x70\x74\x20\x69\x6e\x74\x65\x67\x72\x61\x74\x69\x6f\x6e\x0a\x63\x65\x72\x74\x20\x3d\x20\x22\x22\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x6c\x65\x74\x73\x65\x6e\x63\x72\x79\x70\x74\x5d\x0a\x23\x20\x59\x6f\x75\x72\x20\x64\x6f\x6d\x61\x69\x6e\x20\x6f\x72\x20\x73\x75\x62\x64\x6f\x6d\x61\x69\x6e\x2c\x20\x69\x66\x20\x6e\x6f\x74\x20\x73\x65\x74\x20\x61\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x77\x69\x6c\x6c\x20\x62\x65\x0a\x23\x20\x66\x65\x74\x63\x68\x65\x64\x20\x66\x6f\x72\x20\x77\x68\x61\x74\x65\x76\x65\x72\x20\x64\x6f\x6d\x61\x69\x6e\x20\x64\x69\x73\x70\x61\x74\x63\x68\x20\x67\x65\x74\x73\x20\x61\x63\x63\x65\x73\x73\x65\x64\x20\x74\x68\x72\x6f\x75\x67\x68\x0a\x64\x6f\x6d\x61\x69\x6e\x20\x3d\x20\x22\x22\x0a\x23\x20\x41\x6e\x20\x65\x6d\x61\x69\x6c\x20\x61\x64\x64\x72\x65\x73\x73\x20\x6c\x65\x74\x73\x20\x79\x6f\x75\x20\x72\x65\x63\x6f\x76\x65\x72\x20\x79\x6f\x75\x72\x20\x61\x63\x63\x6f\x75\x6e\x74\x73\x20\x70\x72\x69\x76\x61\x74\x65\x20\x6b\x65\x79\x0a\x65\x6d\x61\x69\x6c\x20\x3d\x20\x22\x22\x0a\x0a\x23\x20\x4e\x6f\x74\x20\x69\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x65\x64\x0a\x5b\x61\x75\x74\x68\x5d\x0a\x23\x20\x41\x6c\x6c\x6f\x77\x20\x75\x73\x61\x67\x65\x20\x77\x69\x74\x68\x6f\x75\x74\x20\x62\x65\x69\x6e\x67\x20\x6c\x6f\x67\x67\x65\x64\x20\x69\x6e\x2c\x20\x61\x6c\x6c\x20\x63\x68\x61\x6e\x6e\x65\x6c\x73\x20\x61\x6e\x64\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x67\x65\x74\x0a\x23\x20\x74\x72\x61\x6e\x73\x66\x65\x72\x72\x65\x64\x20\x77\x68\x65\x6e\x20\x6c\x6f\x67\x67\x69\x6e\x67\x20\x69\x6e\x20\x6f\x72\x20\x72\x65\x67\x69\x73\x74\x65\x72\x69\x6e\x67\x0a\x61\x6e\x6f\x6e\x79\x6d\x6f\x75\x73\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x45\x6e\x61\x62\x6c\x65\x20\x75\x73\x65\x72\x6e\x61\x6d\x65\x2f\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x6c\x6f\x67\x69\x6e\x0a\x6c\x6f\x67\x69\x6e\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x45\x6e\x61\x62\x6c\x65\x20\x75\x73\x65\x72\x6e\x61\x6d\x65\x2f\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x72\x65\x67\x69\x73\x74\x72\x61\x74\x69\x6f\x6e\x0a\x72\x65\x67\x69\x73\x74\x72\x61\x74\x69\x6f\x6e\x20\x3d\x20\x74\x72\x75\x65\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x67\x69\x74\x68\x75\x62\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x66\x61\x63\x65\x62\x6f\x6f\x6b\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x67\x6f\x6f\x67\x6c\x65\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x61\x75\x74\x68\x2e\x70\x72\x6f\x76\x69\x64\x65\x72\x73\x2e\x74\x77\x69\x74\x74\x65\x72\x5d\x0a\x6b\x65\x79\x20\x3d\x20\x22\x22\x0a\x73\x65\x63\x72\x65\x74\x20\x3d\x20\x22\x22\x0a\x0a\x5b\x64\x63\x63\x5d\x0a\x23\x20\x52\x65\x63\x65\x69\x76\x65\x20\x66\x69\x6c\x65\x73\x20\x74\x68\x72\x6f\x75\x67\x68\x20\x44\x43\x43\x2c\x20\x74\x68\x65\x20\x75\x73\x65\x72\x20\x67\x65\x74\x73\x20\x74\x6f\x20\x63\x68\x6f\x6f\x73\x65\x20\x69\x66\x20\x74\x68\x65\x79\x20\x77\x61\x6e\x74\x20\x74\x6f\x20\x61\x63\x63\x65\x70\x74\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x2c\x0a\x23\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x20\x74\x68\x65\x6e\x20\x67\x65\x74\x73\x20\x70\x72\x6f\x78\x69\x65\x64\x20\x74\x6f\x20\x74\x68\x65\x20\x75\x73\x65\x72\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x74\x72\x75\x65\x0a\x0a\x5b\x64\x63\x63\x2e\x61\x75\x74\x6f\x67\x65\x74\x5d\x0a\x23\x20\x49\x6e\x73\x74\x65\x61\x64\x20\x6f\x66\x20\x70\x72\x6f\x78\x79\x69\x6e\x67\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x20\x64\x69\x72\x65\x63\x74\x6c\x79\x20\x74\x6f\x20\x74\x68\x65\x20\x75\x73\x65\x72\x2c\x20\x64\x69\x73\x70\x61\x74\x63\x68\x20\x61\x75\x74\x6f\x6d\x61\x74\x69\x63\x61\x6c\x6c\x79\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x73\x0a\x23\x20\x44\x43\x43\x20\x66\x69\x6c\x65\x73\x20\x61\x6e\x64\x20\x73\x65\x6e\x64\x73\x20\x61\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x20\x6c\x69\x6e\x6b\x20\x74\x6f\x20\x74\x68\x65\x20\x75\x73\x65\x72\x20\x6f\x6e\x63\x65\x20\x69\x74\x73\x20\x64\x6f\x6e\x65\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x23\x20\x44\x65\x6c\x65\x74\x65\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x61\x66\x74\x65\x72\x20\x74\x68\x65\x20\x75\x73\x65\x72\x20\x68\x61\x73\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x65\x64\x20\x69\x74\x20\x6f\x6e\x63\x65\x0a\x64\x65\x6c\x65\x74\x65\x20\x3d\x20\x74\x72\x75\x65\x0a\x23\x20\x44\x65\x6c\x65\x74\x65\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x20\x61\x66\x74\x65\x72\x20\x61\x20\x63\x65\x72\x74\x61\x69\x6e\x20\x74\x69\x6d\x65\x20\x70\x65\x72\x69\x6f\x64\x20\x6f\x66\x20\x69\x6e\x61\x63\x74\x69\x76\x69\x74\x79\x2c\x20\x6e\x6f\x74\x20\x69\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x65\x64\x20\x79\x65\x74\x0a\x64\x65\x6c\x65\x74\x65\x5f\x61\x66\x74\x65\x72\x20\x3d\x20\x22\x33\x30\x6d\x22\x0a\x0a\x5b\x70\x72\x6f\x78\x79\x5d\x0a\x23\x20\x44\x69\x73\x70\x61\x74\x63\x68\x20\x77\x69\x6c\x6c\x20\x6d\x61\x6b\x65\x20\x61\x6c\x6c\x20\x6f\x75\x74\x67\x6f\x69\x6e\x67\x20\x63\x6f\x6e\x6e\x65\x63\x74\x69\x6f\x6e\x73\x20\x74\x68\x72\x6f\x75\x67\x68\x20\x74\x68\x65\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x20\x70\x72\x6f\x78\x79\x20\x77\x68\x65\x6e\x20\x65\x6e\x61\x62\x6c\x65\x64\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x20\x22\x73\x6f\x63\x6b\x73\x35\x22\x0a\x68\x6f\x73\x74\x20\x3d\x20\x22\x31\x32\x37\x2e\x30\x2e\x30\x2e\x31\x22\x0a\x70\x6f\x72\x74\x20\x3d\x20\x31\x30\x38\x30\x0a\x75\x73\x65\x72\x6e\x61\x6d\x65\x20\x3d\x20\x22\x22\x0a\x70\x61\x73\x73\x77\x6f\x72\x64\x20\x3d\x20\x22\x22\x0a\x0a\x23\x20\x48\x54\x54\x50\x20\x53\x74\x72\x69\x63\x74\x2d\x54\x72\x61\x6e\x73\x70\x6f\x72\x74\x2d\x53\x65\x63\x75\x72\x69\x74\x79\x0a\x5b\x68\x74\x74\x70\x73\x2e\x68\x73\x74\x73\x5d\x0a\x65\x6e\x61\x62\x6c\x65\x64\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x6d\x61\x78\x5f\x61\x67\x65\x20\x3d\x20\x33\x31\x35\x33\x36\x30\x30\x30\x0a\x69\x6e\x63\x6c\x75\x64\x65\x5f\x73\x75\x62\x64\x6f\x6d\x61\x69\x6e\x73\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x70\x72\x65\x6c\x6f\x61\x64\x20\x3d\x20\x66\x61\x6c\x73\x65\x0a\x0a\x23\x20\x41\x64\x64\x20\x79\x6f\x75\x72\x20\x6f\x77\x6e\x20\x48\x54\x54\x50\x20\x68\x65\x61\x64\x65\x72\x73\x20\x74\x6f\x20\x74\x68\x65\x20\x69\x6e\x64\x65\x78\x20\x70\x61\x67\x65\x0a\x5b\x68\x65\x61\x64\x65\x72\x73\x5d\x0a\x23\x20\x58\x2d\x45\x78\x61\x6d\x70\x6c\x65\x20\x3d\x20\x22\x52\x61\x69\x6e\x62\x6f\x77\x73\x22\x0a" func configDefaultTomlBytes() ([]byte, error) { return bindataRead( @@ -241,7 +241,7 @@ func configDefaultToml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "config.default.toml", size: 1986, mode: os.FileMode(438), modTime: time.Unix(1592211627, 0)} + info := bindataFileInfo{name: "config.default.toml", size: 2401, mode: os.FileMode(438), modTime: time.Unix(1592268862, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -261,7 +261,7 @@ func connect221f01bcad19a228e175JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "connect.221f01bcad19a228e175.js.br", size: 2671, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "connect.221f01bcad19a228e175.js.br", size: 2671, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -281,7 +281,7 @@ func faviconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "favicon.ico", size: 5430, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "favicon.ico", size: 5430, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -301,7 +301,7 @@ func fontMontserratBoldWoff() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/Montserrat-Bold.woff", size: 14076, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/Montserrat-Bold.woff", size: 14076, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -321,7 +321,7 @@ func fontMontserratBoldWoff2() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/Montserrat-Bold.woff2", size: 9636, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/Montserrat-Bold.woff2", size: 9636, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -341,7 +341,7 @@ func fontMontserratRegularWoff() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/Montserrat-Regular.woff", size: 14100, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/Montserrat-Regular.woff", size: 14100, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -361,7 +361,7 @@ func fontMontserratRegularWoff2() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/Montserrat-Regular.woff2", size: 9688, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/Montserrat-Regular.woff2", size: 9688, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -381,7 +381,7 @@ func fontRobotomonoBoldWoff() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/RobotoMono-Bold.woff", size: 20304, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/RobotoMono-Bold.woff", size: 20304, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -401,7 +401,7 @@ func fontRobotomonoBoldWoff2() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/RobotoMono-Bold.woff2", size: 16028, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/RobotoMono-Bold.woff2", size: 16028, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -421,7 +421,7 @@ func fontRobotomonoRegularWoff() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/RobotoMono-Regular.woff", size: 20316, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/RobotoMono-Regular.woff", size: 20316, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -441,7 +441,7 @@ func fontRobotomonoRegularWoff2() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "font/RobotoMono-Regular.woff2", size: 16108, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "font/RobotoMono-Regular.woff2", size: 16108, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -461,7 +461,7 @@ func icon_192Png() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "icon_192.png", size: 13364, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "icon_192.png", size: 13364, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -481,7 +481,7 @@ func icon_512Png() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "icon_512.png", size: 52660, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "icon_512.png", size: 52660, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -501,7 +501,7 @@ func main6e2f9707840af18d703aCssBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "main.6e2f9707840af18d703a.css.br", size: 2829, mode: os.FileMode(438), modTime: time.Unix(1592211643, 0)} + info := bindataFileInfo{name: "main.6e2f9707840af18d703a.css.br", size: 2829, mode: os.FileMode(438), modTime: time.Unix(1592268875, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -521,7 +521,7 @@ func mainEa6539a6d81f2477f278JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "main.ea6539a6d81f2477f278.js.br", size: 14631, mode: os.FileMode(438), modTime: time.Unix(1592211644, 0)} + info := bindataFileInfo{name: "main.ea6539a6d81f2477f278.js.br", size: 14631, mode: os.FileMode(438), modTime: time.Unix(1592268876, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -541,7 +541,7 @@ func manifestJsonBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "manifest.json.br", size: 168, mode: os.FileMode(438), modTime: time.Unix(1592211644, 0)} + info := bindataFileInfo{name: "manifest.json.br", size: 168, mode: os.FileMode(438), modTime: time.Unix(1592268876, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -561,7 +561,7 @@ func runtime826f1d36a180b6a1ef8bJsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "runtime.826f1d36a180b6a1ef8b.js.br", size: 1110, mode: os.FileMode(438), modTime: time.Unix(1592211644, 0)} + info := bindataFileInfo{name: "runtime.826f1d36a180b6a1ef8b.js.br", size: 1110, mode: os.FileMode(438), modTime: time.Unix(1592268876, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -581,7 +581,7 @@ func swJsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "sw.js.br", size: 5321, mode: os.FileMode(438), modTime: time.Unix(1592211644, 0)} + info := bindataFileInfo{name: "sw.js.br", size: 5321, mode: os.FileMode(438), modTime: time.Unix(1592268876, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -601,7 +601,7 @@ func vendorsConnect3d9e4b38d1d847a2adc0JsLicenseTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "vendors~connect.3d9e4b38d1d847a2adc0.js.LICENSE.txt", size: 246, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "vendors~connect.3d9e4b38d1d847a2adc0.js.LICENSE.txt", size: 246, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -621,7 +621,7 @@ func vendorsConnect4974860b3043e16c3cc9JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "vendors~connect.4974860b3043e16c3cc9.js.br", size: 12192, mode: os.FileMode(438), modTime: time.Unix(1592211644, 0)} + info := bindataFileInfo{name: "vendors~connect.4974860b3043e16c3cc9.js.br", size: 12192, mode: os.FileMode(438), modTime: time.Unix(1592268876, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -641,7 +641,7 @@ func vendorsMain4e764db916b94e84a1a0JsLicenseTxt() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "vendors~main.4e764db916b94e84a1a0.js.LICENSE.txt", size: 1329, mode: os.FileMode(438), modTime: time.Unix(1592211642, 0)} + info := bindataFileInfo{name: "vendors~main.4e764db916b94e84a1a0.js.LICENSE.txt", size: 1329, mode: os.FileMode(438), modTime: time.Unix(1592268874, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -661,7 +661,7 @@ func vendorsMainA6279a534b718800ea26JsBr() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "vendors~main.a6279a534b718800ea26.js.br", size: 71675, mode: os.FileMode(438), modTime: time.Unix(1592211644, 0)} + info := bindataFileInfo{name: "vendors~main.a6279a534b718800ea26.js.br", size: 71675, mode: os.FileMode(438), modTime: time.Unix(1592268876, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/commands/dispatch.go b/commands/dispatch.go index 7d699396..5700a770 100644 --- a/commands/dispatch.go +++ b/commands/dispatch.go @@ -114,13 +114,20 @@ func init() { viper.SetDefault("auto_ctcp", true) viper.SetDefault("verify_certificates", true) + viper.SetDefault("https.enabled", true) viper.SetDefault("https.port", 443) + viper.SetDefault("auth.anonymous", true) viper.SetDefault("auth.login", true) viper.SetDefault("auth.registration", true) + viper.SetDefault("dcc.enabled", true) viper.SetDefault("dcc.autoget.delete", true) + + viper.SetDefault("proxy.protocol", "socks5") + viper.SetDefault("proxy.host", "127.0.0.1") + viper.SetDefault("proxy.port", 1080) } func initConfig(configPath string, overwrite bool) error { diff --git a/config.default.toml b/config.default.toml index f69168ed..9378f79d 100644 --- a/config.default.toml +++ b/config.default.toml @@ -79,6 +79,15 @@ delete = true # Delete the file after a certain time period of inactivity, not implemented yet delete_after = "30m" +[proxy] +# Dispatch will make all outgoing connections through the specified proxy when enabled +enabled = false +protocol = "socks5" +host = "127.0.0.1" +port = 1080 +username = "" +password = "" + # HTTP Strict-Transport-Security [https.hsts] enabled = false diff --git a/config/config.go b/config/config.go index ca6a15e0..f0b74048 100644 --- a/config/config.go +++ b/config/config.go @@ -21,6 +21,7 @@ type Config struct { LetsEncrypt LetsEncrypt Auth Auth DCC DCC + Proxy Proxy } type Defaults struct { @@ -77,6 +78,15 @@ type Autoget struct { DeleteAfter time.Duration `mapstructure:"delete_after"` } +type Proxy struct { + Enabled bool + Protocol string + Host string + Port string + Username string + Password string +} + func LoadConfig() (*Config, chan *Config) { viper.SetConfigName("config") viper.AddConfigPath(storage.Path.ConfigRoot()) diff --git a/pkg/irc/client.go b/pkg/irc/client.go index 95d529fd..6aefb2be 100644 --- a/pkg/irc/client.go +++ b/pkg/irc/client.go @@ -33,6 +33,8 @@ type Config struct { Source string HandleNickInUse func(string) string + + Dialer Dialer } type Client struct { @@ -56,7 +58,7 @@ type Client struct { conn net.Conn connected bool registered bool - dialer *net.Dialer + dialer Dialer recvBuf []byte scan *bufio.Scanner backoff *backoff.Backoff @@ -89,6 +91,10 @@ func NewClient(config *Config) *Client { config.SASLMechanisms = DefaultSASLMechanisms } + if config.Dialer == nil { + config.Dialer = DefaultDialer + } + client := &Client{ Config: config, Messages: make(chan *Message, 32), @@ -97,7 +103,7 @@ func NewClient(config *Config) *Client { nick: config.Nick, requestedCapabilities: map[string][]string{}, enabledCapabilities: map[string][]string{}, - dialer: &net.Dialer{Timeout: 10 * time.Second}, + dialer: config.Dialer, recvBuf: make([]byte, 0, 4096), backoff: &backoff.Backoff{ Min: 500 * time.Millisecond, diff --git a/pkg/irc/conn.go b/pkg/irc/conn.go index c0b66220..b97e6eda 100644 --- a/pkg/irc/conn.go +++ b/pkg/irc/conn.go @@ -12,9 +12,15 @@ import ( ) var ( + DefaultDialer = &net.Dialer{Timeout: 10 * time.Second} + ErrBadProtocol = errors.New("This server does not speak IRC") ) +type Dialer interface { + Dial(network, address string) (net.Conn, error) +} + func (c *Client) Connect() { c.connChange(false, nil) go c.run() @@ -119,23 +125,23 @@ func (c *Client) connect() error { c.lock.Lock() defer c.lock.Unlock() - addr := net.JoinHostPort(c.Config.Host, c.Config.Port) - if c.Config.TLS { - conn, err := tls.DialWithDialer(c.dialer, "tcp", addr, c.Config.TLSConfig) - if err != nil { - return err - } - - c.conn = conn - } else { - conn, err := c.dialer.Dial("tcp", addr) - if err != nil { - return err - } - - c.conn = conn + conn, err := c.dialer.Dial("tcp", net.JoinHostPort(c.Config.Host, c.Config.Port)) + if err != nil { + return err } + if c.Config.TLS { + c.Config.TLSConfig.ServerName = c.Config.Host + + tlsConn := tls.Client(conn, c.Config.TLSConfig) + err = tlsConn.Handshake() + if err != nil { + return err + } + conn = tlsConn + } + + c.conn = conn c.connected = true c.connChange(true, nil) c.scan = bufio.NewScanner(c.conn) diff --git a/pkg/irc/dcc.go b/pkg/irc/dcc.go index daef9e34..8cfc3696 100644 --- a/pkg/irc/dcc.go +++ b/pkg/irc/dcc.go @@ -17,9 +17,11 @@ type DCCSend struct { IP string `json:"ip"` Port string `json:"port"` Length uint64 `json:"length"` + + dialer Dialer } -func ParseDCCSend(ctcp *CTCP) *DCCSend { +func (c *Client) ParseDCCSend(ctcp *CTCP) *DCCSend { params := strings.Split(ctcp.Params, " ") if len(params) > 4 { @@ -43,20 +45,21 @@ func ParseDCCSend(ctcp *CTCP) *DCCSend { IP: intToIP(ip), Port: params[3], Length: length, + dialer: c.dialer, } } return nil } -func DownloadDCC(w io.Writer, pack *DCCSend, progress chan DownloadProgress) error { +func (pack *DCCSend) Download(w io.Writer, progress chan DownloadProgress) error { if progress != nil { progress <- DownloadProgress{ File: pack.File, } } - conn, err := net.DialTimeout("tcp", net.JoinHostPort(pack.IP, pack.Port), 10*time.Second) + conn, err := pack.dialer.Dial("tcp", net.JoinHostPort(pack.IP, pack.Port)) if err != nil { return err } diff --git a/server/irc.go b/server/irc.go index a24e35d9..0f7d4b2e 100644 --- a/server/irc.go +++ b/server/irc.go @@ -4,9 +4,13 @@ import ( "crypto/tls" "encoding/hex" "fmt" + "log" + "net" + "strings" "github.com/khlieng/dispatch/pkg/irc" "github.com/khlieng/dispatch/storage" + "golang.org/x/net/proxy" ) func createNickInUseHandler(i *irc.Client, state *State) func(string) string { @@ -54,6 +58,25 @@ func connectIRC(network *storage.Network, state *State, srcIP []byte) *irc.Clien ircCfg.ServerPassword = cfg.Defaults.ServerPassword } + if cfg.Proxy.Enabled && strings.ToLower(cfg.Proxy.Protocol) == "socks5" { + addr := net.JoinHostPort(cfg.Proxy.Host, cfg.Proxy.Port) + + var auth *proxy.Auth + if cfg.Proxy.Username != "" { + auth = &proxy.Auth{ + User: cfg.Proxy.Username, + Password: cfg.Proxy.Password, + } + } + + dialer, err := proxy.SOCKS5("tcp", addr, auth, irc.DefaultDialer) + if err != nil { + log.Println(err) + } else { + ircCfg.Dialer = dialer + } + } + i := irc.NewClient(ircCfg) i.Config.HandleNickInUse = createNickInUseHandler(i, state) diff --git a/server/irc_handler.go b/server/irc_handler.go index 5d5163a8..b5d9efdb 100644 --- a/server/irc_handler.go +++ b/server/irc_handler.go @@ -231,7 +231,7 @@ func (i *ircHandler) mode(msg *irc.Message) { func (i *ircHandler) message(msg *irc.Message) { if ctcp := msg.ToCTCP(); ctcp != nil { if ctcp.Command == "DCC" && strings.HasPrefix(ctcp.Params, "SEND") { - if pack := irc.ParseDCCSend(ctcp); pack != nil { + if pack := i.client.ParseDCCSend(ctcp); pack != nil { go i.receiveDCCSend(pack, msg) return } @@ -470,7 +470,7 @@ func (i *ircHandler) receiveDCCSend(pack *irc.DCCSend, msg *irc.Message) { } defer file.Close() - irc.DownloadDCC(file, pack, i.dccProgress) + pack.Download(file, i.dccProgress) } else { i.state.setPendingDCC(pack.File, pack) diff --git a/server/server.go b/server/server.go index 3563f96c..b9fc07d1 100644 --- a/server/server.go +++ b/server/server.go @@ -11,7 +11,6 @@ import ( "github.com/gorilla/websocket" "github.com/khlieng/dispatch/config" "github.com/khlieng/dispatch/pkg/https" - "github.com/khlieng/dispatch/pkg/irc" "github.com/khlieng/dispatch/pkg/session" "github.com/khlieng/dispatch/storage" ) @@ -195,7 +194,7 @@ func (d *Dispatch) ServeHTTP(w http.ResponseWriter, r *http.Request) { state.deletePendingDCC(filename) w.Header().Set("Content-Length", strconv.FormatUint(pack.Length, 10)) - irc.DownloadDCC(w, pack, nil) + pack.Download(w, nil) } else { file := storage.Path.DownloadedFile(state.user.Username, filename) http.ServeFile(w, r, file) diff --git a/vendor/golang.org/x/net/internal/socks/client.go b/vendor/golang.org/x/net/internal/socks/client.go new file mode 100644 index 00000000..3d6f516a --- /dev/null +++ b/vendor/golang.org/x/net/internal/socks/client.go @@ -0,0 +1,168 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package socks + +import ( + "context" + "errors" + "io" + "net" + "strconv" + "time" +) + +var ( + noDeadline = time.Time{} + aLongTimeAgo = time.Unix(1, 0) +) + +func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) { + host, port, err := splitHostPort(address) + if err != nil { + return nil, err + } + if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() { + c.SetDeadline(deadline) + defer c.SetDeadline(noDeadline) + } + if ctx != context.Background() { + errCh := make(chan error, 1) + done := make(chan struct{}) + defer func() { + close(done) + if ctxErr == nil { + ctxErr = <-errCh + } + }() + go func() { + select { + case <-ctx.Done(): + c.SetDeadline(aLongTimeAgo) + errCh <- ctx.Err() + case <-done: + errCh <- nil + } + }() + } + + b := make([]byte, 0, 6+len(host)) // the size here is just an estimate + b = append(b, Version5) + if len(d.AuthMethods) == 0 || d.Authenticate == nil { + b = append(b, 1, byte(AuthMethodNotRequired)) + } else { + ams := d.AuthMethods + if len(ams) > 255 { + return nil, errors.New("too many authentication methods") + } + b = append(b, byte(len(ams))) + for _, am := range ams { + b = append(b, byte(am)) + } + } + if _, ctxErr = c.Write(b); ctxErr != nil { + return + } + + if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil { + return + } + if b[0] != Version5 { + return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) + } + am := AuthMethod(b[1]) + if am == AuthMethodNoAcceptableMethods { + return nil, errors.New("no acceptable authentication methods") + } + if d.Authenticate != nil { + if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil { + return + } + } + + b = b[:0] + b = append(b, Version5, byte(d.cmd), 0) + if ip := net.ParseIP(host); ip != nil { + if ip4 := ip.To4(); ip4 != nil { + b = append(b, AddrTypeIPv4) + b = append(b, ip4...) + } else if ip6 := ip.To16(); ip6 != nil { + b = append(b, AddrTypeIPv6) + b = append(b, ip6...) + } else { + return nil, errors.New("unknown address type") + } + } else { + if len(host) > 255 { + return nil, errors.New("FQDN too long") + } + b = append(b, AddrTypeFQDN) + b = append(b, byte(len(host))) + b = append(b, host...) + } + b = append(b, byte(port>>8), byte(port)) + if _, ctxErr = c.Write(b); ctxErr != nil { + return + } + + if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil { + return + } + if b[0] != Version5 { + return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0]))) + } + if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded { + return nil, errors.New("unknown error " + cmdErr.String()) + } + if b[2] != 0 { + return nil, errors.New("non-zero reserved field") + } + l := 2 + var a Addr + switch b[3] { + case AddrTypeIPv4: + l += net.IPv4len + a.IP = make(net.IP, net.IPv4len) + case AddrTypeIPv6: + l += net.IPv6len + a.IP = make(net.IP, net.IPv6len) + case AddrTypeFQDN: + if _, err := io.ReadFull(c, b[:1]); err != nil { + return nil, err + } + l += int(b[0]) + default: + return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3]))) + } + if cap(b) < l { + b = make([]byte, l) + } else { + b = b[:l] + } + if _, ctxErr = io.ReadFull(c, b); ctxErr != nil { + return + } + if a.IP != nil { + copy(a.IP, b) + } else { + a.Name = string(b[:len(b)-2]) + } + a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1]) + return &a, nil +} + +func splitHostPort(address string) (string, int, error) { + host, port, err := net.SplitHostPort(address) + if err != nil { + return "", 0, err + } + portnum, err := strconv.Atoi(port) + if err != nil { + return "", 0, err + } + if 1 > portnum || portnum > 0xffff { + return "", 0, errors.New("port number out of range " + port) + } + return host, portnum, nil +} diff --git a/vendor/golang.org/x/net/internal/socks/socks.go b/vendor/golang.org/x/net/internal/socks/socks.go new file mode 100644 index 00000000..97db2340 --- /dev/null +++ b/vendor/golang.org/x/net/internal/socks/socks.go @@ -0,0 +1,317 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package socks provides a SOCKS version 5 client implementation. +// +// SOCKS protocol version 5 is defined in RFC 1928. +// Username/Password authentication for SOCKS version 5 is defined in +// RFC 1929. +package socks + +import ( + "context" + "errors" + "io" + "net" + "strconv" +) + +// A Command represents a SOCKS command. +type Command int + +func (cmd Command) String() string { + switch cmd { + case CmdConnect: + return "socks connect" + case cmdBind: + return "socks bind" + default: + return "socks " + strconv.Itoa(int(cmd)) + } +} + +// An AuthMethod represents a SOCKS authentication method. +type AuthMethod int + +// A Reply represents a SOCKS command reply code. +type Reply int + +func (code Reply) String() string { + switch code { + case StatusSucceeded: + return "succeeded" + case 0x01: + return "general SOCKS server failure" + case 0x02: + return "connection not allowed by ruleset" + case 0x03: + return "network unreachable" + case 0x04: + return "host unreachable" + case 0x05: + return "connection refused" + case 0x06: + return "TTL expired" + case 0x07: + return "command not supported" + case 0x08: + return "address type not supported" + default: + return "unknown code: " + strconv.Itoa(int(code)) + } +} + +// Wire protocol constants. +const ( + Version5 = 0x05 + + AddrTypeIPv4 = 0x01 + AddrTypeFQDN = 0x03 + AddrTypeIPv6 = 0x04 + + CmdConnect Command = 0x01 // establishes an active-open forward proxy connection + cmdBind Command = 0x02 // establishes a passive-open forward proxy connection + + AuthMethodNotRequired AuthMethod = 0x00 // no authentication required + AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password + AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods + + StatusSucceeded Reply = 0x00 +) + +// An Addr represents a SOCKS-specific address. +// Either Name or IP is used exclusively. +type Addr struct { + Name string // fully-qualified domain name + IP net.IP + Port int +} + +func (a *Addr) Network() string { return "socks" } + +func (a *Addr) String() string { + if a == nil { + return "" + } + port := strconv.Itoa(a.Port) + if a.IP == nil { + return net.JoinHostPort(a.Name, port) + } + return net.JoinHostPort(a.IP.String(), port) +} + +// A Conn represents a forward proxy connection. +type Conn struct { + net.Conn + + boundAddr net.Addr +} + +// BoundAddr returns the address assigned by the proxy server for +// connecting to the command target address from the proxy server. +func (c *Conn) BoundAddr() net.Addr { + if c == nil { + return nil + } + return c.boundAddr +} + +// A Dialer holds SOCKS-specific options. +type Dialer struct { + cmd Command // either CmdConnect or cmdBind + proxyNetwork string // network between a proxy server and a client + proxyAddress string // proxy server address + + // ProxyDial specifies the optional dial function for + // establishing the transport connection. + ProxyDial func(context.Context, string, string) (net.Conn, error) + + // AuthMethods specifies the list of request authentication + // methods. + // If empty, SOCKS client requests only AuthMethodNotRequired. + AuthMethods []AuthMethod + + // Authenticate specifies the optional authentication + // function. It must be non-nil when AuthMethods is not empty. + // It must return an error when the authentication is failed. + Authenticate func(context.Context, io.ReadWriter, AuthMethod) error +} + +// DialContext connects to the provided address on the provided +// network. +// +// The returned error value may be a net.OpError. When the Op field of +// net.OpError contains "socks", the Source field contains a proxy +// server address and the Addr field contains a command target +// address. +// +// See func Dial of the net package of standard library for a +// description of the network and address parameters. +func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { + if err := d.validateTarget(network, address); err != nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} + } + if ctx == nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")} + } + var err error + var c net.Conn + if d.ProxyDial != nil { + c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress) + } else { + var dd net.Dialer + c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress) + } + if err != nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} + } + a, err := d.connect(ctx, c, address) + if err != nil { + c.Close() + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} + } + return &Conn{Conn: c, boundAddr: a}, nil +} + +// DialWithConn initiates a connection from SOCKS server to the target +// network and address using the connection c that is already +// connected to the SOCKS server. +// +// It returns the connection's local address assigned by the SOCKS +// server. +func (d *Dialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) { + if err := d.validateTarget(network, address); err != nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} + } + if ctx == nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")} + } + a, err := d.connect(ctx, c, address) + if err != nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} + } + return a, nil +} + +// Dial connects to the provided address on the provided network. +// +// Unlike DialContext, it returns a raw transport connection instead +// of a forward proxy connection. +// +// Deprecated: Use DialContext or DialWithConn instead. +func (d *Dialer) Dial(network, address string) (net.Conn, error) { + if err := d.validateTarget(network, address); err != nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} + } + var err error + var c net.Conn + if d.ProxyDial != nil { + c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress) + } else { + c, err = net.Dial(d.proxyNetwork, d.proxyAddress) + } + if err != nil { + proxy, dst, _ := d.pathAddrs(address) + return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err} + } + if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil { + c.Close() + return nil, err + } + return c, nil +} + +func (d *Dialer) validateTarget(network, address string) error { + switch network { + case "tcp", "tcp6", "tcp4": + default: + return errors.New("network not implemented") + } + switch d.cmd { + case CmdConnect, cmdBind: + default: + return errors.New("command not implemented") + } + return nil +} + +func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) { + for i, s := range []string{d.proxyAddress, address} { + host, port, err := splitHostPort(s) + if err != nil { + return nil, nil, err + } + a := &Addr{Port: port} + a.IP = net.ParseIP(host) + if a.IP == nil { + a.Name = host + } + if i == 0 { + proxy = a + } else { + dst = a + } + } + return +} + +// NewDialer returns a new Dialer that dials through the provided +// proxy server's network and address. +func NewDialer(network, address string) *Dialer { + return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect} +} + +const ( + authUsernamePasswordVersion = 0x01 + authStatusSucceeded = 0x00 +) + +// UsernamePassword are the credentials for the username/password +// authentication method. +type UsernamePassword struct { + Username string + Password string +} + +// Authenticate authenticates a pair of username and password with the +// proxy server. +func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error { + switch auth { + case AuthMethodNotRequired: + return nil + case AuthMethodUsernamePassword: + if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 { + return errors.New("invalid username/password") + } + b := []byte{authUsernamePasswordVersion} + b = append(b, byte(len(up.Username))) + b = append(b, up.Username...) + b = append(b, byte(len(up.Password))) + b = append(b, up.Password...) + // TODO(mikio): handle IO deadlines and cancelation if + // necessary + if _, err := rw.Write(b); err != nil { + return err + } + if _, err := io.ReadFull(rw, b[:2]); err != nil { + return err + } + if b[0] != authUsernamePasswordVersion { + return errors.New("invalid username/password version") + } + if b[1] != authStatusSucceeded { + return errors.New("username/password authentication failed") + } + return nil + } + return errors.New("unsupported authentication method " + strconv.Itoa(int(auth))) +} diff --git a/vendor/golang.org/x/net/proxy/dial.go b/vendor/golang.org/x/net/proxy/dial.go new file mode 100644 index 00000000..811c2e4e --- /dev/null +++ b/vendor/golang.org/x/net/proxy/dial.go @@ -0,0 +1,54 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proxy + +import ( + "context" + "net" +) + +// A ContextDialer dials using a context. +type ContextDialer interface { + DialContext(ctx context.Context, network, address string) (net.Conn, error) +} + +// Dial works like DialContext on net.Dialer but using a dialer returned by FromEnvironment. +// +// The passed ctx is only used for returning the Conn, not the lifetime of the Conn. +// +// Custom dialers (registered via RegisterDialerType) that do not implement ContextDialer +// can leak a goroutine for as long as it takes the underlying Dialer implementation to timeout. +// +// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. +func Dial(ctx context.Context, network, address string) (net.Conn, error) { + d := FromEnvironment() + if xd, ok := d.(ContextDialer); ok { + return xd.DialContext(ctx, network, address) + } + return dialContext(ctx, d, network, address) +} + +// WARNING: this can leak a goroutine for as long as the underlying Dialer implementation takes to timeout +// A Conn returned from a successful Dial after the context has been cancelled will be immediately closed. +func dialContext(ctx context.Context, d Dialer, network, address string) (net.Conn, error) { + var ( + conn net.Conn + done = make(chan struct{}, 1) + err error + ) + go func() { + conn, err = d.Dial(network, address) + close(done) + if conn != nil && ctx.Err() != nil { + conn.Close() + } + }() + select { + case <-ctx.Done(): + err = ctx.Err() + case <-done: + } + return conn, err +} diff --git a/vendor/golang.org/x/net/proxy/direct.go b/vendor/golang.org/x/net/proxy/direct.go new file mode 100644 index 00000000..3d66bdef --- /dev/null +++ b/vendor/golang.org/x/net/proxy/direct.go @@ -0,0 +1,31 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proxy + +import ( + "context" + "net" +) + +type direct struct{} + +// Direct implements Dialer by making network connections directly using net.Dial or net.DialContext. +var Direct = direct{} + +var ( + _ Dialer = Direct + _ ContextDialer = Direct +) + +// Dial directly invokes net.Dial with the supplied parameters. +func (direct) Dial(network, addr string) (net.Conn, error) { + return net.Dial(network, addr) +} + +// DialContext instantiates a net.Dialer and invokes its DialContext receiver with the supplied parameters. +func (direct) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { + var d net.Dialer + return d.DialContext(ctx, network, addr) +} diff --git a/vendor/golang.org/x/net/proxy/per_host.go b/vendor/golang.org/x/net/proxy/per_host.go new file mode 100644 index 00000000..573fe79e --- /dev/null +++ b/vendor/golang.org/x/net/proxy/per_host.go @@ -0,0 +1,155 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proxy + +import ( + "context" + "net" + "strings" +) + +// A PerHost directs connections to a default Dialer unless the host name +// requested matches one of a number of exceptions. +type PerHost struct { + def, bypass Dialer + + bypassNetworks []*net.IPNet + bypassIPs []net.IP + bypassZones []string + bypassHosts []string +} + +// NewPerHost returns a PerHost Dialer that directs connections to either +// defaultDialer or bypass, depending on whether the connection matches one of +// the configured rules. +func NewPerHost(defaultDialer, bypass Dialer) *PerHost { + return &PerHost{ + def: defaultDialer, + bypass: bypass, + } +} + +// Dial connects to the address addr on the given network through either +// defaultDialer or bypass. +func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) { + host, _, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + + return p.dialerForRequest(host).Dial(network, addr) +} + +// DialContext connects to the address addr on the given network through either +// defaultDialer or bypass. +func (p *PerHost) DialContext(ctx context.Context, network, addr string) (c net.Conn, err error) { + host, _, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + d := p.dialerForRequest(host) + if x, ok := d.(ContextDialer); ok { + return x.DialContext(ctx, network, addr) + } + return dialContext(ctx, d, network, addr) +} + +func (p *PerHost) dialerForRequest(host string) Dialer { + if ip := net.ParseIP(host); ip != nil { + for _, net := range p.bypassNetworks { + if net.Contains(ip) { + return p.bypass + } + } + for _, bypassIP := range p.bypassIPs { + if bypassIP.Equal(ip) { + return p.bypass + } + } + return p.def + } + + for _, zone := range p.bypassZones { + if strings.HasSuffix(host, zone) { + return p.bypass + } + if host == zone[1:] { + // For a zone ".example.com", we match "example.com" + // too. + return p.bypass + } + } + for _, bypassHost := range p.bypassHosts { + if bypassHost == host { + return p.bypass + } + } + return p.def +} + +// AddFromString parses a string that contains comma-separated values +// specifying hosts that should use the bypass proxy. Each value is either an +// IP address, a CIDR range, a zone (*.example.com) or a host name +// (localhost). A best effort is made to parse the string and errors are +// ignored. +func (p *PerHost) AddFromString(s string) { + hosts := strings.Split(s, ",") + for _, host := range hosts { + host = strings.TrimSpace(host) + if len(host) == 0 { + continue + } + if strings.Contains(host, "/") { + // We assume that it's a CIDR address like 127.0.0.0/8 + if _, net, err := net.ParseCIDR(host); err == nil { + p.AddNetwork(net) + } + continue + } + if ip := net.ParseIP(host); ip != nil { + p.AddIP(ip) + continue + } + if strings.HasPrefix(host, "*.") { + p.AddZone(host[1:]) + continue + } + p.AddHost(host) + } +} + +// AddIP specifies an IP address that will use the bypass proxy. Note that +// this will only take effect if a literal IP address is dialed. A connection +// to a named host will never match an IP. +func (p *PerHost) AddIP(ip net.IP) { + p.bypassIPs = append(p.bypassIPs, ip) +} + +// AddNetwork specifies an IP range that will use the bypass proxy. Note that +// this will only take effect if a literal IP address is dialed. A connection +// to a named host will never match. +func (p *PerHost) AddNetwork(net *net.IPNet) { + p.bypassNetworks = append(p.bypassNetworks, net) +} + +// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of +// "example.com" matches "example.com" and all of its subdomains. +func (p *PerHost) AddZone(zone string) { + if strings.HasSuffix(zone, ".") { + zone = zone[:len(zone)-1] + } + if !strings.HasPrefix(zone, ".") { + zone = "." + zone + } + p.bypassZones = append(p.bypassZones, zone) +} + +// AddHost specifies a host name that will use the bypass proxy. +func (p *PerHost) AddHost(host string) { + if strings.HasSuffix(host, ".") { + host = host[:len(host)-1] + } + p.bypassHosts = append(p.bypassHosts, host) +} diff --git a/vendor/golang.org/x/net/proxy/proxy.go b/vendor/golang.org/x/net/proxy/proxy.go new file mode 100644 index 00000000..9ff4b9a7 --- /dev/null +++ b/vendor/golang.org/x/net/proxy/proxy.go @@ -0,0 +1,149 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package proxy provides support for a variety of protocols to proxy network +// data. +package proxy // import "golang.org/x/net/proxy" + +import ( + "errors" + "net" + "net/url" + "os" + "sync" +) + +// A Dialer is a means to establish a connection. +// Custom dialers should also implement ContextDialer. +type Dialer interface { + // Dial connects to the given address via the proxy. + Dial(network, addr string) (c net.Conn, err error) +} + +// Auth contains authentication parameters that specific Dialers may require. +type Auth struct { + User, Password string +} + +// FromEnvironment returns the dialer specified by the proxy-related +// variables in the environment and makes underlying connections +// directly. +func FromEnvironment() Dialer { + return FromEnvironmentUsing(Direct) +} + +// FromEnvironmentUsing returns the dialer specify by the proxy-related +// variables in the environment and makes underlying connections +// using the provided forwarding Dialer (for instance, a *net.Dialer +// with desired configuration). +func FromEnvironmentUsing(forward Dialer) Dialer { + allProxy := allProxyEnv.Get() + if len(allProxy) == 0 { + return forward + } + + proxyURL, err := url.Parse(allProxy) + if err != nil { + return forward + } + proxy, err := FromURL(proxyURL, forward) + if err != nil { + return forward + } + + noProxy := noProxyEnv.Get() + if len(noProxy) == 0 { + return proxy + } + + perHost := NewPerHost(proxy, forward) + perHost.AddFromString(noProxy) + return perHost +} + +// proxySchemes is a map from URL schemes to a function that creates a Dialer +// from a URL with such a scheme. +var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error) + +// RegisterDialerType takes a URL scheme and a function to generate Dialers from +// a URL with that scheme and a forwarding Dialer. Registered schemes are used +// by FromURL. +func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) { + if proxySchemes == nil { + proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error)) + } + proxySchemes[scheme] = f +} + +// FromURL returns a Dialer given a URL specification and an underlying +// Dialer for it to make network requests. +func FromURL(u *url.URL, forward Dialer) (Dialer, error) { + var auth *Auth + if u.User != nil { + auth = new(Auth) + auth.User = u.User.Username() + if p, ok := u.User.Password(); ok { + auth.Password = p + } + } + + switch u.Scheme { + case "socks5", "socks5h": + addr := u.Hostname() + port := u.Port() + if port == "" { + port = "1080" + } + return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward) + } + + // If the scheme doesn't match any of the built-in schemes, see if it + // was registered by another package. + if proxySchemes != nil { + if f, ok := proxySchemes[u.Scheme]; ok { + return f(u, forward) + } + } + + return nil, errors.New("proxy: unknown scheme: " + u.Scheme) +} + +var ( + allProxyEnv = &envOnce{ + names: []string{"ALL_PROXY", "all_proxy"}, + } + noProxyEnv = &envOnce{ + names: []string{"NO_PROXY", "no_proxy"}, + } +) + +// envOnce looks up an environment variable (optionally by multiple +// names) once. It mitigates expensive lookups on some platforms +// (e.g. Windows). +// (Borrowed from net/http/transport.go) +type envOnce struct { + names []string + once sync.Once + val string +} + +func (e *envOnce) Get() string { + e.once.Do(e.init) + return e.val +} + +func (e *envOnce) init() { + for _, n := range e.names { + e.val = os.Getenv(n) + if e.val != "" { + return + } + } +} + +// reset is used by tests +func (e *envOnce) reset() { + e.once = sync.Once{} + e.val = "" +} diff --git a/vendor/golang.org/x/net/proxy/socks5.go b/vendor/golang.org/x/net/proxy/socks5.go new file mode 100644 index 00000000..c91651f9 --- /dev/null +++ b/vendor/golang.org/x/net/proxy/socks5.go @@ -0,0 +1,42 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package proxy + +import ( + "context" + "net" + + "golang.org/x/net/internal/socks" +) + +// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given +// address with an optional username and password. +// See RFC 1928 and RFC 1929. +func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) { + d := socks.NewDialer(network, address) + if forward != nil { + if f, ok := forward.(ContextDialer); ok { + d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { + return f.DialContext(ctx, network, address) + } + } else { + d.ProxyDial = func(ctx context.Context, network string, address string) (net.Conn, error) { + return dialContext(ctx, forward, network, address) + } + } + } + if auth != nil { + up := socks.UsernamePassword{ + Username: auth.User, + Password: auth.Password, + } + d.AuthMethods = []socks.AuthMethod{ + socks.AuthMethodNotRequired, + socks.AuthMethodUsernamePassword, + } + d.Authenticate = up.Authenticate + } + return d, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 31b97e72..3ff3fd5f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -243,8 +243,10 @@ golang.org/x/net/html/atom golang.org/x/net/idna golang.org/x/net/internal/iana golang.org/x/net/internal/socket +golang.org/x/net/internal/socks golang.org/x/net/ipv4 golang.org/x/net/ipv6 +golang.org/x/net/proxy # golang.org/x/sys v0.0.0-20200610111108-226ff32320da ## explicit golang.org/x/sys/internal/unsafeheader