2 Unix SMB/CIFS implementation.
5 Copyright (C) Wilco Baan Hofman 2006
6 Copyright (C) Jelmer Vernooij 2006
7 Copyright (C) Andrew Bartlett 2012
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "popt_common.h"
28 #include "../librpc/gen_ndr/drsblobs.h"
29 #include "../librpc/gen_ndr/ndr_drsblobs.h"
30 #include "../libcli/security/dom_sid.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../auth/common_auth.h"
33 #include "lib/tsocket/tsocket.h"
34 #include "include/auth.h"
36 #define TRUST_DOM "trustdom"
37 #define TRUST_PWD "trustpwd1232"
38 #define TRUST_SID "S-1-5-21-1111111111-2222222222-3333333333"
40 static bool samu_correct(struct samu
*s1
, struct samu
*s2
)
43 uint32_t s1_len
, s2_len
;
44 const char *s1_buf
, *s2_buf
;
45 const uint8_t *d1_buf
, *d2_buf
;
46 const struct dom_sid
*s1_sid
, *s2_sid
;
48 /* Check Unix username */
49 s1_buf
= pdb_get_username(s1
);
50 s2_buf
= pdb_get_username(s2
);
51 if (s2_buf
== NULL
&& s1_buf
!= NULL
) {
52 DEBUG(0, ("Username is not set\n"));
54 } else if (s1_buf
== NULL
) {
56 } else if (strcmp(s1_buf
,s2_buf
)) {
57 DEBUG(0, ("Username not written correctly, want %s, got \"%s\"\n",
59 pdb_get_username(s2
)));
63 /* Check NT username */
64 s1_buf
= pdb_get_nt_username(s1
);
65 s2_buf
= pdb_get_nt_username(s2
);
66 if (s2_buf
== NULL
&& s1_buf
!= NULL
) {
67 DEBUG(0, ("NT Username is not set\n"));
69 } else if (s1_buf
== NULL
) {
71 } else if (strcmp(s1_buf
, s2_buf
)) {
72 DEBUG(0, ("NT Username not written correctly, want \"%s\", got \"%s\"\n",
73 pdb_get_nt_username(s1
),
74 pdb_get_nt_username(s2
)));
79 if (pdb_get_acct_ctrl(s1
) != pdb_get_acct_ctrl(s2
)) {
80 DEBUG(0, ("Acct ctrl field not written correctly, want %d (0x%X), got %d (0x%X)\n",
81 pdb_get_acct_ctrl(s1
),
82 pdb_get_acct_ctrl(s1
),
83 pdb_get_acct_ctrl(s2
),
84 pdb_get_acct_ctrl(s2
)));
88 /* Check NT password */
89 d1_buf
= pdb_get_nt_passwd(s1
);
90 d2_buf
= pdb_get_nt_passwd(s2
);
91 if (d2_buf
== NULL
&& d1_buf
!= NULL
) {
92 DEBUG(0, ("NT password is not set\n"));
94 } else if (d1_buf
== NULL
) {
96 } else if (memcmp(d1_buf
, d2_buf
, NT_HASH_LEN
)) {
97 DEBUG(0, ("NT password not written correctly\n"));
101 /* Check lanman password */
102 d1_buf
= pdb_get_lanman_passwd(s1
);
103 d2_buf
= pdb_get_lanman_passwd(s2
);
104 if (d2_buf
== NULL
&& d1_buf
!= NULL
) {
105 DEBUG(0, ("Lanman password is not set\n"));
106 } else if (d1_buf
== NULL
) {
108 } else if (memcmp(d1_buf
, d2_buf
, NT_HASH_LEN
)) {
109 DEBUG(0, ("Lanman password not written correctly\n"));
113 /* Check password history */
114 d1_buf
= pdb_get_pw_history(s1
, &s1_len
);
115 d2_buf
= pdb_get_pw_history(s2
, &s2_len
);
116 if (d2_buf
== NULL
&& d1_buf
!= NULL
) {
117 DEBUG(0, ("Password history is not set\n"));
118 } else if (d1_buf
== NULL
) {
120 } else if (s1_len
!= s2_len
) {
121 DEBUG(0, ("Password history not written correctly, lengths differ, want %d, got %d\n",
124 } else if (strncmp(s1_buf
, s2_buf
, s1_len
)) {
125 DEBUG(0, ("Password history not written correctly\n"));
129 /* Check logon time */
130 if (pdb_get_logon_time(s1
) != pdb_get_logon_time(s2
)) {
131 DEBUG(0, ("Logon time is not written correctly\n"));
135 /* Check logoff time */
136 if (pdb_get_logoff_time(s1
) != pdb_get_logoff_time(s2
)) {
137 DEBUG(0, ("Logoff time is not written correctly: %s vs %s \n",
138 http_timestring(talloc_tos(), pdb_get_logoff_time(s1
)),
139 http_timestring(talloc_tos(), pdb_get_logoff_time(s2
))));
143 /* Check kickoff time */
144 if (pdb_get_kickoff_time(s1
) != pdb_get_kickoff_time(s2
)) {
145 DEBUG(0, ("Kickoff time is not written correctly: %s vs %s \n",
146 http_timestring(talloc_tos(), pdb_get_kickoff_time(s1
)),
147 http_timestring(talloc_tos(), pdb_get_kickoff_time(s2
))));
151 /* Check bad password time */
152 if (pdb_get_bad_password_time(s1
) != pdb_get_bad_password_time(s2
)) {
153 DEBUG(0, ("Bad password time is not written correctly\n"));
157 /* Check password last set time */
158 if (pdb_get_pass_last_set_time(s1
) != pdb_get_pass_last_set_time(s2
)) {
159 DEBUG(0, ("Password last set time is not written correctly: %s vs %s \n",
160 http_timestring(talloc_tos(), pdb_get_pass_last_set_time(s1
)),
161 http_timestring(talloc_tos(), pdb_get_pass_last_set_time(s2
))));
165 /* Check password can change time */
166 if (pdb_get_pass_can_change_time(s1
) != pdb_get_pass_can_change_time(s2
)) {
167 DEBUG(0, ("Password can change time is not written correctly %s vs %s \n",
168 http_timestring(talloc_tos(), pdb_get_pass_can_change_time(s1
)),
169 http_timestring(talloc_tos(), pdb_get_pass_can_change_time(s2
))));
173 /* Check password must change time */
174 if (pdb_get_pass_must_change_time(s1
) != pdb_get_pass_must_change_time(s2
)) {
175 DEBUG(0, ("Password must change time is not written correctly\n"));
179 /* Check logon divs */
180 if (pdb_get_logon_divs(s1
) != pdb_get_logon_divs(s2
)) {
181 DEBUG(0, ("Logon divs not written correctly\n"));
185 /* Check logon hours */
186 if (pdb_get_hours_len(s1
) != pdb_get_hours_len(s2
)) {
187 DEBUG(0, ("Logon hours length not written correctly\n"));
189 } else if (pdb_get_hours_len(s1
) != 0) {
190 d1_buf
= pdb_get_hours(s1
);
191 d2_buf
= pdb_get_hours(s2
);
192 if (d2_buf
== NULL
&& d2_buf
!= NULL
) {
193 DEBUG(0, ("Logon hours is not set\n"));
195 } else if (d1_buf
== NULL
) {
197 } else if (memcmp(d1_buf
, d2_buf
, MAX_HOURS_LEN
)) {
198 DEBUG(0, ("Logon hours is not written correctly\n"));
203 /* Check profile path */
204 s1_buf
= pdb_get_profile_path(s1
);
205 s2_buf
= pdb_get_profile_path(s2
);
206 if (s2_buf
== NULL
&& s1_buf
!= NULL
) {
207 DEBUG(0, ("Profile path is not set\n"));
209 } else if (s1_buf
== NULL
) {
211 } else if (strcmp(s1_buf
, s2_buf
)) {
212 DEBUG(0, ("Profile path is not written correctly\n"));
217 s1_buf
= pdb_get_homedir(s1
);
218 s2_buf
= pdb_get_homedir(s2
);
219 if (s2_buf
== NULL
&& s1_buf
!= NULL
) {
220 DEBUG(0, ("Home dir is not set\n"));
222 } else if (s1_buf
== NULL
) {
224 } else if (strcmp(s1_buf
, s2_buf
)) {
225 DEBUG(0, ("Home dir is not written correctly\n"));
229 /* Check logon script */
230 s1_buf
= pdb_get_logon_script(s1
);
231 s2_buf
= pdb_get_logon_script(s2
);
232 if (s2_buf
== NULL
&& s1_buf
!= NULL
) {
233 DEBUG(0, ("Logon script not set\n"));
235 } else if (s1_buf
== NULL
) {
237 } else if (strcmp(s1_buf
, s2_buf
)) {
238 DEBUG(0, ("Logon script is not written correctly\n"));
242 /* Check user and group sids */
243 s1_sid
= pdb_get_user_sid(s1
);
244 s2_sid
= pdb_get_user_sid(s2
);
245 if (s2_sid
== NULL
&& s1_sid
!= NULL
) {
246 DEBUG(0, ("USER SID not set\n"));
248 } else if (s1_sid
== NULL
) {
250 } else if (!dom_sid_equal(s1_sid
, s2_sid
)) {
251 DEBUG(0, ("USER SID is not written correctly\n"));
258 static bool test_auth(TALLOC_CTX
*mem_ctx
, struct samu
*pdb_entry
)
260 struct auth_usersupplied_info
*user_info
;
261 struct auth_context
*auth_context
;
262 static const uint8_t challenge_8
[8] = {1, 2, 3, 4, 5, 6, 7, 8};
263 DATA_BLOB challenge
= data_blob_const(challenge_8
, sizeof(challenge_8
));
264 struct tsocket_address
*remote_address
;
265 struct tsocket_address
*local_address
;
266 unsigned char local_nt_response
[24];
267 DATA_BLOB nt_resp
= data_blob_const(local_nt_response
, sizeof(local_nt_response
));
268 unsigned char local_nt_session_key
[16];
269 struct netr_SamInfo3
*info3_sam
, *info3_auth
;
270 struct auth_serversupplied_info
*server_info
;
273 uint8_t authoritative
= 0;
275 SMBOWFencrypt(pdb_get_nt_passwd(pdb_entry
), challenge_8
,
277 SMBsesskeygen_ntv1(pdb_get_nt_passwd(pdb_entry
), local_nt_session_key
);
279 if (tsocket_address_inet_from_strings(NULL
, "ip", NULL
, 0, &remote_address
) != 0) {
283 if (tsocket_address_inet_from_strings(NULL
, "ip", NULL
, 0, &local_address
) != 0) {
287 status
= make_user_info(mem_ctx
,
288 &user_info
, pdb_get_username(pdb_entry
), pdb_get_username(pdb_entry
),
289 pdb_get_domain(pdb_entry
), pdb_get_domain(pdb_entry
), lp_netbios_name(),
290 remote_address
,local_address
, "pdbtest",
291 NULL
, &nt_resp
, NULL
, NULL
, NULL
,
292 AUTH_PASSWORD_RESPONSE
);
293 if (!NT_STATUS_IS_OK(status
)) {
294 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
298 status
= check_sam_security_info3(&challenge
, NULL
, user_info
, &info3_sam
);
299 if (!NT_STATUS_IS_OK(status
)) {
300 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
304 if (memcmp(info3_sam
->base
.key
.key
, local_nt_session_key
, 16) != 0) {
305 DEBUG(0, ("Returned NT session key is incorrect\n"));
309 status
= make_auth3_context_for_ntlm(NULL
, &auth_context
);
311 if (!NT_STATUS_IS_OK(status
)) {
312 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
316 ok
= auth3_context_set_challenge(
317 auth_context
, challenge
.data
, "fixed");
319 DBG_ERR("auth3_context_set_challenge failed\n");
323 status
= auth_check_ntlm_password(mem_ctx
,
329 if (!NT_STATUS_IS_OK(status
)) {
330 DEBUG(0, ("Failed to test authentication with auth module: "
331 "%s authoritative[%u].\n",
332 nt_errstr(status
), authoritative
));
336 info3_auth
= talloc_zero(mem_ctx
, struct netr_SamInfo3
);
337 if (info3_auth
== NULL
) {
341 status
= serverinfo_to_SamInfo3(server_info
, info3_auth
);
342 if (!NT_STATUS_IS_OK(status
)) {
343 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
348 if (memcmp(info3_auth
->base
.key
.key
, local_nt_session_key
, 16) != 0) {
349 DEBUG(0, ("Returned NT session key is incorrect\n"));
353 if (!dom_sid_equal(info3_sam
->base
.domain_sid
, info3_auth
->base
.domain_sid
)) {
354 DEBUG(0, ("domain_sid in SAM info3 %s does not match domain_sid in AUTH info3 %s\n",
355 dom_sid_string(NULL
, info3_sam
->base
.domain_sid
),
356 dom_sid_string(NULL
, info3_auth
->base
.domain_sid
)));
361 * Compre more details from the two info3 structures,
362 * then test that an expired/disabled/pwdmustchange account
363 * returns the correct errors
369 static bool test_trusted_domains(TALLOC_CTX
*ctx
,
370 struct pdb_methods
*pdb
,
374 /* test trustdom calls */
375 struct pdb_trusted_domain
*td
;
376 struct pdb_trusted_domain
*new_td
;
377 struct trustAuthInOutBlob taiob
;
378 struct AuthenticationInformation aia
;
379 enum ndr_err_code ndr_err
;
381 td
= talloc_zero(ctx
,struct pdb_trusted_domain
);
383 fprintf(stderr
, "talloc failed\n");
387 td
->domain_name
= talloc_strdup(td
, TRUST_DOM
);
388 td
->netbios_name
= talloc_strdup(td
, TRUST_DOM
);
389 if (!td
->domain_name
|| !td
->netbios_name
) {
390 fprintf(stderr
, "talloc failed\n");
394 td
->trust_auth_incoming
= data_blob_null
;
399 taiob
.current
.count
= 1;
400 taiob
.current
.array
= &aia
;
401 unix_to_nt_time(&aia
.LastUpdateTime
, time(NULL
));
402 aia
.AuthType
= TRUST_AUTH_TYPE_CLEAR
;
403 aia
.AuthInfo
.clear
.password
= (uint8_t *) talloc_strdup(ctx
, TRUST_PWD
);
404 aia
.AuthInfo
.clear
.size
= strlen(TRUST_PWD
);
406 taiob
.previous
.count
= 0;
407 taiob
.previous
.array
= NULL
;
409 ndr_err
= ndr_push_struct_blob(&td
->trust_auth_outgoing
,
411 (ndr_push_flags_fn_t
) ndr_push_trustAuthInOutBlob
);
412 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
413 fprintf(stderr
, "ndr_push_struct_blob failed.\n");
417 td
->trust_direction
= LSA_TRUST_DIRECTION_OUTBOUND
;
418 td
->trust_type
= LSA_TRUST_TYPE_DOWNLEVEL
;
419 td
->trust_attributes
= 0;
420 td
->trust_forest_trust_info
= data_blob_null
;
422 rv
= pdb
->set_trusted_domain(pdb
, TRUST_DOM
, td
);
423 if (!NT_STATUS_IS_OK(rv
)) {
424 fprintf(stderr
, "Error in set_trusted_domain %s\n",
425 get_friendly_nt_error_msg(rv
));
429 rv
= pdb
->get_trusted_domain(pdb
, ctx
, TRUST_DOM
, &new_td
);
430 if (!NT_STATUS_IS_OK(rv
)) {
431 fprintf(stderr
, "Error in set_trusted_domain %s\n",
432 get_friendly_nt_error_msg(rv
));
436 if (!strequal(td
->domain_name
, new_td
->domain_name
) ||
437 !strequal(td
->netbios_name
, new_td
->netbios_name
) ||
438 !dom_sid_equal(&td
->security_identifier
,
439 &new_td
->security_identifier
) ||
440 td
->trust_direction
!= new_td
->trust_direction
||
441 td
->trust_type
!= new_td
->trust_type
||
442 td
->trust_attributes
!= new_td
->trust_attributes
||
443 td
->trust_auth_incoming
.length
!= new_td
->trust_auth_incoming
.length
||
444 td
->trust_forest_trust_info
.length
!= new_td
->trust_forest_trust_info
.length
||
445 data_blob_cmp(&td
->trust_auth_outgoing
, &new_td
->trust_auth_outgoing
) != 0) {
446 fprintf(stderr
, "Old and new trusdet domain data do not match\n");
454 int main(int argc
, const char **argv
)
457 struct samu
*out
= NULL
;
458 struct samu
*in
= NULL
;
465 uint32_t expire
, min_age
, history
;
466 struct pdb_methods
*pdb
;
468 static const char *backend
= NULL
;
469 static const char *unix_user
= "nobody";
470 struct poptOption long_options
[] = {
471 {"username", 'u', POPT_ARG_STRING
, &unix_user
, 0, "Unix user to use for testing", "USERNAME" },
472 {"backend", 'b', POPT_ARG_STRING
, &backend
, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
478 ctx
= talloc_stackframe();
482 pc
= poptGetContext("pdbtest", argc
, argv
, long_options
, 0);
484 poptSetOtherOptionHelp(pc
, "backend[:settings] username");
486 while(poptGetNextOpt(pc
) != -1);
490 /* Load configuration */
491 lp_load_global(get_dyn_CONFIGFILE());
492 setup_logging("pdbtest", DEBUG_STDOUT
);
495 if (backend
== NULL
) {
496 backend
= lp_passdb_backend();
499 rv
= make_pdb_method_name(&pdb
, backend
);
500 if (NT_STATUS_IS_ERR(rv
)) {
501 fprintf(stderr
, "Error initializing '%s': %s\n", backend
, get_friendly_nt_error_msg(rv
));
505 if (!(out
= samu_new(ctx
))) {
506 fprintf(stderr
, "Can't create samu structure.\n");
510 if ((pwd
= Get_Pwnam_alloc(ctx
, unix_user
)) == NULL
) {
511 fprintf(stderr
, "Error getting user information for %s\n", unix_user
);
515 samu_set_unix(out
, pwd
);
517 pdb_set_profile_path(out
, "\\\\torture\\profile", PDB_SET
);
518 pdb_set_homedir(out
, "\\\\torture\\home", PDB_SET
);
519 pdb_set_logon_script(out
, "torture_script.cmd", PDB_SET
);
521 pdb_set_acct_ctrl(out
, ACB_NORMAL
, PDB_SET
);
523 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY
, &history
);
524 if (history
* PW_HISTORY_ENTRY_LEN
< NT_HASH_LEN
) {
525 buf
= (uint8_t *)TALLOC(ctx
, NT_HASH_LEN
);
527 buf
= (uint8_t *)TALLOC(ctx
, history
* PW_HISTORY_ENTRY_LEN
);
530 /* Generate some random hashes */
533 for (i
= 0; i
< NT_HASH_LEN
; i
++) {
534 buf
[i
] = (uint8_t) rand();
536 pdb_set_nt_passwd(out
, buf
, PDB_SET
);
537 for (i
= 0; i
< LM_HASH_LEN
; i
++) {
538 buf
[i
] = (uint8_t) rand();
540 pdb_set_lanman_passwd(out
, buf
, PDB_SET
);
541 for (i
= 0; i
< history
* PW_HISTORY_ENTRY_LEN
; i
++) {
542 buf
[i
] = (uint8_t) rand();
544 pdb_set_pw_history(out
, buf
, history
, PDB_SET
);
546 pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE
, &expire
);
547 pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE
, &min_age
);
548 pdb_set_pass_last_set_time(out
, time(NULL
), PDB_SET
);
550 if (min_age
== (uint32_t)-1) {
551 pdb_set_pass_can_change_time(out
, 0, PDB_SET
);
553 pdb_set_pass_can_change_time(out
, time(NULL
)+min_age
, PDB_SET
);
556 pdb_set_logon_time(out
, time(NULL
)-3600, PDB_SET
);
558 pdb_set_logoff_time(out
, time(NULL
), PDB_SET
);
560 pdb_set_kickoff_time(out
, time(NULL
)+3600, PDB_SET
);
563 if (!NT_STATUS_IS_OK(rv
= pdb
->add_sam_account(pdb
, out
))) {
564 fprintf(stderr
, "Error in add_sam_account: %s\n",
565 get_friendly_nt_error_msg(rv
));
569 if (!(in
= samu_new(ctx
))) {
570 fprintf(stderr
, "Can't create samu structure.\n");
574 /* Get account information through getsampwnam() */
575 rv
= pdb
->getsampwnam(pdb
, in
, out
->username
);
576 if (NT_STATUS_IS_ERR(rv
)) {
577 fprintf(stderr
, "Error getting sampw of added user %s: %s\n",
578 out
->username
, nt_errstr(rv
));
579 if (!NT_STATUS_IS_OK(rv
= pdb
->delete_sam_account(pdb
, out
))) {
580 fprintf(stderr
, "Error in delete_sam_account %s\n",
581 get_friendly_nt_error_msg(rv
));
587 /* Verify integrity */
588 if (samu_correct(out
, in
)) {
589 printf("User info written correctly\n");
591 printf("User info NOT written correctly\n");
595 if (test_auth(ctx
, out
)) {
596 printf("Authentication module test passed\n");
598 printf("Authentication module test failed!\n");
604 if (!NT_STATUS_IS_OK(rv
= pdb
->delete_sam_account(pdb
, out
))) {
605 fprintf(stderr
, "Error in delete_sam_account %s\n",
606 get_friendly_nt_error_msg(rv
));
609 if (pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX
) {
610 if (!test_trusted_domains(ctx
, pdb
, &error
)) {
611 fprintf(stderr
, "failed testing trusted domains.\n");