Add basic pledge/unveil sandbox on OpenBSD
[tinc] / test / integration / commandline.py
1 #!/usr/bin/env python3
2
3 """Test supported and unsupported commandline flags."""
4
5 import os
6 import signal
7 import subprocess as subp
8 import time
9
10 from testlib import check, util, path
11 from testlib.log import log
12 from testlib.proc import Tinc, Script
13 from testlib.test import Test
14 from testlib.feature import SANDBOX_LEVEL
15
16 tinc_flags = (
17     (0, ("get", "name")),
18     (0, ("-n", "foo", "get", "name")),
19     (0, ("-nfoo", "get", "name")),
20     (0, ("--net=foo", "get", "name")),
21     (0, ("--net", "foo", "get", "name")),
22     (0, ("-c", "conf", "-c", "conf")),
23     (0, ("-n", "net", "-n", "net")),
24     (0, ("--pidfile=pid", "--pidfile=pid")),
25     (1, ("-n", "foo", "get", "somethingreallyunknown")),
26     (1, ("--net",)),
27     (1, ("--net", "get", "name")),
28     (1, ("foo",)),
29     (1, ("-c", "conf", "-n", "n/e\\t")),
30 )
31
32 tincd_flags = (
33     (0, ("-D",)),
34     (0, ("--no-detach",)),
35     (0, ("-D", "-d")),
36     (0, ("-D", "-d2")),
37     (0, ("-D", "-d", "2")),
38     (0, ("-D", "-n", "foo")),
39     (0, ("-D", "-nfoo")),
40     (0, ("-D", "--net=foo")),
41     (0, ("-D", "--net", "foo")),
42     (0, ("-D", "-c", ".", "-c", ".")),
43     (0, ("-D", "-n", "net", "-n", "net")),
44     (0, ("-D", "-n", "net", "-o", "FakeOpt=42")),
45     (0, ("-D", "--logfile=log", "--logfile=log")),
46     (0, ("-D", "--pidfile=pid", "--pidfile=pid")),
47     (1, ("foo",)),
48     (1, ("--pidfile",)),
49     (1, ("--foo",)),
50     (1, ("-n", "net", "-o", "Compression=")),
51     (1, ("-c", "fakedir", "-n", "n/e\\t")),
52 )
53
54
55 def init(ctx: Test) -> Tinc:
56     """Initialize new test nodes."""
57     tinc = ctx.node()
58     stdin = f"""
59         init {tinc}
60         set Port 0
61         set Address localhost
62         set DeviceType dummy
63         set Sandbox {SANDBOX_LEVEL}
64     """
65     tinc.cmd(stdin=stdin)
66     tinc.add_script(Script.TINC_UP)
67     return tinc
68
69
70 with Test("commandline flags") as context:
71     node = init(context)
72
73     for code, flags in tincd_flags:
74         COOKIE = util.random_string(10)
75         server = node.tincd(*flags, env={"COOKIE": COOKIE})
76
77         if not code:
78             log.info("waiting for tincd to come up")
79             env = node[Script.TINC_UP].wait().env
80             check.equals(COOKIE, env["COOKIE"])
81
82         log.info("stopping tinc")
83         node.cmd("stop", code=code)
84
85         log.info("reading tincd output")
86         stdout, stderr = server.communicate()
87
88         log.debug('got code %d, ("%s", "%s")', server.returncode, stdout, stderr)
89         check.equals(code, server.returncode)
90
91     for code, flags in tinc_flags:
92         node.cmd(*flags, code=code)
93
94
95 def test_relative_path(ctx: Test, chroot: bool) -> None:
96     """Test tincd with relative paths."""
97
98     foo = init(ctx)
99
100     conf_dir = os.path.realpath(foo.sub("."))
101     dirname = os.path.dirname(conf_dir)
102     basename = os.path.basename(conf_dir)
103     log.info("using confdir %s, dirname %s, basename %s", conf_dir, dirname, basename)
104
105     args = [
106         path.TINCD_PATH,
107         "-D",
108         "-c",
109         basename,
110         "--pidfile",
111         "pid",
112         "--logfile",
113         ".//./log",
114     ]
115
116     if chroot:
117         args.append("-R")
118
119     pidfile = os.path.join(dirname, "pid")
120     util.remove_file(pidfile)
121
122     logfile = os.path.join(dirname, "log")
123     util.remove_file(logfile)
124
125     with subp.Popen(args, stderr=subp.STDOUT, cwd=dirname) as tincd:
126         foo[Script.TINC_UP].wait(10)
127
128         log.info("pidfile and logfile must exist at expected paths")
129         check.file_exists(pidfile)
130         check.file_exists(logfile)
131
132         # chrooted tincd won't be able to reopen its log since in this
133         # test we put the log outside tinc's configuration directory.
134         if os.name != "nt" and not chroot:
135             log.info("test log file rotation")
136             time.sleep(1)
137             util.remove_file(logfile)
138             os.kill(tincd.pid, signal.SIGHUP)
139             time.sleep(1)
140
141             log.info("pidfile and logfile must still exist")
142             check.file_exists(pidfile)
143             check.file_exists(logfile)
144
145         log.info("stopping tinc through '%s'", pidfile)
146         foo.cmd("--pidfile", pidfile, "stop")
147         check.equals(0, tincd.wait())
148
149
150 with Test("relative path to tincd dir") as context:
151     test_relative_path(context, chroot=False)
152
153 if os.name != "nt" and not os.getuid():
154     with Test("relative path to tincd dir (chroot)") as context:
155         test_relative_path(context, chroot=True)