annotate test/test_dropbear.py @ 1851:7f549ee3df48

Use HOME before /etc/passwd to find id_dropbear (#137) Currently dbclient uses the value of HOME by default when looking for ~/.ssh/known_hosts, falling back to /etc/passwd if HOME is not set (so that people can work around broken values in /etc/passwd). However, when locating the default authentication key (defaults to ~/.ssh/id_dropbear), paths not starting with / are always prefixed with the value from /etc/passwd. Make the behaviour consistent by adjusting expand_homedir_path to use the value of HOME, falling back to /etc/passwd if HOME is not set.
author Matt Robinson <git@nerdoftheherd.com>
date Tue, 19 Oct 2021 06:02:47 +0100
parents d757f48ae29f
children e0c1825c567d
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:
1841
d757f48ae29f Add a default 10 second timeout for tests
Matt Johnston <matt@ucc.asn.au>
parents: 1836
diff changeset
52 kwargs.setdefault("timeout", 10)
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
53 # wait for response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
54 return subprocess.run(full_args, **kwargs)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
55
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
56 class HandleTcp(socketserver.ThreadingMixIn, socketserver.TCPServer):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
57 """ 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
58 and returns the inbound data.
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
59 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
60 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
61 """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
62 def __init__(self, port, timeout, response=None):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
63 super().__init__(('localhost', port), self.Handler)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
64 self.port = port
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
65 self.timeout = timeout
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
66 self.response = response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
67 self.sink = None
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
68
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
69 class Handler(socketserver.StreamRequestHandler):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
70 def handle(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
71 if isinstance(self.server.response, queue.Queue):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
72 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
73 i = self.server.response.get()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
74 if i is None:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
75 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
76 self.wfile.write(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
77 elif self.server.response:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
78 self.wfile.write(self.server.response)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
79 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
80 self.server.sink = self.rfile.read()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
81
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
82 def __enter__(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
83 self.server_thread = threading.Thread(target=self.serve_forever)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
84 self.server_thread.daemon = True
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
85 self.server_thread.start()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
86 return self
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
87
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
88 def __exit__(self, *exc_stuff):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
89 self.shutdown()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
90 self.server_thread.join()
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 def inbound(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
93 """ Returns the data sent to the socket """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
94 return self.sink
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
95
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
96 def readall_socket(sock):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
97 b = []
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
98 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
99 i = sock.recv(4096)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
100 if not i:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
101 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
102 b.append(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
103 return b''.join(b)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
104
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
105 # returns a str
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
106 def random_alnum(size):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
107 r = os.urandom(500 + size*5)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
108 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
109
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
110