socks_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Copyright (c) 2015, Yawning Angel <yawning at torproject dot org>
  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) (n int, err error) {
  53. var buf []byte
  54. if buf, err = hex.DecodeString(str); err != nil {
  55. return
  56. }
  57. return c.readBuf.Write(buf)
  58. }
  59. func (c *testReadWriter) readHex() string {
  60. return hex.EncodeToString(c.writeBuf.Bytes())
  61. }
  62. func (c *testReadWriter) toBufio() *bufio.ReadWriter {
  63. return bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c))
  64. }
  65. func (c *testReadWriter) toRequest() *Request {
  66. req := new(Request)
  67. req.rw = c.toBufio()
  68. return req
  69. }
  70. func (c *testReadWriter) reset(req *Request) {
  71. c.readBuf.Reset()
  72. c.writeBuf.Reset()
  73. req.rw = c.toBufio()
  74. }
  75. // TestAuthInvalidVersion tests auth negotiation with an invalid version.
  76. func TestAuthInvalidVersion(t *testing.T) {
  77. c := new(testReadWriter)
  78. req := c.toRequest()
  79. // VER = 03, NMETHODS = 01, METHODS = [00]
  80. c.writeHex("030100")
  81. if _, err := req.negotiateAuth(); err == nil {
  82. t.Error("negotiateAuth(InvalidVersion) succeded")
  83. }
  84. }
  85. // TestAuthInvalidNMethods tests auth negotiaton with no methods.
  86. func TestAuthInvalidNMethods(t *testing.T) {
  87. c := new(testReadWriter)
  88. req := c.toRequest()
  89. var err error
  90. var method byte
  91. // VER = 05, NMETHODS = 00
  92. c.writeHex("0500")
  93. if method, err = req.negotiateAuth(); err != nil {
  94. t.Error("negotiateAuth(No Methods) failed:", err)
  95. }
  96. if method != authNoAcceptableMethods {
  97. t.Error("negotiateAuth(No Methods) picked unexpected method:", method)
  98. }
  99. if msg := c.readHex(); msg != "05ff" {
  100. t.Error("negotiateAuth(No Methods) invalid response:", msg)
  101. }
  102. }
  103. // TestAuthNoneRequired tests auth negotiaton with NO AUTHENTICATION REQUIRED.
  104. func TestAuthNoneRequired(t *testing.T) {
  105. c := new(testReadWriter)
  106. req := c.toRequest()
  107. var err error
  108. var method byte
  109. // VER = 05, NMETHODS = 01, METHODS = [00]
  110. c.writeHex("050100")
  111. if method, err = req.negotiateAuth(); err != nil {
  112. t.Error("negotiateAuth(None) failed:", err)
  113. }
  114. if method != authNoneRequired {
  115. t.Error("negotiateAuth(None) unexpected method:", method)
  116. }
  117. if msg := c.readHex(); msg != "0500" {
  118. t.Error("negotiateAuth(None) invalid response:", msg)
  119. }
  120. }
  121. // TestAuthUsernamePassword tests auth negotiation with USERNAME/PASSWORD.
  122. func TestAuthUsernamePassword(t *testing.T) {
  123. c := new(testReadWriter)
  124. req := c.toRequest()
  125. var err error
  126. var method byte
  127. // VER = 05, NMETHODS = 01, METHODS = [02]
  128. c.writeHex("050102")
  129. if method, err = req.negotiateAuth(); err != nil {
  130. t.Error("negotiateAuth(UsernamePassword) failed:", err)
  131. }
  132. if method != authUsernamePassword {
  133. t.Error("negotiateAuth(UsernamePassword) unexpected method:", method)
  134. }
  135. if msg := c.readHex(); msg != "0502" {
  136. t.Error("negotiateAuth(UsernamePassword) invalid response:", msg)
  137. }
  138. }
  139. // TestAuthBoth tests auth negotiation containing both NO AUTHENTICATION
  140. // REQUIRED and USERNAME/PASSWORD.
  141. func TestAuthBoth(t *testing.T) {
  142. c := new(testReadWriter)
  143. req := c.toRequest()
  144. var err error
  145. var method byte
  146. // VER = 05, NMETHODS = 02, METHODS = [00, 02]
  147. c.writeHex("05020002")
  148. if method, err = req.negotiateAuth(); err != nil {
  149. t.Error("negotiateAuth(Both) failed:", err)
  150. }
  151. if method != authUsernamePassword {
  152. t.Error("negotiateAuth(Both) unexpected method:", method)
  153. }
  154. if msg := c.readHex(); msg != "0502" {
  155. t.Error("negotiateAuth(Both) invalid response:", msg)
  156. }
  157. }
  158. // TestAuthUnsupported tests auth negotiation with a unsupported method.
  159. func TestAuthUnsupported(t *testing.T) {
  160. c := new(testReadWriter)
  161. req := c.toRequest()
  162. var err error
  163. var method byte
  164. // VER = 05, NMETHODS = 01, METHODS = [01] (GSSAPI)
  165. c.writeHex("050101")
  166. if method, err = req.negotiateAuth(); err != nil {
  167. t.Error("negotiateAuth(Unknown) failed:", err)
  168. }
  169. if method != authNoAcceptableMethods {
  170. t.Error("negotiateAuth(Unknown) picked unexpected method:", method)
  171. }
  172. if msg := c.readHex(); msg != "05ff" {
  173. t.Error("negotiateAuth(Unknown) invalid response:", msg)
  174. }
  175. }
  176. // TestAuthUnsupported2 tests auth negotiation with supported and unsupported
  177. // methods.
  178. func TestAuthUnsupported2(t *testing.T) {
  179. c := new(testReadWriter)
  180. req := c.toRequest()
  181. var err error
  182. var method byte
  183. // VER = 05, NMETHODS = 03, METHODS = [00,01,02]
  184. c.writeHex("0503000102")
  185. if method, err = req.negotiateAuth(); err != nil {
  186. t.Error("negotiateAuth(Unknown2) failed:", err)
  187. }
  188. if method != authUsernamePassword {
  189. t.Error("negotiateAuth(Unknown2) picked unexpected method:", method)
  190. }
  191. if msg := c.readHex(); msg != "0502" {
  192. t.Error("negotiateAuth(Unknown2) invalid response:", msg)
  193. }
  194. }
  195. // TestRFC1929InvalidVersion tests RFC1929 auth with an invalid version.
  196. func TestRFC1929InvalidVersion(t *testing.T) {
  197. c := new(testReadWriter)
  198. req := c.toRequest()
  199. // VER = 03, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
  200. c.writeHex("03054142434445056162636465")
  201. if err := req.authenticate(authUsernamePassword); err == nil {
  202. t.Error("authenticate(InvalidVersion) succeded")
  203. }
  204. if msg := c.readHex(); msg != "0101" {
  205. t.Error("authenticate(InvalidVersion) invalid response:", msg)
  206. }
  207. }
  208. // TestRFC1929InvalidUlen tests RFC1929 auth with an invalid ULEN.
  209. func TestRFC1929InvalidUlen(t *testing.T) {
  210. c := new(testReadWriter)
  211. req := c.toRequest()
  212. // VER = 01, ULEN = 0, UNAME = "", PLEN = 5, PASSWD = "abcde"
  213. c.writeHex("0100056162636465")
  214. if err := req.authenticate(authUsernamePassword); err == nil {
  215. t.Error("authenticate(InvalidUlen) succeded")
  216. }
  217. if msg := c.readHex(); msg != "0101" {
  218. t.Error("authenticate(InvalidUlen) invalid response:", msg)
  219. }
  220. }
  221. // TestRFC1929InvalidPlen tests RFC1929 auth with an invalid PLEN.
  222. func TestRFC1929InvalidPlen(t *testing.T) {
  223. c := new(testReadWriter)
  224. req := c.toRequest()
  225. // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 0, PASSWD = ""
  226. c.writeHex("0105414243444500")
  227. if err := req.authenticate(authUsernamePassword); err == nil {
  228. t.Error("authenticate(InvalidPlen) succeded")
  229. }
  230. if msg := c.readHex(); msg != "0101" {
  231. t.Error("authenticate(InvalidPlen) invalid response:", msg)
  232. }
  233. }
  234. // TestRFC1929Success tests RFC1929 auth with valid credentials.
  235. func TestRFC1929Success(t *testing.T) {
  236. c := new(testReadWriter)
  237. req := c.toRequest()
  238. // VER = 01, ULEN = 5, UNAME = "ABCDE", PLEN = 5, PASSWD = "abcde"
  239. c.writeHex("01054142434445056162636465")
  240. if err := req.authenticate(authUsernamePassword); err != nil {
  241. t.Error("authenticate(Success) failed:", err)
  242. }
  243. if msg := c.readHex(); msg != "0100" {
  244. t.Error("authenticate(Success) invalid response:", msg)
  245. }
  246. if string(req.Uname) != "ABCDE" {
  247. t.Error("RFC1929 uname mismatch:", req.Uname)
  248. }
  249. if string(req.Passwd) != "abcde" {
  250. t.Error("RFC1929 passwd mismatch:", req.Passwd)
  251. }
  252. }
  253. // TestRequestInvalidHdr tests SOCKS5 requests with invalid VER/CMD/RSV/ATYPE
  254. func TestRequestInvalidHdr(t *testing.T) {
  255. c := new(testReadWriter)
  256. req := c.toRequest()
  257. // VER = 03, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  258. c.writeHex("030100017f000001235a")
  259. if err := req.readCommand(); err == nil {
  260. t.Error("readCommand(InvalidVer) succeded")
  261. }
  262. if msg := c.readHex(); msg != "05010001000000000000" {
  263. t.Error("readCommand(InvalidVer) invalid response:", msg)
  264. }
  265. c.reset(req)
  266. // VER = 05, CMD = 05, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  267. c.writeHex("050500017f000001235a")
  268. if err := req.readCommand(); err == nil {
  269. t.Error("readCommand(InvalidCmd) succeded")
  270. }
  271. if msg := c.readHex(); msg != "05070001000000000000" {
  272. t.Error("readCommand(InvalidCmd) invalid response:", msg)
  273. }
  274. c.reset(req)
  275. // VER = 05, CMD = 01, RSV = 30, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  276. c.writeHex("050130017f000001235a")
  277. if err := req.readCommand(); err == nil {
  278. t.Error("readCommand(InvalidRsv) succeded")
  279. }
  280. if msg := c.readHex(); msg != "05010001000000000000" {
  281. t.Error("readCommand(InvalidRsv) invalid response:", msg)
  282. }
  283. c.reset(req)
  284. // VER = 05, CMD = 01, RSV = 01, ATYPE = 05, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  285. c.writeHex("050100057f000001235a")
  286. if err := req.readCommand(); err == nil {
  287. t.Error("readCommand(InvalidAtype) succeded")
  288. }
  289. if msg := c.readHex(); msg != "05080001000000000000" {
  290. t.Error("readCommand(InvalidAtype) invalid response:", msg)
  291. }
  292. c.reset(req)
  293. }
  294. // TestRequestIPv4 tests IPv4 SOCKS5 requests.
  295. func TestRequestIPv4(t *testing.T) {
  296. c := new(testReadWriter)
  297. req := c.toRequest()
  298. // VER = 05, CMD = 01, RSV = 00, ATYPE = 01, DST.ADDR = 127.0.0.1, DST.PORT = 9050
  299. c.writeHex("050100017f000001235a")
  300. if err := req.readCommand(); err != nil {
  301. t.Error("readCommand(IPv4) failed:", err)
  302. }
  303. addr, err := net.ResolveTCPAddr("tcp", req.Target)
  304. if err != nil {
  305. t.Error("net.ResolveTCPAddr failed:", err)
  306. }
  307. if !tcpAddrsEqual(addr, &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 9050}) {
  308. t.Error("Unexpected target:", addr)
  309. }
  310. }
  311. // TestRequestIPv6 tests IPv4 SOCKS5 requests.
  312. func TestRequestIPv6(t *testing.T) {
  313. c := new(testReadWriter)
  314. req := c.toRequest()
  315. // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = 0102:0304:0506:0708:090a:0b0c:0d0e:0f10, DST.PORT = 9050
  316. c.writeHex("050100040102030405060708090a0b0c0d0e0f10235a")
  317. if err := req.readCommand(); err != nil {
  318. t.Error("readCommand(IPv6) failed:", err)
  319. }
  320. addr, err := net.ResolveTCPAddr("tcp", req.Target)
  321. if err != nil {
  322. t.Error("net.ResolveTCPAddr failed:", err)
  323. }
  324. if !tcpAddrsEqual(addr, &net.TCPAddr{IP: net.ParseIP("0102:0304:0506:0708:090a:0b0c:0d0e:0f10"), Port: 9050}) {
  325. t.Error("Unexpected target:", addr)
  326. }
  327. }
  328. // TestRequestFQDN tests FQDN (DOMAINNAME) SOCKS5 requests.
  329. func TestRequestFQDN(t *testing.T) {
  330. c := new(testReadWriter)
  331. req := c.toRequest()
  332. // VER = 05, CMD = 01, RSV = 00, ATYPE = 04, DST.ADDR = example.com, DST.PORT = 9050
  333. c.writeHex("050100030b6578616d706c652e636f6d235a")
  334. if err := req.readCommand(); err != nil {
  335. t.Error("readCommand(FQDN) failed:", err)
  336. }
  337. if req.Target != "example.com:9050" {
  338. t.Error("Unexpected target:", req.Target)
  339. }
  340. }
  341. // TestResponseNil tests nil address SOCKS5 responses.
  342. func TestResponseNil(t *testing.T) {
  343. c := new(testReadWriter)
  344. req := c.toRequest()
  345. if err := req.Reply(ReplySucceeded); err != nil {
  346. t.Error("Reply(ReplySucceeded) failed:", err)
  347. }
  348. if msg := c.readHex(); msg != "05000001000000000000" {
  349. t.Error("Reply(ReplySucceeded) invalid response:", msg)
  350. }
  351. }
  352. var _ io.ReadWriter = (*testReadWriter)(nil)