Line data Source code
1 : /*
2 : * Unit tests for the ntlm_check password hash check library.
3 : *
4 : * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 3 of the License, or
9 : * (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : *
19 : */
20 :
21 : /*
22 : * from cmocka.c:
23 : * These headers or their equivalents should be included prior to
24 : * including
25 : * this header file.
26 : *
27 : * #include <stdarg.h>
28 : * #include <stddef.h>
29 : * #include <setjmp.h>
30 : *
31 : * This allows test applications to use custom definitions of C standard
32 : * library functions and types.
33 : *
34 : */
35 :
36 : /*
37 : * Note that the messaging routines (audit_message_send and get_event_server)
38 : * are not tested by these unit tests. Currently they are for integration
39 : * test support, and as such are exercised by the integration tests.
40 : */
41 : #include <stdarg.h>
42 : #include <stddef.h>
43 : #include <stdint.h>
44 : #include <setjmp.h>
45 : #include <cmocka.h>
46 :
47 : #include "includes.h"
48 : #include "librpc/gen_ndr/netlogon.h"
49 : #include "libcli/auth/libcli_auth.h"
50 : #include "auth/credentials/credentials.h"
51 :
52 : struct ntlm_state {
53 : const char *username;
54 : const char *domain;
55 : DATA_BLOB challenge;
56 : DATA_BLOB ntlm;
57 : DATA_BLOB lm;
58 : DATA_BLOB ntlm_key;
59 : DATA_BLOB lm_key;
60 : const struct samr_Password *nt_hash;
61 : };
62 :
63 10 : static int test_ntlm_setup_with_options(void **state,
64 : int flags, bool upn)
65 : {
66 10 : NTSTATUS status;
67 10 : DATA_BLOB challenge = {
68 : .data = discard_const_p(uint8_t, "I am a teapot"),
69 : .length = 8
70 : };
71 10 : struct ntlm_state *ntlm_state = talloc(NULL, struct ntlm_state);
72 10 : DATA_BLOB target_info = NTLMv2_generate_names_blob(ntlm_state,
73 : NULL,
74 : "serverdom");
75 10 : struct cli_credentials *creds = cli_credentials_init(ntlm_state);
76 10 : cli_credentials_set_username(creds,
77 : "testuser",
78 : CRED_SPECIFIED);
79 10 : cli_credentials_set_domain(creds,
80 : "testdom",
81 : CRED_SPECIFIED);
82 10 : cli_credentials_set_workstation(creds,
83 : "testwksta",
84 : CRED_SPECIFIED);
85 10 : cli_credentials_set_password(creds,
86 : "testpass",
87 : CRED_SPECIFIED);
88 :
89 10 : if (upn) {
90 0 : cli_credentials_set_principal(creds,
91 : "testuser@samba.org",
92 : CRED_SPECIFIED);
93 : }
94 :
95 10 : cli_credentials_get_ntlm_username_domain(creds,
96 : ntlm_state,
97 : &ntlm_state->username,
98 : &ntlm_state->domain);
99 :
100 10 : status = cli_credentials_get_ntlm_response(creds,
101 : ntlm_state,
102 : &flags,
103 : challenge,
104 : NULL,
105 : target_info,
106 : &ntlm_state->lm,
107 : &ntlm_state->ntlm,
108 : &ntlm_state->lm_key,
109 : &ntlm_state->ntlm_key);
110 10 : ntlm_state->challenge = challenge;
111 :
112 10 : ntlm_state->nt_hash = cli_credentials_get_nt_hash(creds,
113 : ntlm_state);
114 :
115 10 : if (!NT_STATUS_IS_OK(status)) {
116 : return -1;
117 : }
118 :
119 10 : *state = ntlm_state;
120 10 : return 0;
121 : }
122 :
123 6 : static int test_ntlm_setup(void **state) {
124 6 : return test_ntlm_setup_with_options(state, 0, false);
125 : }
126 :
127 2 : static int test_ntlm_and_lm_setup(void **state) {
128 2 : return test_ntlm_setup_with_options(state,
129 : CLI_CRED_LANMAN_AUTH,
130 : false);
131 : }
132 :
133 1 : static int test_ntlm2_setup(void **state) {
134 1 : return test_ntlm_setup_with_options(state,
135 : CLI_CRED_NTLM2,
136 : false);
137 : }
138 :
139 1 : static int test_ntlmv2_setup(void **state) {
140 1 : return test_ntlm_setup_with_options(state,
141 : CLI_CRED_NTLMv2_AUTH,
142 : false);
143 : }
144 :
145 10 : static int test_ntlm_teardown(void **state)
146 : {
147 10 : struct ntlm_state *ntlm_state
148 10 : = talloc_get_type_abort(*state,
149 : struct ntlm_state);
150 10 : TALLOC_FREE(ntlm_state);
151 10 : *state = NULL;
152 10 : return 0;
153 : }
154 :
155 2 : static void test_ntlm_allowed(void **state)
156 : {
157 2 : DATA_BLOB user_sess_key, lm_sess_key;
158 2 : struct ntlm_state *ntlm_state
159 2 : = talloc_get_type_abort(*state,
160 : struct ntlm_state);
161 2 : NTSTATUS status;
162 2 : status = ntlm_password_check(ntlm_state,
163 : false,
164 : NTLM_AUTH_ON,
165 : 0,
166 2 : &ntlm_state->challenge,
167 2 : &ntlm_state->lm,
168 2 : &ntlm_state->ntlm,
169 : ntlm_state->username,
170 : ntlm_state->username,
171 : ntlm_state->domain,
172 : NULL,
173 : ntlm_state->nt_hash,
174 : &user_sess_key,
175 : &lm_sess_key);
176 :
177 2 : assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_OK));
178 2 : }
179 :
180 1 : static void test_ntlm_allowed_lm_supplied(void **state)
181 : {
182 1 : test_ntlm_allowed(state);
183 1 : }
184 :
185 1 : static void test_ntlm_disabled(void **state)
186 : {
187 1 : DATA_BLOB user_sess_key, lm_sess_key;
188 1 : struct ntlm_state *ntlm_state
189 1 : = talloc_get_type_abort(*state,
190 : struct ntlm_state);
191 1 : NTSTATUS status;
192 1 : status = ntlm_password_check(ntlm_state,
193 : false,
194 : NTLM_AUTH_DISABLED,
195 : 0,
196 1 : &ntlm_state->challenge,
197 1 : &ntlm_state->lm,
198 1 : &ntlm_state->ntlm,
199 : ntlm_state->username,
200 : ntlm_state->username,
201 : ntlm_state->domain,
202 : NULL,
203 : ntlm_state->nt_hash,
204 : &user_sess_key,
205 : &lm_sess_key);
206 :
207 1 : assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_NTLM_BLOCKED));
208 1 : }
209 :
210 1 : static void test_ntlm2(void **state)
211 : {
212 1 : DATA_BLOB user_sess_key, lm_sess_key;
213 1 : struct ntlm_state *ntlm_state
214 1 : = talloc_get_type_abort(*state,
215 : struct ntlm_state);
216 1 : NTSTATUS status;
217 1 : status = ntlm_password_check(ntlm_state,
218 : false,
219 : NTLM_AUTH_ON,
220 : 0,
221 1 : &ntlm_state->challenge,
222 1 : &ntlm_state->lm,
223 1 : &ntlm_state->ntlm,
224 : ntlm_state->username,
225 : ntlm_state->username,
226 : ntlm_state->domain,
227 : NULL,
228 : ntlm_state->nt_hash,
229 : &user_sess_key,
230 : &lm_sess_key);
231 :
232 : /*
233 : * NTLM2 session security (where the real challenge is the
234 : * MD5(challenge, client-challenge) (in the first 8 bytes of
235 : * the lm) isn't decoded by ntlm_password_check(), it must
236 : * first be converted back into normal NTLM by the NTLMSSP
237 : * layer
238 : */
239 1 : assert_int_equal(NT_STATUS_V(status),
240 : NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
241 1 : }
242 :
243 1 : static void test_ntlm_mschapv2_only_allowed(void **state)
244 : {
245 1 : DATA_BLOB user_sess_key, lm_sess_key;
246 1 : struct ntlm_state *ntlm_state
247 1 : = talloc_get_type_abort(*state,
248 : struct ntlm_state);
249 1 : NTSTATUS status;
250 1 : status = ntlm_password_check(ntlm_state,
251 : false,
252 : NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY,
253 : MSV1_0_ALLOW_MSVCHAPV2,
254 1 : &ntlm_state->challenge,
255 1 : &ntlm_state->lm,
256 1 : &ntlm_state->ntlm,
257 : ntlm_state->username,
258 : ntlm_state->username,
259 : ntlm_state->domain,
260 : NULL,
261 : ntlm_state->nt_hash,
262 : &user_sess_key,
263 : &lm_sess_key);
264 :
265 1 : assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_OK));
266 1 : }
267 :
268 1 : static void test_ntlm_mschapv2_only_denied(void **state)
269 : {
270 1 : DATA_BLOB user_sess_key, lm_sess_key;
271 1 : struct ntlm_state *ntlm_state
272 1 : = talloc_get_type_abort(*state,
273 : struct ntlm_state);
274 1 : NTSTATUS status;
275 1 : status = ntlm_password_check(ntlm_state,
276 : false,
277 : NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY,
278 : 0,
279 1 : &ntlm_state->challenge,
280 1 : &ntlm_state->lm,
281 1 : &ntlm_state->ntlm,
282 : ntlm_state->username,
283 : ntlm_state->username,
284 : ntlm_state->domain,
285 : NULL,
286 : ntlm_state->nt_hash,
287 : &user_sess_key,
288 : &lm_sess_key);
289 :
290 1 : assert_int_equal(NT_STATUS_V(status),
291 : NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
292 1 : }
293 :
294 1 : static void test_ntlmv2_only_ntlmv2(void **state)
295 : {
296 1 : DATA_BLOB user_sess_key, lm_sess_key;
297 1 : struct ntlm_state *ntlm_state
298 1 : = talloc_get_type_abort(*state,
299 : struct ntlm_state);
300 1 : NTSTATUS status;
301 1 : status = ntlm_password_check(ntlm_state,
302 : false,
303 : NTLM_AUTH_NTLMV2_ONLY,
304 : 0,
305 1 : &ntlm_state->challenge,
306 1 : &ntlm_state->lm,
307 1 : &ntlm_state->ntlm,
308 : ntlm_state->username,
309 : ntlm_state->username,
310 : ntlm_state->domain,
311 : NULL,
312 : ntlm_state->nt_hash,
313 : &user_sess_key,
314 : &lm_sess_key);
315 :
316 1 : assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_OK));
317 1 : }
318 :
319 2 : static void test_ntlmv2_only_ntlm(void **state)
320 : {
321 2 : DATA_BLOB user_sess_key, lm_sess_key;
322 2 : struct ntlm_state *ntlm_state
323 2 : = talloc_get_type_abort(*state,
324 : struct ntlm_state);
325 2 : NTSTATUS status;
326 2 : status = ntlm_password_check(ntlm_state,
327 : false,
328 : NTLM_AUTH_NTLMV2_ONLY,
329 : 0,
330 2 : &ntlm_state->challenge,
331 2 : &ntlm_state->lm,
332 2 : &ntlm_state->ntlm,
333 : ntlm_state->username,
334 : ntlm_state->username,
335 : ntlm_state->domain,
336 : NULL,
337 : ntlm_state->nt_hash,
338 : &user_sess_key,
339 : &lm_sess_key);
340 :
341 2 : assert_int_equal(NT_STATUS_V(status),
342 : NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
343 2 : }
344 :
345 1 : static void test_ntlmv2_only_ntlm_and_lanman(void **state)
346 : {
347 1 : test_ntlmv2_only_ntlm(state);
348 1 : }
349 :
350 1 : static void test_ntlmv2_only_ntlm_once(void **state)
351 : {
352 1 : DATA_BLOB user_sess_key, lm_sess_key;
353 1 : struct ntlm_state *ntlm_state
354 1 : = talloc_get_type_abort(*state,
355 : struct ntlm_state);
356 1 : NTSTATUS status;
357 1 : status = ntlm_password_check(ntlm_state,
358 : false,
359 : NTLM_AUTH_NTLMV2_ONLY,
360 : 0,
361 1 : &ntlm_state->challenge,
362 : &data_blob_null,
363 1 : &ntlm_state->ntlm,
364 : ntlm_state->username,
365 : ntlm_state->username,
366 : ntlm_state->domain,
367 : NULL,
368 : ntlm_state->nt_hash,
369 : &user_sess_key,
370 : &lm_sess_key);
371 :
372 1 : assert_int_equal(NT_STATUS_V(status),
373 : NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
374 1 : }
375 :
376 1 : int main(int argc, const char **argv)
377 : {
378 1 : const struct CMUnitTest tests[] = {
379 : cmocka_unit_test_setup_teardown(test_ntlm_allowed,
380 : test_ntlm_setup,
381 : test_ntlm_teardown),
382 : cmocka_unit_test_setup_teardown(test_ntlm_allowed_lm_supplied,
383 : test_ntlm_and_lm_setup,
384 : test_ntlm_teardown),
385 : cmocka_unit_test_setup_teardown(test_ntlm_disabled,
386 : test_ntlm_setup,
387 : test_ntlm_teardown),
388 : cmocka_unit_test_setup_teardown(test_ntlm2,
389 : test_ntlm2_setup,
390 : test_ntlm_teardown),
391 : cmocka_unit_test_setup_teardown(test_ntlm_mschapv2_only_allowed,
392 : test_ntlm_setup,
393 : test_ntlm_teardown),
394 : cmocka_unit_test_setup_teardown(test_ntlm_mschapv2_only_denied,
395 : test_ntlm_setup,
396 : test_ntlm_teardown),
397 : cmocka_unit_test_setup_teardown(test_ntlmv2_only_ntlm,
398 : test_ntlm_setup,
399 : test_ntlm_teardown),
400 : cmocka_unit_test_setup_teardown(test_ntlmv2_only_ntlm_and_lanman,
401 : test_ntlm_and_lm_setup,
402 : test_ntlm_teardown),
403 : cmocka_unit_test_setup_teardown(test_ntlmv2_only_ntlm_once,
404 : test_ntlm_setup,
405 : test_ntlm_teardown),
406 : cmocka_unit_test_setup_teardown(test_ntlmv2_only_ntlmv2,
407 : test_ntlmv2_setup,
408 : test_ntlm_teardown)
409 : };
410 :
411 1 : cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
412 1 : return cmocka_run_group_tests(tests, NULL, NULL);
413 : }
|