CVE-2018-1139 libcli/auth: Add initial tests for ntlm_password_check()
[gd/samba-autobuild/.git] / libcli / auth / tests / ntlm_check.c
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 <setjmp.h>
44 #include <cmocka.h>
45
46 #include "includes.h"
47 #include "../lib/crypto/crypto.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 static int test_ntlm_setup_with_options(void **state,
64                                         int flags, bool upn)
65 {
66         NTSTATUS status;
67         DATA_BLOB challenge = {
68                 .data = discard_const_p(uint8_t, "I am a teapot"),
69                 .length = 8
70         };
71         struct ntlm_state *ntlm_state = talloc(NULL, struct ntlm_state);
72         DATA_BLOB target_info = NTLMv2_generate_names_blob(ntlm_state,
73                                                            NULL,
74                                                            "serverdom");
75         struct cli_credentials *creds = cli_credentials_init(ntlm_state);
76         cli_credentials_set_username(creds,
77                                      "testuser",
78                                      CRED_SPECIFIED);
79         cli_credentials_set_domain(creds,
80                                    "testdom",
81                                    CRED_SPECIFIED);
82         cli_credentials_set_workstation(creds,
83                                         "testwksta",
84                                         CRED_SPECIFIED);
85         cli_credentials_set_password(creds,
86                                      "testpass",
87                                      CRED_SPECIFIED);
88
89         if (upn) {
90                 cli_credentials_set_principal(creds,
91                                               "testuser@samba.org",
92                                               CRED_SPECIFIED);
93         }
94
95         cli_credentials_get_ntlm_username_domain(creds,
96                                                  ntlm_state,
97                                                  &ntlm_state->username,
98                                                  &ntlm_state->domain);
99
100         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         ntlm_state->challenge = challenge;
111
112         ntlm_state->nt_hash = cli_credentials_get_nt_hash(creds,
113                                                           ntlm_state);
114
115         if (!NT_STATUS_IS_OK(status)) {
116                 return -1;
117         }
118
119         *state = ntlm_state;
120         return 0;
121 }
122
123 static int test_ntlm_setup(void **state) {
124         return test_ntlm_setup_with_options(state, 0, false);
125 }
126
127 static int test_ntlm_and_lm_setup(void **state) {
128         return test_ntlm_setup_with_options(state,
129                                             CLI_CRED_LANMAN_AUTH,
130                                             false);
131 }
132
133 static int test_ntlm2_setup(void **state) {
134         return test_ntlm_setup_with_options(state,
135                                             CLI_CRED_NTLM2,
136                                             false);
137 }
138
139 static int test_ntlmv2_setup(void **state) {
140         return test_ntlm_setup_with_options(state,
141                                             CLI_CRED_NTLMv2_AUTH,
142                                             false);
143 }
144
145 static int test_ntlm_teardown(void **state)
146 {
147         struct ntlm_state *ntlm_state
148                 = talloc_get_type_abort(*state,
149                                         struct ntlm_state);
150         TALLOC_FREE(ntlm_state);
151         *state = NULL;
152         return 0;
153 }
154
155 static void test_ntlm_allowed(void **state)
156 {
157         DATA_BLOB user_sess_key, lm_sess_key;
158         struct ntlm_state *ntlm_state
159                 = talloc_get_type_abort(*state,
160                                         struct ntlm_state);
161         NTSTATUS status;
162         status = ntlm_password_check(ntlm_state,
163                                      false,
164                                      NTLM_AUTH_ON,
165                                      0,
166                                      &ntlm_state->challenge,
167                                      &ntlm_state->lm,
168                                      &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         assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_OK));
178 }
179
180 static void test_ntlm_allowed_lm_supplied(void **state)
181 {
182         return test_ntlm_allowed(state);
183 }
184
185 static void test_ntlm_disabled(void **state)
186 {
187         DATA_BLOB user_sess_key, lm_sess_key;
188         struct ntlm_state *ntlm_state
189                 = talloc_get_type_abort(*state,
190                                         struct ntlm_state);
191         NTSTATUS status;
192         status = ntlm_password_check(ntlm_state,
193                                      false,
194                                      NTLM_AUTH_DISABLED,
195                                      0,
196                                      &ntlm_state->challenge,
197                                      &ntlm_state->lm,
198                                      &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         assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_NTLM_BLOCKED));
208 }
209
210 static void test_ntlm2(void **state)
211 {
212         DATA_BLOB user_sess_key, lm_sess_key;
213         struct ntlm_state *ntlm_state
214                 = talloc_get_type_abort(*state,
215                                         struct ntlm_state);
216         NTSTATUS status;
217         status = ntlm_password_check(ntlm_state,
218                                      false,
219                                      NTLM_AUTH_ON,
220                                      0,
221                                      &ntlm_state->challenge,
222                                      &ntlm_state->lm,
223                                      &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         assert_int_equal(NT_STATUS_V(status),
240                          NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
241 }
242
243 static void test_ntlm_mschapv2_only_allowed(void **state)
244 {
245         DATA_BLOB user_sess_key, lm_sess_key;
246         struct ntlm_state *ntlm_state
247                 = talloc_get_type_abort(*state,
248                                         struct ntlm_state);
249         NTSTATUS status;
250         status = ntlm_password_check(ntlm_state,
251                                      false,
252                                      NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY,
253                                      MSV1_0_ALLOW_MSVCHAPV2,
254                                      &ntlm_state->challenge,
255                                      &ntlm_state->lm,
256                                      &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         assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_OK));
266 }
267
268 static void test_ntlm_mschapv2_only_denied(void **state)
269 {
270         DATA_BLOB user_sess_key, lm_sess_key;
271         struct ntlm_state *ntlm_state
272                 = talloc_get_type_abort(*state,
273                                         struct ntlm_state);
274         NTSTATUS status;
275         status = ntlm_password_check(ntlm_state,
276                                      false,
277                                      NTLM_AUTH_MSCHAPv2_NTLMV2_ONLY,
278                                      0,
279                                      &ntlm_state->challenge,
280                                      &ntlm_state->lm,
281                                      &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         assert_int_equal(NT_STATUS_V(status),
291                          NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
292 }
293
294 static void test_ntlmv2_only_ntlmv2(void **state)
295 {
296         DATA_BLOB user_sess_key, lm_sess_key;
297         struct ntlm_state *ntlm_state
298                 = talloc_get_type_abort(*state,
299                                         struct ntlm_state);
300         NTSTATUS status;
301         status = ntlm_password_check(ntlm_state,
302                                      false,
303                                      NTLM_AUTH_NTLMV2_ONLY,
304                                      0,
305                                      &ntlm_state->challenge,
306                                      &ntlm_state->lm,
307                                      &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         assert_int_equal(NT_STATUS_V(status), NT_STATUS_V(NT_STATUS_OK));
317 }
318
319 static void test_ntlmv2_only_ntlm(void **state)
320 {
321         DATA_BLOB user_sess_key, lm_sess_key;
322         struct ntlm_state *ntlm_state
323                 = talloc_get_type_abort(*state,
324                                         struct ntlm_state);
325         NTSTATUS status;
326         status = ntlm_password_check(ntlm_state,
327                                      false,
328                                      NTLM_AUTH_NTLMV2_ONLY,
329                                      0,
330                                      &ntlm_state->challenge,
331                                      &ntlm_state->lm,
332                                      &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         assert_int_equal(NT_STATUS_V(status),
342                          NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
343 }
344
345 static void test_ntlmv2_only_ntlm_and_lanman(void **state)
346 {
347         return test_ntlmv2_only_ntlm(state);
348 }
349
350 static void test_ntlmv2_only_ntlm_once(void **state)
351 {
352         DATA_BLOB user_sess_key, lm_sess_key;
353         struct ntlm_state *ntlm_state
354                 = talloc_get_type_abort(*state,
355                                         struct ntlm_state);
356         NTSTATUS status;
357         status = ntlm_password_check(ntlm_state,
358                                      false,
359                                      NTLM_AUTH_NTLMV2_ONLY,
360                                      0,
361                                      &ntlm_state->challenge,
362                                      &data_blob_null,
363                                      &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         assert_int_equal(NT_STATUS_V(status),
373                          NT_STATUS_V(NT_STATUS_WRONG_PASSWORD));
374 }
375
376 int main(int argc, const char **argv)
377 {
378         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         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
412         return cmocka_run_group_tests(tests, NULL, NULL);
413 }