1 # Unix SMB/CIFS implementation.
3 # Copyright (C) Samuel Cabrero <scabrero@suse.de> 2018
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 from subprocess import Popen, PIPE
21 from samba.tests.ntlm_auth_base import NTLMAuthTestCase
22 from samba.compat import get_string
24 class NTLMAuthHelpersTests(NTLMAuthTestCase):
27 super(NTLMAuthHelpersTests, self).setUp()
28 self.username = os.environ["DC_USERNAME"]
29 self.password = os.environ["DC_PASSWORD"]
30 self.domain = os.environ["DOMAIN"]
31 out = get_string(self.check_output("wbinfo -n %s" % self.username))
32 self.group_sid = out.split(" ")[0]
33 self.assertTrue(self.group_sid.startswith("S-1-5-21-"))
34 self.bad_group_sid = self.group_sid[:-2]
36 def test_specified_domain(self):
37 """ ntlm_auth with specified domain """
43 ret = self.run_helper(client_username=username,
44 client_password=password,
46 server_username=username,
47 server_password=password,
49 server_use_winbind=False)
56 ret = self.run_helper(client_username=username,
57 client_password=password,
59 server_username=username,
60 server_password=password,
62 server_use_winbind=False)
65 def test_agaist_winbind(self):
66 """ ntlm_auth against winbindd """
68 ret = self.run_helper(client_username=self.username,
69 client_password=self.password,
70 client_domain=self.domain,
71 server_use_winbind=True)
74 def test_ntlmssp_gss_spnego(self):
75 """ ntlm_auth with NTLMSSP client and gss-spnego server """
81 ret = self.run_helper(client_username=username,
82 client_password=password,
84 server_username=username,
85 server_password=password,
87 client_helper="ntlmssp-client-1",
88 server_helper="gss-spnego",
89 server_use_winbind=False)
92 def test_gss_spnego(self):
93 """ ntlm_auth with NTLMSSP gss-spnego-client and gss-spnego server """
99 ret = self.run_helper(client_username=username,
100 client_password=password,
101 client_domain=domain,
102 server_username=username,
103 server_password=password,
104 server_domain=domain,
105 client_helper="gss-spnego-client",
106 server_helper="gss-spnego",
107 server_use_winbind=False)
110 def test_gss_spnego_winbind(self):
111 """ ntlm_auth with NTLMSSP gss-spnego-client and gss-spnego server
114 ret = self.run_helper(client_username=self.username,
115 client_password=self.password,
116 client_domain=self.domain,
117 client_helper="gss-spnego-client",
118 server_helper="gss-spnego",
119 server_use_winbind=True)
122 def test_ntlmssp_gss_spnego_cached_creds(self):
123 """ ntlm_auth with NTLMSSP client and gss-spnego server against
124 winbind with cached credentials """
126 param = "--ccache-save=%s%s%s%%%s" % (self.domain,
127 self.winbind_separator,
130 cache_cmd = ["wbinfo",
132 self.check_exit_code(cache_cmd, 0)
134 ret = self.run_helper(client_username=self.username,
135 client_password=self.password,
136 client_domain=self.domain,
137 client_use_cached_creds=True,
138 client_helper="ntlmssp-client-1",
139 server_helper="gss-spnego",
140 server_use_winbind=True)
143 def test_require_membership(self):
144 """ ntlm_auth against winbindd with require-membership-of """
146 ret = self.run_helper(client_username=self.username,
147 client_password=self.password,
148 client_domain=self.domain,
149 require_membership=self.group_sid,
150 server_use_winbind=True)
153 ret = self.run_helper(client_username=self.username,
154 client_password=self.password,
155 client_domain=self.domain,
156 require_membership=self.bad_group_sid,
157 server_use_winbind=True)
158 self.assertFalse(ret)
160 def test_require_membership_gss_spnego(self):
161 """ ntlm_auth with NTLMSSP gss-spnego-client and gss-spnego server
162 against winbind with require-membership-of """
164 ret = self.run_helper(client_username=self.username,
165 client_password=self.password,
166 client_domain=self.domain,
167 require_membership=self.group_sid,
168 client_helper="gss-spnego-client",
169 server_helper="gss-spnego",
170 server_use_winbind=True)
173 ret = self.run_helper(client_username=self.username,
174 client_password=self.password,
175 client_domain=self.domain,
176 require_membership=self.bad_group_sid,
177 client_helper="gss-spnego-client",
178 server_helper="gss-spnego",
179 server_use_winbind=True)
180 self.assertFalse(ret)
182 def test_plaintext_with_membership(self):
183 """ ntlm_auth plaintext authentication with require-membership-of """
185 proc = Popen([self.ntlm_auth_path,
186 "--require-membership-of", self.group_sid,
187 "--helper-protocol", "squid-2.5-basic"],
188 stdout=PIPE, stdin=PIPE, stderr=PIPE)
189 creds = "%s%s%s %s\n" % (self.domain, self.winbind_separator,
192 (out, err) = proc.communicate(input=creds.encode('utf-8'))
193 self.assertEqual(proc.returncode, 0)
194 self.assertTrue(out.startswith(b"OK\n"))
196 # Check membership failure
197 proc = Popen([self.ntlm_auth_path,
198 "--require-membership-of", self.bad_group_sid,
199 "--helper-protocol", "squid-2.5-basic"],
200 stdout=PIPE, stdin=PIPE, stderr=PIPE)
201 creds = "%s%s%s %s\n" % (self.domain,
202 self.winbind_separator,
205 (out, err) = proc.communicate(input=creds.encode('utf-8'))
206 self.assertEqual(proc.returncode, 0)
207 self.assertTrue(out.startswith(b"ERR\n"))
209 def test_ntlm_server_1_with_fixed_password(self):
210 """ ntlm_auth ntlm-server-1 with fixed password """
213 "LANMAN-Challenge: 0123456789abcdef",
214 "NT-Response: 25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6",
216 "Username: testuser",
217 "Request-User-Session-Key: Yes",
220 proc = Popen([self.ntlm_auth_path,
221 "--password", "SecREt01",
222 "--helper-protocol", "ntlm-server-1"],
223 stdout=PIPE, stdin=PIPE, stderr=PIPE)
224 buf = "\n".join(ntlm_cmds)
225 (out, err) = proc.communicate(input=buf.encode('utf-8'))
226 self.assertEqual(proc.returncode, 0)
228 lines = out.split(b"\n")
230 self.assertEqual(len(lines), 4)
231 self.assertEquals(lines[0], b"Authenticated: Yes")
233 lines[1], b"User-Session-Key: 3F373EA8E4AF954F14FAA506F8EEBDC4")
234 self.assertEquals(lines[2], b".")
235 self.assertEquals(lines[3], b"")
237 # Break the password with a leading A on the challenge
238 ntlm_cmds[0] = "LANMAN-Challenge: A123456789abcdef"
240 proc = Popen([self.ntlm_auth_path,
241 "--password", "SecREt01",
242 "--helper-protocol", "ntlm-server-1"],
243 stdout=PIPE, stdin=PIPE, stderr=PIPE)
244 buf = "\n".join(ntlm_cmds)
245 (out, err) = proc.communicate(input=buf.encode('utf-8'))
246 self.assertEqual(proc.returncode, 0)
248 lines = out.split(b"\n")
249 self.assertEqual(len(lines), 5)
250 self.assertEquals(lines[0], b"Authenticated: No")
252 def test_ntlm_server_1_with_plaintext_winbind(self):
253 """ ntlm_auth ntlm-server-1 with plaintext password against winbind """
256 "Password: %s" % self.password,
257 "NT-Domain: %s" % self.domain,
258 "Username: %s" % self.username,
259 "Request-User-Session-Key: Yes",
262 proc = Popen([self.ntlm_auth_path,
263 "--require-membership-of", self.group_sid,
264 "--helper-protocol", "ntlm-server-1"],
265 stdout=PIPE, stdin=PIPE, stderr=PIPE)
266 buf = "\n".join(ntlm_cmds)
267 (out, err) = proc.communicate(input=buf.encode('utf-8'))
268 self.assertEqual(proc.returncode, 0)
270 lines = out.split(b"\n")
272 self.assertEqual(len(lines), 3)
273 self.assertEquals(lines[0], b"Authenticated: Yes")
274 self.assertEquals(lines[1], b".")
275 self.assertEquals(lines[2], b"")
277 # Check membership failure
279 proc = Popen([self.ntlm_auth_path,
280 "--require-membership-of", self.bad_group_sid,
281 "--helper-protocol", "ntlm-server-1"],
282 stdout=PIPE, stdin=PIPE, stderr=PIPE)
283 buf = "\n".join(ntlm_cmds)
284 (out, err) = proc.communicate(input=buf.encode('utf-8'))
285 self.assertEqual(proc.returncode, 0)
287 lines = out.split(b"\n")
289 self.assertEqual(len(lines), 3)
290 self.assertEquals(lines[0], b"Authenticated: No")
291 self.assertEquals(lines[1], b".")
292 self.assertEquals(lines[2], b"")