mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
4aa9affec2
If openssl was old, Tor would add a warning about its version in between saying "no torrc found, using reasonable defaults" and "configuration was valid".
274 lines
9.1 KiB
Python
Executable File
274 lines
9.1 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
import binascii
|
|
import hashlib
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
TOR = "./src/or/tor"
|
|
TOP_SRCDIR = "."
|
|
|
|
if len(sys.argv) > 1:
|
|
TOR = sys.argv[1]
|
|
del sys.argv[1]
|
|
|
|
if len(sys.argv) > 1:
|
|
TOP_SRCDIR = sys.argv[1]
|
|
del sys.argv[1]
|
|
|
|
class UnexpectedSuccess(Exception):
|
|
pass
|
|
|
|
class UnexpectedFailure(Exception):
|
|
pass
|
|
|
|
def contents(fn):
|
|
f = open(fn)
|
|
try:
|
|
return f.read()
|
|
finally:
|
|
f.close()
|
|
|
|
def run_tor(args, failure=False):
|
|
p = subprocess.Popen([TOR] + args, stdout=subprocess.PIPE)
|
|
output, _ = p.communicate()
|
|
result = p.poll()
|
|
if result and not failure:
|
|
raise UnexpectedFailure()
|
|
elif not result and failure:
|
|
raise UnexpectedSuccess()
|
|
return output
|
|
|
|
def spaceify_fp(fp):
|
|
for i in xrange(0, len(fp), 4):
|
|
yield fp[i:i+4]
|
|
|
|
def lines(s):
|
|
out = s.split("\n")
|
|
if out and out[-1] == '':
|
|
del out[-1]
|
|
return out
|
|
|
|
def strip_log_junk(line):
|
|
m = re.match(r'([^\[]+\[[a-z]*\] *)(.*)', line)
|
|
if not m:
|
|
return ""+line
|
|
return m.group(2).strip()
|
|
|
|
def randstring(entropy_bytes):
|
|
s = os.urandom(entropy_bytes)
|
|
return binascii.b2a_hex(s)
|
|
|
|
def findLineContaining(lines, s):
|
|
for ln in lines:
|
|
if s in ln:
|
|
return True
|
|
return False
|
|
|
|
class CmdlineTests(unittest.TestCase):
|
|
|
|
def test_version(self):
|
|
out = run_tor(["--version"])
|
|
self.failUnless(out.startswith("Tor version "))
|
|
self.assertEquals(len(lines(out)), 1)
|
|
|
|
def test_quiet(self):
|
|
out = run_tor(["--quiet", "--quumblebluffin", "1"], failure=True)
|
|
self.assertEquals(out, "")
|
|
|
|
def test_help(self):
|
|
out = run_tor(["--help"], failure=False)
|
|
out2 = run_tor(["-h"], failure=False)
|
|
self.assert_(out.startswith("Copyright (c) 2001"))
|
|
self.assert_(out.endswith(
|
|
"tor -f <torrc> [args]\n"
|
|
"See man page for options, or https://www.torproject.org/ for documentation.\n"))
|
|
self.assert_(out == out2)
|
|
|
|
def test_hush(self):
|
|
torrc = tempfile.NamedTemporaryFile(delete=False)
|
|
torrc.close()
|
|
try:
|
|
out = run_tor(["--hush", "-f", torrc.name,
|
|
"--quumblebluffin", "1"], failure=True)
|
|
finally:
|
|
os.unlink(torrc.name)
|
|
self.assertEquals(len(lines(out)), 2)
|
|
ln = [ strip_log_junk(l) for l in lines(out) ]
|
|
self.assertEquals(ln[0], "Failed to parse/validate config: Unknown option 'quumblebluffin'. Failing.")
|
|
self.assertEquals(ln[1], "Reading config failed--see warnings above.")
|
|
|
|
def test_missing_argument(self):
|
|
out = run_tor(["--hush", "--hash-password"], failure=True)
|
|
self.assertEquals(len(lines(out)), 2)
|
|
ln = [ strip_log_junk(l) for l in lines(out) ]
|
|
self.assertEquals(ln[0], "Command-line option '--hash-password' with no value. Failing.")
|
|
|
|
def test_hash_password(self):
|
|
out = run_tor(["--hash-password", "woodwose"])
|
|
result = lines(out)[-1]
|
|
self.assertEquals(result[:3], "16:")
|
|
self.assertEquals(len(result), 61)
|
|
r = binascii.a2b_hex(result[3:])
|
|
self.assertEquals(len(r), 29)
|
|
|
|
salt, how, hashed = r[:8], r[8], r[9:]
|
|
self.assertEquals(len(hashed), 20)
|
|
|
|
count = (16 + (ord(how) & 15)) << ((ord(how) >> 4) + 6)
|
|
stuff = salt + "woodwose"
|
|
repetitions = count // len(stuff) + 1
|
|
inp = stuff * repetitions
|
|
inp = inp[:count]
|
|
|
|
self.assertEquals(hashlib.sha1(inp).digest(), hashed)
|
|
|
|
def test_digests(self):
|
|
main_c = os.path.join(TOP_SRCDIR, "src", "or", "main.c")
|
|
|
|
if os.stat(TOR).st_mtime < os.stat(main_c).st_mtime:
|
|
self.skipTest(TOR+" not up to date")
|
|
out = run_tor(["--digests"])
|
|
main_line = [ l for l in lines(out) if l.endswith("/main.c") ]
|
|
digest, name = main_line[0].split()
|
|
actual = hashlib.sha1(open(main_c).read()).hexdigest()
|
|
self.assertEquals(digest, actual)
|
|
|
|
def test_dump_options(self):
|
|
default_torrc = tempfile.NamedTemporaryFile(delete=False)
|
|
torrc = tempfile.NamedTemporaryFile(delete=False)
|
|
torrc.write("SocksPort 9999")
|
|
torrc.close()
|
|
default_torrc.write("SafeLogging 0")
|
|
default_torrc.close()
|
|
out_sh = out_nb = out_fl = None
|
|
opts = [ "-f", torrc.name,
|
|
"--defaults-torrc", default_torrc.name ]
|
|
try:
|
|
out_sh = run_tor(["--dump-config", "short"]+opts)
|
|
out_nb = run_tor(["--dump-config", "non-builtin"]+opts)
|
|
out_fl = run_tor(["--dump-config", "full"]+opts)
|
|
out_nr = run_tor(["--dump-config", "bliznert"]+opts,
|
|
failure=True)
|
|
|
|
out_verif = run_tor(["--verify-config"]+opts)
|
|
finally:
|
|
os.unlink(torrc.name)
|
|
os.unlink(default_torrc.name)
|
|
|
|
self.assertEquals(len(lines(out_sh)), 2)
|
|
self.assert_(lines(out_sh)[0].startswith("DataDirectory "))
|
|
self.assertEquals(lines(out_sh)[1:],
|
|
[ "SocksPort 9999" ])
|
|
|
|
self.assertEquals(len(lines(out_nb)), 2)
|
|
self.assertEquals(lines(out_nb),
|
|
[ "SafeLogging 0",
|
|
"SocksPort 9999" ])
|
|
|
|
out_fl = lines(out_fl)
|
|
self.assert_(len(out_fl) > 100)
|
|
self.assert_("SocksPort 9999" in out_fl)
|
|
self.assert_("SafeLogging 0" in out_fl)
|
|
self.assert_("ClientOnly 0" in out_fl)
|
|
|
|
self.assert_(out_verif.endswith("Configuration was valid\n"))
|
|
|
|
def test_list_fingerprint(self):
|
|
tmpdir = tempfile.mkdtemp(prefix='ttca_')
|
|
torrc = tempfile.NamedTemporaryFile(delete=False)
|
|
torrc.write("ORPort 9999\n")
|
|
torrc.write("DataDirectory %s\n"%tmpdir)
|
|
torrc.write("Nickname tippi")
|
|
torrc.close()
|
|
opts = ["-f", torrc.name]
|
|
try:
|
|
out = run_tor(["--list-fingerprint"]+opts)
|
|
fp = contents(os.path.join(tmpdir, "fingerprint"))
|
|
finally:
|
|
os.unlink(torrc.name)
|
|
shutil.rmtree(tmpdir)
|
|
|
|
out = lines(out)
|
|
lastlog = strip_log_junk(out[-2])
|
|
lastline = out[-1]
|
|
fp = fp.strip()
|
|
nn_fp = fp.split()[0]
|
|
space_fp = " ".join(spaceify_fp(fp.split()[1]))
|
|
self.assertEquals(lastlog,
|
|
"Your Tor server's identity key fingerprint is '%s'"%fp)
|
|
self.assertEquals(lastline, "tippi %s"%space_fp)
|
|
self.assertEquals(nn_fp, "tippi")
|
|
|
|
def test_list_options(self):
|
|
out = lines(run_tor(["--list-torrc-options"]))
|
|
self.assert_(len(out)>100)
|
|
self.assert_(out[0] <= 'AccountingMax')
|
|
self.assert_("UseBridges" in out)
|
|
self.assert_("SocksPort" in out)
|
|
|
|
def test_cmdline_args(self):
|
|
default_torrc = tempfile.NamedTemporaryFile(delete=False)
|
|
torrc = tempfile.NamedTemporaryFile(delete=False)
|
|
torrc.write("SocksPort 9999\n")
|
|
torrc.write("SocksPort 9998\n")
|
|
torrc.write("ORPort 9000\n")
|
|
torrc.write("ORPort 9001\n")
|
|
torrc.write("Nickname eleventeen\n")
|
|
torrc.write("ControlPort 9500\n")
|
|
torrc.close()
|
|
default_torrc.write("")
|
|
default_torrc.close()
|
|
out_sh = out_nb = out_fl = None
|
|
opts = [ "-f", torrc.name,
|
|
"--defaults-torrc", default_torrc.name,
|
|
"--dump-config", "short" ]
|
|
try:
|
|
out_1 = run_tor(opts)
|
|
out_2 = run_tor(opts+["+ORPort", "9003",
|
|
"SocksPort", "9090",
|
|
"/ControlPort",
|
|
"/TransPort",
|
|
"+ExtORPort", "9005"])
|
|
finally:
|
|
os.unlink(torrc.name)
|
|
os.unlink(default_torrc.name)
|
|
|
|
out_1 = [ l for l in lines(out_1) if not l.startswith("DataDir") ]
|
|
out_2 = [ l for l in lines(out_2) if not l.startswith("DataDir") ]
|
|
|
|
self.assertEquals(out_1,
|
|
["ControlPort 9500",
|
|
"Nickname eleventeen",
|
|
"ORPort 9000",
|
|
"ORPort 9001",
|
|
"SocksPort 9999",
|
|
"SocksPort 9998"])
|
|
self.assertEquals(out_2,
|
|
["ExtORPort 9005",
|
|
"Nickname eleventeen",
|
|
"ORPort 9000",
|
|
"ORPort 9001",
|
|
"ORPort 9003",
|
|
"SocksPort 9090"])
|
|
|
|
def test_missing_torrc(self):
|
|
fname = "nonexistent_file_"+randstring(8)
|
|
out = run_tor(["-f", fname, "--verify-config"], failure=True)
|
|
ln = [ strip_log_junk(l) for l in lines(out) ]
|
|
self.assert_("Unable to open configuration file" in ln[-2])
|
|
self.assert_("Reading config failed" in ln[-1])
|
|
|
|
out = run_tor(["-f", fname, "--verify-config", "--ignore-missing-torrc"])
|
|
ln = [ strip_log_junk(l) for l in lines(out) ]
|
|
self.assert_(findLineContaining(ln, ", using reasonable defaults"))
|
|
self.assert_("Configuration was valid" in ln[-1])
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|