annotate test/test_dropbear.py @ 1874:1c9215154d4a

Handle /proc/.../maps being reordered We now search for the first r-xp line in the file
author Matt Johnston <matt@ucc.asn.au>
date Thu, 03 Feb 2022 22:13:06 +0800
parents 0dcc5b0d93fa
children 81991ded740f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
1 import subprocess
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
2 import os
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
3 import pty
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
4 import tempfile
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
5 import logging
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
6 import time
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
7 import socketserver
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
8 import threading
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
9 import queue
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
10
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
11 import pytest
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
12
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
13 LOCALADDR="127.0.5.5"
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
14
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
15 @pytest.fixture(scope="module")
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
16 def dropbear(request):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
17 opt = request.config.option
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
18 if opt.remote:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
19 yield None
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
20 return
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
21
1870
0dcc5b0d93fa Make re-exec work with "dropbearmulti dropbear"
Matt Johnston <matt@ucc.asn.au>
parents: 1864
diff changeset
22 # split so that "dropbearmulti dropbear" works
0dcc5b0d93fa Make re-exec work with "dropbearmulti dropbear"
Matt Johnston <matt@ucc.asn.au>
parents: 1864
diff changeset
23 args = opt.dropbear.split() + [
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
24 "-p", LOCALADDR, # bind locally only
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
25 "-r", opt.hostkey,
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
26 "-p", opt.port,
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
27 "-F", "-E",
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
28 ]
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
29 p = subprocess.Popen(args, stderr=subprocess.PIPE, text=True)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
30 # Wait until it has started listening
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
31 for l in p.stderr:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
32 if "Not backgrounding" in l:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
33 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
34 # Check it's still running
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
35 assert p.poll() is None
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
36 # Ready
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
37 yield p
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
38 p.terminate()
1852
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
39 print("Terminated dropbear. Flushing output:")
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
40 for l in p.stderr:
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
41 print(l.rstrip())
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
42 print("Done")
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
43
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
44 def dbclient(request, *args, **kwargs):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
45 opt = request.config.option
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
46 host = opt.remote or LOCALADDR
1870
0dcc5b0d93fa Make re-exec work with "dropbearmulti dropbear"
Matt Johnston <matt@ucc.asn.au>
parents: 1864
diff changeset
47 # split so that "dropbearmulti dbclient" works
0dcc5b0d93fa Make re-exec work with "dropbearmulti dropbear"
Matt Johnston <matt@ucc.asn.au>
parents: 1864
diff changeset
48 base_args = opt.dbclient.split() + ["-y", host, "-p", opt.port]
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
49 if opt.user:
1870
0dcc5b0d93fa Make re-exec work with "dropbearmulti dropbear"
Matt Johnston <matt@ucc.asn.au>
parents: 1864
diff changeset
50 base_args.extend(['-l', opt.user])
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
51 full_args = base_args + list(args)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
52 bg = kwargs.get("background")
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
53 if "background" in kwargs:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
54 del kwargs["background"]
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
55 if bg:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
56 return subprocess.Popen(full_args, **kwargs)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
57 else:
1841
d757f48ae29f Add a default 10 second timeout for tests
Matt Johnston <matt@ucc.asn.au>
parents: 1836
diff changeset
58 kwargs.setdefault("timeout", 10)
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
59 # wait for response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
60 return subprocess.run(full_args, **kwargs)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
61
1863
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
62 def own_venv_command():
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
63 """ Returns a command to run as a prefix to get the same venv
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
64 as the current running Python. Returns '' on not a virtualenv
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
65 """
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
66 try:
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
67 venv = os.environ['VIRTUAL_ENV']
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
68 except KeyError:
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
69 return ""
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
70
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
71 # note: bash/zsh unix specific
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
72 return f"source {venv}/bin/activate"
b550845e500b Use venv for test_aslr
Matt Johnston <matt@ucc.asn.au>
parents: 1852
diff changeset
73
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
74 class HandleTcp(socketserver.ThreadingMixIn, socketserver.TCPServer):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
75 """ Listens for a single incoming request, sends a response if given,
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
76 and returns the inbound data.
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
77 Reponse can be a queue object, in which case each item in the queue will
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
78 be sent as a response, until it receives a None item.
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
79 """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
80 def __init__(self, port, timeout, response=None):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
81 super().__init__(('localhost', port), self.Handler)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
82 self.port = port
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
83 self.timeout = timeout
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
84 self.response = response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
85 self.sink = None
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
86
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
87 class Handler(socketserver.StreamRequestHandler):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
88 def handle(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
89 if isinstance(self.server.response, queue.Queue):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
90 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
91 i = self.server.response.get()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
92 if i is None:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
93 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
94 self.wfile.write(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
95 elif self.server.response:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
96 self.wfile.write(self.server.response)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
97 assert self.server.sink is None, ">1 request sent to handler"
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
98 self.server.sink = self.rfile.read()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
99
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
100 def __enter__(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
101 self.server_thread = threading.Thread(target=self.serve_forever)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
102 self.server_thread.daemon = True
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
103 self.server_thread.start()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
104 return self
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
105
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
106 def __exit__(self, *exc_stuff):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
107 self.shutdown()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
108 self.server_thread.join()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
109
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
110 def inbound(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
111 """ Returns the data sent to the socket """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
112 return self.sink
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 def readall_socket(sock):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
115 b = []
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
116 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
117 i = sock.recv(4096)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
118 if not i:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
119 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
120 b.append(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
121 return b''.join(b)
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 # returns a str
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
124 def random_alnum(size):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
125 r = os.urandom(500 + size*5)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
126 return bytes(i for i in r if bytes((i,)).isalnum())[:size].decode()
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