annotate test/test_dropbear.py @ 1855:35d504d59c05

Implement server-side support for sk-ecdsa U2F-backed keys (#142) * Implement server-side support for sk-ecdsa U2F-backed keys * Fix out-of-bounds read on normal ecdsa-sha2-[identifier] keys * Fix one more potential out-of-bounds read * Check if nistp256 curve is used in sk-ecdsa-sha2- key It's the only allowed curve per PROTOCOL.u2f specification * Implement server-side support for sk-ed25519 FIDO2-backed keys * Keys with type sk-* make no sense as host keys, so they should be disabled * fix typo * Make sk-ecdsa call buf_ecdsa_verify This reduces code duplication, the SK code just handles the different message format. * Reduce sk specific code The application id can be stored in signkey, then we don't need to call sk-specific functions from svr-authpubkey * Remove debugging output, which causes compilation errors with DEBUG_TRACE disabled * Proper cleanup of sk_app Co-authored-by: Matt Johnston <[email protected]>
author egor-duda <egor-duda@users.noreply.github.com>
date Sat, 22 Jan 2022 16:53:04 +0300
parents e0c1825c567d
children b550845e500b
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()
1852
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
38 print("Terminated dropbear. Flushing output:")
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
39 for l in p.stderr:
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
40 print(l.rstrip())
e0c1825c567d Debug pytest password auth failing
Matt Johnston <matt@ucc.asn.au>
parents: 1841
diff changeset
41 print("Done")
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
42
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
43 def dbclient(request, *args, **kwargs):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
44 opt = request.config.option
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
45 host = opt.remote or LOCALADDR
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
46 base_args = [opt.dbclient, "-y", host, "-p", opt.port]
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
47 if opt.user:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
48 full_args.extend(['-l', opt.user])
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
49 full_args = base_args + list(args)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
50 bg = kwargs.get("background")
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
51 if "background" in kwargs:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
52 del kwargs["background"]
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
53 if bg:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
54 return subprocess.Popen(full_args, **kwargs)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
55 else:
1841
d757f48ae29f Add a default 10 second timeout for tests
Matt Johnston <matt@ucc.asn.au>
parents: 1836
diff changeset
56 kwargs.setdefault("timeout", 10)
1836
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
57 # wait for response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
58 return subprocess.run(full_args, **kwargs)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
59
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
60 class HandleTcp(socketserver.ThreadingMixIn, socketserver.TCPServer):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
61 """ 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
62 and returns the inbound data.
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
63 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
64 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
65 """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
66 def __init__(self, port, timeout, response=None):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
67 super().__init__(('localhost', port), self.Handler)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
68 self.port = port
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
69 self.timeout = timeout
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
70 self.response = response
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
71 self.sink = None
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
72
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
73 class Handler(socketserver.StreamRequestHandler):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
74 def handle(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
75 if isinstance(self.server.response, queue.Queue):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
76 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
77 i = self.server.response.get()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
78 if i is None:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
79 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
80 self.wfile.write(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
81 elif self.server.response:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
82 self.wfile.write(self.server.response)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
83 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
84 self.server.sink = self.rfile.read()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
85
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
86 def __enter__(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
87 self.server_thread = threading.Thread(target=self.serve_forever)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
88 self.server_thread.daemon = True
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
89 self.server_thread.start()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
90 return self
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 __exit__(self, *exc_stuff):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
93 self.shutdown()
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
94 self.server_thread.join()
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 inbound(self):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
97 """ Returns the data sent to the socket """
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
98 return self.sink
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 readall_socket(sock):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
101 b = []
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
102 while True:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
103 i = sock.recv(4096)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
104 if not i:
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
105 break
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
106 b.append(i)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
107 return b''.join(b)
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 # returns a str
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
110 def random_alnum(size):
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
111 r = os.urandom(500 + size*5)
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
112 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
113
06c7ddbb9dd6 Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff changeset
114