annotate test/test_dropbear.py @ 1836:06c7ddbb9dd6

Add first channel tests These initial tests are checking various edge cases of channel handling that have cropped up over the years.
author Matt Johnston <matt@codeconstruct.com.au>
date Mon, 18 Oct 2021 14:22:37 +0800
parents
children d757f48ae29f
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
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
22 args = [opt.dropbear,
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
23 "-p", LOCALADDR, # bind locally only
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
24 "-r", opt.hostkey,
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
25 "-p", opt.port,
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
26 "-F", "-E",
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
27 ]
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
28 p = subprocess.Popen(args, stderr=subprocess.PIPE, text=True)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
29 # Wait until it has started listening
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
30 for l in p.stderr:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
31 if "Not backgrounding" in l:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
32 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
33 # Check it's still running
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
34 assert p.poll() is None
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
35 # Ready
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
36 yield p
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
37 p.terminate()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
38
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
39 def dbclient(request, *args, **kwargs):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
40 opt = request.config.option
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
41 host = opt.remote or LOCALADDR
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
42 base_args = [opt.dbclient, "-y", host, "-p", opt.port]
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
43 if opt.user:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
44 full_args.extend(['-l', opt.user])
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
45 full_args = base_args + list(args)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
46 bg = kwargs.get("background")
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
47 if "background" in kwargs:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
48 del kwargs["background"]
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
49 if bg:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
50 return subprocess.Popen(full_args, **kwargs)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
51 else:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
52 # wait for response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
53 return subprocess.run(full_args, **kwargs)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
54
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
55 class HandleTcp(socketserver.ThreadingMixIn, socketserver.TCPServer):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
56 """ 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
57 and returns the inbound data.
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
58 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
59 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
60 """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
61 def __init__(self, port, timeout, response=None):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
62 super().__init__(('localhost', port), self.Handler)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
63 self.port = port
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
64 self.timeout = timeout
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
65 self.response = response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
66 self.sink = None
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
67
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
68 class Handler(socketserver.StreamRequestHandler):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
69 def handle(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
70 if isinstance(self.server.response, queue.Queue):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
71 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
72 i = self.server.response.get()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
73 if i is None:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
74 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
75 self.wfile.write(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
76 elif self.server.response:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
77 self.wfile.write(self.server.response)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
78 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
79 self.server.sink = self.rfile.read()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
80
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
81 def __enter__(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
82 self.server_thread = threading.Thread(target=self.serve_forever)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
83 self.server_thread.daemon = True
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
84 self.server_thread.start()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
85 return self
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 def __exit__(self, *exc_stuff):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
88 self.shutdown()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
89 self.server_thread.join()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
90
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
91 def inbound(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
92 """ Returns the data sent to the socket """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
93 return self.sink
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
94
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
95 def readall_socket(sock):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
96 b = []
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
97 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
98 i = sock.recv(4096)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
99 if not i:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
100 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
101 b.append(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
102 return b''.join(b)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
103
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
104 # returns a str
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
105 def random_alnum(size):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
106 r = os.urandom(500 + size*5)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
107 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
108
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
109