socks_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. * Copyright (c) 2015, Yawning Angel <yawning at schwanenlied dot me>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  19. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. package socks5
  28. import (
  29. "bufio"
  30. "bytes"
  31. "encoding/hex"
  32. "io"
  33. "net"
  34. "testing"
  35. )
  36. func tcpAddrsEqual(a, b *net.TCPAddr) bool {
  37. return a.IP.Equal(b.IP) && a.Port == b.Port
  38. }
  39. // testReadWriter is a bytes.Buffer backed io.ReadWriter used for testing. The
  40. // Read and Write routines are to be used by the component being tested. Data
  41. // can be written to and read back via the writeHex and readHex routines.
  42. type testReadWriter struct {
  43. readBuf bytes.Buffer
  44. writeBuf bytes.Buffer
  45. }
  46. func (c *testReadWriter) Read(buf []byte) (n int, err error) {
  47. return c.readBuf.Read(buf)
  48. }
  49. func (c *testReadWriter) Write(buf []byte) (n int, err error) {
  50. return c.writeBuf.Write(buf)
  51. }
  52. func (c *testReadWriter) writeHex(str string) {
  53. var buf []byte
  54. var err error
  55. if buf, err = hex.DecodeString(str); err != nil {
  56. panic("writeHex: malformed hex: " + err.Error())
  57. }
  58. if _, err = c.readBuf.Write(buf); err != nil {
  59. panic("writeHex: buffered write failed: " + err.Error())
  60. }
  61. }
  62. func (c *testReadWriter) readHex() string {
  63. return hex.EncodeToString(c.writeBuf.Bytes())
  64. }
  65. func (c *testReadWriter) toBufio() *bufio.ReadWriter {
  66. return bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c))
  67. }
  68. func (c *testReadWriter) toRequest() *Request {
  69. req := new(Request)
  70. req.rw = c.toBufio()
  71. return req
  72. }
  73. func (c *testReadWriter) reset(req *Request) {
  74. c.readBuf.Reset()
  75. c.writeBuf.Reset()
  76. req.rw = c.toBufio()
  77. }
  78. // TestAuthInvalidVersion tests auth negotiation with an invalid version.
  79. func TestAuthInvalidVersion(t *testing.T) {
  80. c := new(testReadWriter)
  81. req := c.toRequest()
  82. // VER = 03, NMETHODS = 01, METHODS = [00]
  83. c.writeHex("030100")
  84. if _, err := req.negotiateAuth(); err == nil {
  85. t.Error("negotiateAuth(InvalidVersion) succeded")
  86. }
  87. }
  88. // TestAuthInvalidNMethods tests auth negotiaton with no methods.
  89. func TestAuthInvalidNMethods(t *testing.T) {
  90. c := new(testReadWriter)
  91. req := c.toRequest()
  92. var err error
  93. var method byte
  94. // VER = 05, NMETHODS = 00
  95. c.writeHex("0500")
  96. if method, err = req.negotiateAuth(); err != nil {
  97. t.Error("negotiateAuth(No Methods) failed:", err)
  98. }
  99. if method != authNoAcceptableMethods {
  100. t.Error("negotiateAuth(No Methods) picked unexpected method:", method)
  101. }
  102. if msg := c.readHex(); msg != "05ff" {
  103. t.Error("negotiateAuth(No Methods) invalid response:", msg)
  104. }
  105. }
  106. // TestAuthNoneRequired tests auth negotiaton with NO AUTHENTICATION REQUIRED.
  107. func TestAuthNoneRequired(t *testing.T) {
  108. c := new(testReadWriter)
  109. req := c.toRequest()
  110. var err error
  111. var method byte
  112. // VER = 05, NMETHODS = 01, METHODS = [00]
  113. c.writeHex("050100")
  114. if method, err = req.negotiateAuth(); err != nil {
  115. t.Error("negotiateAuth(None) failed:", err)
  116. }
  117. if method != authNoneRequired {
  118. t.Error("negotiateAuth(None) unexpected method:", method)
  119. }
  120. if msg := c.readHex(); msg != "0500" {
  121. t.Error("negotiateAuth(None) invalid response:", msg)
  122. }
  123. }
  124. // TestAuthUsernamePassword tests auth negotiation with USERNAME/PASSWORD.
  125. func TestAuthUsernamePassword(t *testing.T) {
  126. c := new(testReadWriter)
  127. req := c.toRequest()
  128. var err error
  129. var method byte
  130. // VER = 05, NMETHODS = 01, METHODS = [02]
  131. c.writeHex("050102")
  132. if method, err = req.negotiateAuth(); err != nil {
  133. t.Error("negotiateAuth(UsernamePassword) failed:", err)
  134. }
  135. if method != authUsernamePassword {
  136. t.Error("negotiateAuth(UsernamePassword) unexpected method:", method)
  137. }
  138. if msg := c.readHex(); msg != "0502" {
  139. t.Error("negotiateAuth(UsernamePassword) invalid response:", msg)
  140. }
  141. }
  142. // TestAuthBoth tests auth negotiation containing both NO AUTHENTICATION
  143. // REQUIRED and USERNAME/PASSWORD.
  144. func TestAuthBoth(t *testing.T) {
  145. c := new(testReadWriter)
  146. req := c.toRequest()
  147. var err error
  148. var method byte
  149. // VER = 05, NMETHODS = 02, METHODS = [00, 02]
  150. c.writeHex("05020002")
  151. if method, err = req.negotiateAuth(); err != nil {
  152. t.Error("negotiateAuth(Both) failed:", err)
  153. }
  154. if method != authUsernamePassword {
  155. t.Error("negotiateAuth(Both) unexpected method:", method)
  156. }
  157. if msg := c.readHex(); msg != "0502" {
  158. t.Error("negotiateAuth(Both) invalid response:", msg)
  159. }
  160. }
  161. // TestAuthUnsupported tests auth negotiation with a unsupported method.
  162. func TestAuthUnsupported(t *testing.T) {
  163. c := new(testReadWriter)
  164. req := c.toRequest()
  165. var err error
  166. var method byte
  167. // VER = 05, NMETHODS = 01, METHODS = [01] (GSSAPI)
  168. c.writeHex("050101")
  169. if method, err = req.negotiateAuth(); err != nil {
  170. t.Error("negotiateAuth(Unknown) failed:", err)
  171. }
  172. if method != authNoAcceptableMethods {
  173. t.Error("negotiateAuth(Unknown) picked unexpected method:", method)
  174. }
  175. if msg := c.readHex(); msg != "05ff" {
  176. t.Error("negotiateAuth(Unknown) invalid response:", msg)
  177. }
  178. }
  179. // TestAuthUnsupported2 tests auth negotiation with supported and unsupported
  180. // methods.
  181. func TestAuthUnsupported2(t *testing.T) {
  182. c := new(testReadWriter)
  183. req := c.toRequest()
  184. var err error
  185. var method byte
  186. // VER = 05, NMETHODS = 03, METHODS = [00,01,02]
  187. c.writeHex("0503000102")
  188. if method, err = req.negotiateAuth(); err != nil {
  189. t.Error("negotiateAuth(Unknown2) failed:", err)
  190. }
  191. if method != authUsernamePassword {
  192. t.Error("negotiateAuth(Unknown2) picked unexpected method:", method)
  193. }
  194. if msg := c.readHex(); msg != "0502" {
  195. t.Error("negotiateAuth(Unknown2) invalid response:", msg)
  196. }
  197. }
  198. // TestRFC1929InvalidVersion tests RFC1929 auth with an invalid version.
  199. func TestRFC1929InvalidVersion(t *testing.T) {
  200. c := new(testReadWriter)
  201. req := c.toRequest()
  202. // VER = 03, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
  203. c.writeHex("03054142434445056162636465")
  204. if err := req.authenticate(authUsernamePassword); err == nil {
  205. t.Error("authenticate(InvalidVersion) succeded")
  206. }
  207. if msg := c.readHex(); msg != "0101" {
  208. t.Error("authenticate(InvalidVersion) invalid response:", msg)
  209. }
  210. }
  211. // TestRFC1929InvalidUlen tests RFC1929 auth with an invalid ULEN.
  212. func TestRFC1929InvalidUlen(t *testing.T) {
  213. c := new(testReadWriter)
  214. req := c.toRequest()
  215. // VER = 01, ULEN = 0, UNAME = "", PLEN = 5, PASSWD = "abcde"
  216. c.writeHex("0100056162636465")
  217. if err := req.authenticate(authUsernamePassword); err == nil {
  218. t.Error("authenticate(InvalidUlen) succeded")
  219. }
  220. if msg := c.readHex(); msg != "0101" {
  221. t.Error("authenticate(InvalidUlen) invalid response:", msg)
  222. }
  223. }
  224. // TestRFC1929InvalidPlen tests RFC1929 auth with an invalid PLEN.
  225. func TestRFC1929InvalidPlen(t *testing.T) {
  226. c := new(testReadWriter)
  227. req := c.toRequest()
  228. // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 0, PASSWD = ""
  229. c.writeHex("0105414243444500")
  230. if err := req.authenticate(authUsernamePassword); err == nil {
  231. t.Error("authenticate(InvalidPlen) succeded")
  232. }
  233. if msg := c.readHex(); msg != "0101" {
  234. t.Error("authenticate(InvalidPlen) invalid response:", msg)
  235. }
  236. }
  237. // TestRFC1929InvalidArgs tests RFC1929 auth with invalid pt args.
  238. func TestRFC1929InvalidPTArgs(t *testing.T) {
  239. c := new(testReadWriter)
  240. req := c.toRequest()
  241. // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
  242. c.writeHex("01054142434445056162636465")
  243. if err := req.authenticate(authUsernamePassword); err == nil {
  244. t.Error("authenticate(InvalidArgs) succeded")
  245. }
  246. if msg := c.readHex(); msg != "0101" {
  247. t.Error("authenticate(InvalidArgs) invalid response:", msg)
  248. }
  249. }
  250. // TestRFC1929Success tests RFC1929 auth with valid pt args.
  251. func TestRFC1929Success(t *testing.T) {
  252. c := new(testReadWriter)
  253. req := c.toRequest()
  254. // VER = 01, ULEN = 9, UNAME = "key=value", PLEN = 1, PASSWD = "\0"
  255. c.writeHex("01096b65793d76616c75650100")
  256. if err := req.authenticate(authUsernamePassword); err != nil {
  257. t.Error("authenticate(Success) failed:", err)
  258. }
  259. if msg := c.readHex(); msg != "0100" {
  260. t.Error("authenticate(Success) invalid response:", msg)
  261. }
  262. v, ok := req.Args.Get("key")
  263. if v != "value" || !ok {
  264. t.Error("RFC1929 k,v parse failure:", v)
  265. }
  266. }
  267. // TestRequestInvalidHdr tests SOCKS5 requests with invalid VER/CMD/RSV/ATYPE
  268. func TestRequestInvalidHdr(t *testing.T) {
  269. c := new(testReadWriter)
  270. req := c.toRequest()
  271. // VER = 03, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  272. c.writeHex("030100017f000001235a")
  273. if err := req.readCommand(); err == nil {
  274. t.Error("readCommand(InvalidVer) succeded")
  275. }
  276. if msg := c.readHex(); msg != "05010001000000000000" {
  277. t.Error("readCommand(InvalidVer) invalid response:", msg)
  278. }
  279. c.reset(req)
  280. // VER = 05, CMD = 05, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  281. c.writeHex("050500017f000001235a")
  282. if err := req.readCommand(); err == nil {
  283. t.Error("readCommand(InvalidCmd) succeded")
  284. }
  285. if msg := c.readHex(); msg != "05070001000000000000" {
  286. t.Error("readCommand(InvalidCmd) invalid response:", msg)
  287. }
  288. c.reset(req)
  289. // VER = 05, CMD = 01, RSV = 30, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  290. c.writeHex("050130017f000001235a")
  291. if err := req.readCommand(); err == nil {
  292. t.Error("readCommand(InvalidRsv) succeded")
  293. }
  294. if msg := c.readHex(); msg != "05010001000000000000" {
  295. t.Error("readCommand(InvalidRsv) invalid response:", msg)
  296. }
  297. c.reset(req)
  298. // VER = 05, CMD = 01, RSV = 01, ATYPE = 05, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  299. c.writeHex("050100057f000001235a")
  300. if err := req.readCommand(); err == nil {
  301. t.Error("readCommand(InvalidAtype) succeded")
  302. }
  303. if msg := c.readHex(); msg != "05080001000000000000" {
  304. t.Error("readCommand(InvalidAtype) invalid response:", msg)
  305. }
  306. c.reset(req)
  307. }
  308. // TestRequestIPv4 tests IPv4 SOCKS5 requests.
  309. func TestRequestIPv4(t *testing.T) {
  310. c := new(testReadWriter)
  311. req := c.toRequest()
  312. // VER = 05, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  313. c.writeHex("050100017f000001235a")
  314. if err := req.readCommand(); err != nil {
  315. t.Error("readCommand(IPv4) failed:", err)
  316. }
  317. addr, err := net.ResolveTCPAddr("tcp", req.Target)
  318. if err != nil {
  319. t.Error("net.ResolveTCPAddr failed:", err)
  320. }
  321. if !tcpAddrsEqual(addr, &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 9050}) {
  322. t.Error("Unexpected target:", addr)
  323. }
  324. }
  325. // TestRequestIPv6 tests IPv4 SOCKS5 requests.
  326. func TestRequestIPv6(t *testing.T) {
  327. c := new(testReadWriter)
  328. req := c.toRequest()
  329. // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = 0102:0304:0506:0708:090a:0b0c:0d0e:0f10, DST.PORT = 9050
  330. c.writeHex("050100040102030405060708090a0b0c0d0e0f10235a")
  331. if err := req.readCommand(); err != nil {
  332. t.Error("readCommand(IPv6) failed:", err)
  333. }
  334. addr, err := net.ResolveTCPAddr("tcp", req.Target)
  335. if err != nil {
  336. t.Error("net.ResolveTCPAddr failed:", err)
  337. }
  338. if !tcpAddrsEqual(addr, &net.TCPAddr{IP: net.ParseIP("0102:0304:0506:0708:090a:0b0c:0d0e:0f10"), Port: 9050}) {
  339. t.Error("Unexpected target:", addr)
  340. }
  341. }
  342. // TestRequestFQDN tests FQDN (DOMAINNAME) SOCKS5 requests.
  343. func TestRequestFQDN(t *testing.T) {
  344. c := new(testReadWriter)
  345. req := c.toRequest()
  346. // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = example.com, DST.PORT = 9050
  347. c.writeHex("050100030b6578616d706c652e636f6d235a")
  348. if err := req.readCommand(); err != nil {
  349. t.Error("readCommand(FQDN) failed:", err)
  350. }
  351. if req.Target != "example.com:9050" {
  352. t.Error("Unexpected target:", req.Target)
  353. }
  354. }
  355. // TestResponseNil tests nil address SOCKS5 responses.
  356. func TestResponseNil(t *testing.T) {
  357. c := new(testReadWriter)
  358. req := c.toRequest()
  359. if err := req.Reply(ReplySucceeded); err != nil {
  360. t.Error("Reply(ReplySucceeded) failed:", err)
  361. }
  362. if msg := c.readHex(); msg != "05000001000000000000" {
  363. t.Error("Reply(ReplySucceeded) invalid response:", msg)
  364. }
  365. }
  366. var _ io.ReadWriter = (*testReadWriter)(nil)