Mercurial > dropbear
annotate test/test_channels.py @ 1885:5d8dbb6fdab7
Fix SSH_PUBKEYINFO, limit characters, add tests
We fix a bad_bufptr() failure from a previous commit. We now limit
the allowed characters to those that will definitely be safe
in a shell. Some scripts/programs may use arbitrary environment
variables without escaping correctly - that could be a problem
in a restricted environment.
The current allowed set is a-z A-Z 0-9 .,_-+@
This also adds a test for SSH_PUBKEYINFO, by default it only runs
under github actions (or "act -j build").
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 16 Mar 2022 17:17:23 +0800 |
parents | 06c7ddbb9dd6 |
children |
rev | line source |
---|---|
1836
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
1 from test_dropbear import * |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
2 import signal |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
3 import queue |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
4 import socket |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
5 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
6 # Tests for various edge cases of SSH channels and connection service |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
7 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
8 def test_exitcode(request, dropbear): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
9 r = dbclient(request, "exit 44") |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
10 assert r.returncode == 44 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
11 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
12 @pytest.mark.xfail(reason="Not yet implemented", strict=True) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
13 def test_signal(request, dropbear): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
14 r = dbclient(request, "kill -FPE $$") |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
15 assert r.returncode == -signal.SIGFPE |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
16 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
17 @pytest.mark.parametrize("size", [0, 1, 2, 100, 5000, 200_000]) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
18 def test_roundtrip(request, dropbear, size): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
19 dat = os.urandom(size) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
20 r = dbclient(request, "cat", input=dat, capture_output=True) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
21 r.check_returncode() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
22 assert r.stdout == dat |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
23 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
24 @pytest.mark.parametrize("size", [0, 1, 2, 100, 20001, 41234]) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
25 def test_read_pty(request, dropbear, size): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
26 # testcase for |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
27 # https://bugs.openwrt.org/index.php?do=details&task_id=1814 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
28 # https://github.com/mkj/dropbear/pull/85 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
29 # From Yousong Zhou |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
30 # Fixed Oct 2021 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
31 # |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
32 #$ ssh -t my.router cat /tmp/bigfile | wc |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
33 #Connection to my.router closed. |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
34 # 0 1 14335 <- should be 20001 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
35 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
36 # Write the file. No newlines etc which could confuse ptys |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
37 dat = random_alnum(size) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
38 r = dbclient(request, "tmpf=`mktemp`; echo $tmpf; cat > $tmpf", input=dat, capture_output=True, text=True) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
39 tmpf = r.stdout.rstrip() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
40 r.check_returncode() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
41 # Read with a pty, this is what is being tested. |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
42 # Timing/buffering is subtle, we seem to need to cat a file from disk to hit it. |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
43 m, s = pty.openpty() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
44 r = dbclient(request, "-t", f"cat {tmpf}; rm {tmpf}", stdin=s, capture_output=True) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
45 r.check_returncode() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
46 assert r.stdout.decode() == dat |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
47 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
48 @pytest.mark.parametrize("fd", [1, 2]) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
49 def test_bg_sleep(request, fd, dropbear): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
50 # https://lists.ucc.asn.au/pipermail/dropbear/2006q1/000362.html |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
51 # Rob Landley "Is this a bug?" 24 Mar 2006 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
52 # dbclient user@system "sleep 10& echo hello" |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
53 # |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
54 # It should return right after printing hello, but it doesn't. It waits until |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
55 # the child process exits. |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
56 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
57 # failure is TimeoutExpired |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
58 redir = "" if fd == 1 else " >&2 " |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
59 r = dbclient(request, f"sleep 10& echo hello {redir}", |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
60 capture_output=True, timeout=2, text=True) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
61 r.check_returncode() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
62 st = r.stdout if fd == 1 else r.stderr |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
63 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
64 if fd == 2 and 'accepted unconditionally' in st: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
65 # ignore hostkey warning, a bit of a hack |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
66 assert st.endswith("\n\nhello\n") |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
67 else: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
68 assert st.rstrip() == "hello" |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
69 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
70 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
71 def test_idle(request, dropbear): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
72 # Idle test, -I 1 should make it return before the 2 second timeout |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
73 r = dbclient(request, "-I", "1", "echo zong; sleep 10", |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
74 capture_output=True, timeout=2, text=True) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
75 r.check_returncode() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
76 assert r.stdout.rstrip() == "zong" |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
77 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
78 @pytest.mark.parametrize("size", [1, 4000, 40000]) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
79 def test_netcat(request, dropbear, size): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
80 opt = request.config.option |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
81 if opt.remote: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
82 pytest.xfail("don't know netcat address for remote") |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
83 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
84 dat1 = os.urandom(size) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
85 dat2 = os.urandom(size) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
86 with HandleTcp(3344, 1, dat2) as tcp: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
87 r = dbclient(request, "-B", "localhost:3344", input=dat1, capture_output=True) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
88 r.check_returncode() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
89 assert r.stdout == dat2 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
90 assert tcp.inbound() == dat1 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
91 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
92 @pytest.mark.parametrize("size", [1, 4000, 40000]) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
93 @pytest.mark.parametrize("fwd_flag", "LR") |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
94 def test_tcpflushout(request, dropbear, size, fwd_flag): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
95 """ Tests that an opened TCP connection prevent a SSH session from being closed |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
96 until that TCP connection has finished transferring |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
97 """ |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
98 opt = request.config.option |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
99 if opt.remote: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
100 pytest.xfail("don't know address for remote") |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
101 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
102 dat1 = os.urandom(size) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
103 dat2 = os.urandom(size) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
104 q = queue.Queue() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
105 with HandleTcp(3344, timeout=1, response=q) as tcp: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
106 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
107 r = dbclient(request, f"-{fwd_flag}", "7788:localhost:3344", "sleep 0.1; echo -n done", |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
108 text=True, background=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
109 # time to let the listener start |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
110 time.sleep(0.1) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
111 # open a tcp connection |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
112 c = socket.create_connection(("localhost", 7788)) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
113 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
114 # wait for the shell to finish. sleep a bit longer in case it exits. |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
115 assert r.stdout.read(4) == "done" |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
116 time.sleep(0.1) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
117 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
118 # now the shell has finished, we can write on the tcp socket |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
119 c.sendall(dat2) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
120 c.shutdown(socket.SHUT_WR) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
121 q.put(dat1) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
122 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
123 # return a tcp response |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
124 q.put(None) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
125 # check hasn't exited |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
126 assert r.poll() == None |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
127 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
128 # read the response |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
129 assert readall_socket(c) == dat1 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
130 c.close() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
131 assert tcp.inbound() == dat2 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
132 # check has exited, allow time for dbclient to exit |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
133 time.sleep(0.1) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
134 assert r.poll() == 0 |