Mercurial > dropbear
annotate test/test_dropbear.py @ 1930:299f4f19ba19
Add /usr/sbin and /sbin to default root PATH
When dropbear is used in a very restricted environment (such as in a
initrd), the default user shell is often also very restricted
and doesn't take care of setting the PATH so the user ends up
with the PATH set by dropbear. Unfortunately, dropbear always
sets "/usr/bin:/bin" as default PATH even for the root user
which should have /usr/sbin and /sbin too.
For a concrete instance of this problem, see the "Remote Unlocking"
section in this tutorial: https://paxswill.com/blog/2013/11/04/encrypted-raspberry-pi/
It speaks of a bug in the initramfs script because it's written "blkid"
instead of "/sbin/blkid"... this is just because the scripts from the
initramfs do not expect to have a PATH without the sbin directories and
because dropbear is not setting the PATH appropriately for the root user.
I'm thus suggesting to use the attached patch to fix this misbehaviour (I
did not test it, but it's easy enough). It might seem anecdotic but
multiple Kali users have been bitten by this.
From https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=903403
author | Raphael Hertzog <hertzog@debian.org> |
---|---|
date | Mon, 09 Jul 2018 16:27:53 +0200 |
parents | 81991ded740f |
children |
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 | 62 def own_venv_command(): |
63 """ Returns a command to run as a prefix to get the same venv | |
64 as the current running Python. Returns '' on not a virtualenv | |
65 """ | |
66 try: | |
67 venv = os.environ['VIRTUAL_ENV'] | |
68 except KeyError: | |
69 return "" | |
70 | |
71 # note: bash/zsh unix specific | |
72 return f"source {venv}/bin/activate" | |
73 | |
1836
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
74 class HandleTcp(socketserver.ThreadingMixIn, socketserver.TCPServer): |
1879
81991ded740f
test: Set allow_reuse_addr
Matt Johnston <matt@ucc.asn.au>
parents:
1870
diff
changeset
|
75 |
81991ded740f
test: Set allow_reuse_addr
Matt Johnston <matt@ucc.asn.au>
parents:
1870
diff
changeset
|
76 # override TCPServer's default, avoids TIME_WAIT |
81991ded740f
test: Set allow_reuse_addr
Matt Johnston <matt@ucc.asn.au>
parents:
1870
diff
changeset
|
77 allow_reuse_addr = True |
81991ded740f
test: Set allow_reuse_addr
Matt Johnston <matt@ucc.asn.au>
parents:
1870
diff
changeset
|
78 |
1836
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
79 """ 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
|
80 and returns the inbound data. |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
81 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
|
82 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
|
83 """ |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
84 def __init__(self, port, timeout, response=None): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
85 super().__init__(('localhost', port), self.Handler) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
86 self.port = port |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
87 self.timeout = timeout |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
88 self.response = response |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
89 self.sink = None |
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 class Handler(socketserver.StreamRequestHandler): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
92 def handle(self): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
93 if isinstance(self.server.response, queue.Queue): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
94 while True: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
95 i = self.server.response.get() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
96 if i is None: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
97 break |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
98 self.wfile.write(i) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
99 elif self.server.response: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
100 self.wfile.write(self.server.response) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
101 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
|
102 self.server.sink = self.rfile.read() |
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 def __enter__(self): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
105 self.server_thread = threading.Thread(target=self.serve_forever) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
106 self.server_thread.daemon = True |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
107 self.server_thread.start() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
108 return self |
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 __exit__(self, *exc_stuff): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
111 self.shutdown() |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
112 self.server_thread.join() |
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 inbound(self): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
115 """ Returns the data sent to the socket """ |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
116 return self.sink |
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 def readall_socket(sock): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
119 b = [] |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
120 while True: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
121 i = sock.recv(4096) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
122 if not i: |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
123 break |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
124 b.append(i) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
125 return b''.join(b) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
126 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
127 # returns a str |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
128 def random_alnum(size): |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
129 r = os.urandom(500 + size*5) |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
130 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
|
131 |
06c7ddbb9dd6
Add first channel tests
Matt Johnston <matt@codeconstruct.com.au>
parents:
diff
changeset
|
132 |