test_cmdline_args.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #!/usr/bin/python
  2. import binascii
  3. import hashlib
  4. import os
  5. import re
  6. import shutil
  7. import subprocess
  8. import sys
  9. import tempfile
  10. import unittest
  11. TOR = "./src/or/tor"
  12. TOP_SRCDIR = "."
  13. if len(sys.argv) > 1:
  14. TOR = sys.argv[1]
  15. del sys.argv[1]
  16. if len(sys.argv) > 1:
  17. TOP_SRCDIR = sys.argv[1]
  18. del sys.argv[1]
  19. class UnexpectedSuccess(Exception):
  20. pass
  21. class UnexpectedFailure(Exception):
  22. pass
  23. def contents(fn):
  24. f = open(fn)
  25. try:
  26. return f.read()
  27. finally:
  28. f.close()
  29. def run_tor(args, failure=False):
  30. p = subprocess.Popen([TOR] + args, stdout=subprocess.PIPE)
  31. output, _ = p.communicate()
  32. result = p.poll()
  33. if result and not failure:
  34. raise UnexpectedFailure()
  35. elif not result and failure:
  36. raise UnexpectedSuccess()
  37. return output
  38. def spaceify_fp(fp):
  39. for i in xrange(0, len(fp), 4):
  40. yield fp[i:i+4]
  41. def lines(s):
  42. out = s.split("\n")
  43. if out and out[-1] == '':
  44. del out[-1]
  45. return out
  46. def strip_log_junk(line):
  47. m = re.match(r'([^\[]+\[[a-z]*\] *)(.*)', line)
  48. if not m:
  49. return ""+line
  50. return m.group(2).strip()
  51. class CmdlineTests(unittest.TestCase):
  52. def test_version(self):
  53. out = run_tor(["--version"])
  54. self.failUnless(out.startswith("Tor version "))
  55. self.assertEquals(len(lines(out)), 1)
  56. def test_quiet(self):
  57. out = run_tor(["--quiet", "--quumblebluffin", "1"], failure=True)
  58. self.assertEquals(out, "")
  59. def test_help(self):
  60. out = run_tor(["--help"], failure=False)
  61. out2 = run_tor(["-h"], failure=False)
  62. self.assert_(out.startswith("Copyright (c) 2001"))
  63. self.assert_(out.endswith(
  64. "tor -f <torrc> [args]\n"
  65. "See man page for options, or https://www.torproject.org/ for documentation.\n"))
  66. self.assert_(out == out2)
  67. def test_hush(self):
  68. torrc = tempfile.NamedTemporaryFile(delete=False)
  69. torrc.close()
  70. try:
  71. out = run_tor(["--hush", "-f", torrc.name,
  72. "--quumblebluffin", "1"], failure=True)
  73. finally:
  74. os.unlink(torrc.name)
  75. self.assertEquals(len(lines(out)), 2)
  76. ln = [ strip_log_junk(l) for l in lines(out) ]
  77. self.assertEquals(ln[0], "Failed to parse/validate config: Unknown option 'quumblebluffin'. Failing.")
  78. self.assertEquals(ln[1], "Reading config failed--see warnings above.")
  79. def test_missing_argument(self):
  80. out = run_tor(["--hush", "--hash-password"], failure=True)
  81. self.assertEquals(len(lines(out)), 2)
  82. ln = [ strip_log_junk(l) for l in lines(out) ]
  83. self.assertEquals(ln[0], "Command-line option '--hash-password' with no value. Failing.")
  84. def test_hash_password(self):
  85. out = run_tor(["--hash-password", "woodwose"])
  86. result = lines(out)[-1]
  87. self.assertEquals(result[:3], "16:")
  88. self.assertEquals(len(result), 61)
  89. r = binascii.a2b_hex(result[3:])
  90. self.assertEquals(len(r), 29)
  91. salt, how, hashed = r[:8], r[8], r[9:]
  92. self.assertEquals(len(hashed), 20)
  93. count = (16 + (ord(how) & 15)) << ((ord(how) >> 4) + 6)
  94. stuff = salt + "woodwose"
  95. repetitions = count // len(stuff) + 1
  96. inp = stuff * repetitions
  97. inp = inp[:count]
  98. self.assertEquals(hashlib.sha1(inp).digest(), hashed)
  99. def test_digests(self):
  100. main_c = os.path.join(TOP_SRCDIR, "src", "or", "main.c")
  101. if os.stat(TOR).st_mtime < os.stat(main_c).st_mtime:
  102. self.skipTest(TOR+" not up to date")
  103. out = run_tor(["--digests"])
  104. main_line = [ l for l in lines(out) if l.endswith("/main.c") ]
  105. digest, name = main_line[0].split()
  106. actual = hashlib.sha1(open(main_c).read()).hexdigest()
  107. self.assertEquals(digest, actual)
  108. def test_dump_options(self):
  109. default_torrc = tempfile.NamedTemporaryFile(delete=False)
  110. torrc = tempfile.NamedTemporaryFile(delete=False)
  111. torrc.write("SocksPort 9999")
  112. torrc.close()
  113. default_torrc.write("SafeLogging 0")
  114. default_torrc.close()
  115. out_sh = out_nb = out_fl = None
  116. opts = [ "-f", torrc.name,
  117. "--defaults-torrc", default_torrc.name ]
  118. try:
  119. out_sh = run_tor(["--dump-config", "short"]+opts)
  120. out_nb = run_tor(["--dump-config", "non-builtin"]+opts)
  121. out_fl = run_tor(["--dump-config", "full"]+opts)
  122. out_nr = run_tor(["--dump-config", "bliznert"]+opts,
  123. failure=True)
  124. out_verif = run_tor(["--verify-config"]+opts)
  125. finally:
  126. os.unlink(torrc.name)
  127. os.unlink(default_torrc.name)
  128. self.assertEquals(len(lines(out_sh)), 2)
  129. self.assert_(lines(out_sh)[0].startswith("DataDirectory "))
  130. self.assertEquals(lines(out_sh)[1:],
  131. [ "SocksPort 9999" ])
  132. self.assertEquals(len(lines(out_nb)), 2)
  133. self.assertEquals(lines(out_nb),
  134. [ "SafeLogging 0",
  135. "SocksPort 9999" ])
  136. out_fl = lines(out_fl)
  137. self.assert_(len(out_fl) > 100)
  138. self.assertIn("SocksPort 9999", out_fl)
  139. self.assertIn("SafeLogging 0", out_fl)
  140. self.assertIn("ClientOnly 0", out_fl)
  141. self.assert_(out_verif.endswith("Configuration was valid\n"))
  142. def test_list_fingerprint(self):
  143. tmpdir = tempfile.mkdtemp(prefix='ttca_')
  144. torrc = tempfile.NamedTemporaryFile(delete=False)
  145. torrc.write("ORPort 9999\n")
  146. torrc.write("DataDirectory %s\n"%tmpdir)
  147. torrc.write("Nickname tippi")
  148. torrc.close()
  149. opts = ["-f", torrc.name]
  150. try:
  151. out = run_tor(["--list-fingerprint"]+opts)
  152. fp = contents(os.path.join(tmpdir, "fingerprint"))
  153. finally:
  154. os.unlink(torrc.name)
  155. shutil.rmtree(tmpdir)
  156. out = lines(out)
  157. lastlog = strip_log_junk(out[-2])
  158. lastline = out[-1]
  159. fp = fp.strip()
  160. nn_fp = fp.split()[0]
  161. space_fp = " ".join(spaceify_fp(fp.split()[1]))
  162. self.assertEquals(lastlog,
  163. "Your Tor server's identity key fingerprint is '%s'"%fp)
  164. self.assertEquals(lastline, "tippi %s"%space_fp)
  165. self.assertEquals(nn_fp, "tippi")
  166. def test_list_options(self):
  167. out = lines(run_tor(["--list-torrc-options"]))
  168. self.assert_(len(out)>100)
  169. self.assert_(out[0] <= 'AccountingMax')
  170. self.assert_("UseBridges" in out)
  171. self.assert_("SocksPort" in out)
  172. def test_cmdline_args(self):
  173. default_torrc = tempfile.NamedTemporaryFile(delete=False)
  174. torrc = tempfile.NamedTemporaryFile(delete=False)
  175. torrc.write("SocksPort 9999\n")
  176. torrc.write("SocksPort 9998\n")
  177. torrc.write("ORPort 9000\n")
  178. torrc.write("ORPort 9001\n")
  179. torrc.write("Nickname eleventeen\n")
  180. torrc.write("ControlPort 9500\n")
  181. torrc.close()
  182. default_torrc.write("")
  183. default_torrc.close()
  184. out_sh = out_nb = out_fl = None
  185. opts = [ "-f", torrc.name,
  186. "--defaults-torrc", default_torrc.name,
  187. "--dump-config", "short" ]
  188. try:
  189. out_1 = run_tor(opts)
  190. out_2 = run_tor(opts+["+ORPort", "9003",
  191. "SocksPort", "9090",
  192. "/ControlPort",
  193. "/TransPort",
  194. "+ExtORPort", "9005"])
  195. finally:
  196. os.unlink(torrc.name)
  197. os.unlink(default_torrc.name)
  198. out_1 = [ l for l in lines(out_1) if not l.startswith("DataDir") ]
  199. out_2 = [ l for l in lines(out_2) if not l.startswith("DataDir") ]
  200. self.assertEquals(out_1,
  201. ["ControlPort 9500",
  202. "Nickname eleventeen",
  203. "ORPort 9000",
  204. "ORPort 9001",
  205. "SocksPort 9999",
  206. "SocksPort 9998"])
  207. self.assertEquals(out_2,
  208. ["ExtORPort 9005",
  209. "Nickname eleventeen",
  210. "ORPort 9000",
  211. "ORPort 9001",
  212. "ORPort 9003",
  213. "SocksPort 9090"])
  214. if __name__ == '__main__':
  215. unittest.main()