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 s1_len
, s2_len
;
44 const char *s1_buf
, *s2_buf
;
45 const uint8
*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
!= s1_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
*tsocket_address
;
265 unsigned char local_nt_response
[24];
266 DATA_BLOB nt_resp
= data_blob_const(local_nt_response
, sizeof(local_nt_response
));
267 unsigned char local_nt_session_key
[16];
268 struct netr_SamInfo3
*info3_sam
, *info3_auth
;
269 struct auth_serversupplied_info
*server_info
;
272 SMBOWFencrypt(pdb_get_nt_passwd(pdb_entry
), challenge_8
,
274 SMBsesskeygen_ntv1(pdb_get_nt_passwd(pdb_entry
), local_nt_session_key
);
276 if (tsocket_address_inet_from_strings(NULL
, "ip", NULL
, 0, &tsocket_address
) != 0) {
280 status
= make_user_info(&user_info
, pdb_get_username(pdb_entry
), pdb_get_username(pdb_entry
),
281 pdb_get_domain(pdb_entry
), pdb_get_domain(pdb_entry
), lp_netbios_name(),
282 tsocket_address
, NULL
, &nt_resp
, NULL
, NULL
, NULL
,
283 AUTH_PASSWORD_RESPONSE
);
284 if (!NT_STATUS_IS_OK(status
)) {
285 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
289 status
= check_sam_security_info3(&challenge
, NULL
, user_info
, &info3_sam
);
290 if (!NT_STATUS_IS_OK(status
)) {
291 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
295 if (memcmp(info3_sam
->base
.key
.key
, local_nt_session_key
, 16) != 0) {
296 DEBUG(0, ("Returned NT session key is incorrect\n"));
300 status
= make_auth_context_fixed(NULL
, &auth_context
, challenge
.data
);
302 if (!NT_STATUS_IS_OK(status
)) {
303 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
307 status
= auth_check_ntlm_password(auth_context
, user_info
, &server_info
);
309 if (!NT_STATUS_IS_OK(status
)) {
310 DEBUG(0, ("Failed to test authentication with auth module: %s\n", nt_errstr(status
)));
314 info3_auth
= talloc_zero(mem_ctx
, struct netr_SamInfo3
);
315 if (info3_auth
== NULL
) {
319 status
= serverinfo_to_SamInfo3(server_info
, info3_auth
);
320 if (!NT_STATUS_IS_OK(status
)) {
321 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
326 if (memcmp(info3_auth
->base
.key
.key
, local_nt_session_key
, 16) != 0) {
327 DEBUG(0, ("Returned NT session key is incorrect\n"));
331 if (!dom_sid_equal(info3_sam
->base
.domain_sid
, info3_auth
->base
.domain_sid
)) {
332 DEBUG(0, ("domain_sid in SAM info3 %s does not match domain_sid in AUTH info3 %s\n",
333 dom_sid_string(NULL
, info3_sam
->base
.domain_sid
),
334 dom_sid_string(NULL
, info3_auth
->base
.domain_sid
)));
339 * Compre more details from the two info3 structures,
340 * then test that an expired/disabled/pwdmustchange account
341 * returns the correct errors
347 static bool test_trusted_domains(TALLOC_CTX
*ctx
,
348 struct pdb_methods
*pdb
,
352 /* test trustdom calls */
353 struct pdb_trusted_domain
*td
;
354 struct pdb_trusted_domain
*new_td
;
355 struct trustAuthInOutBlob taiob
;
356 struct AuthenticationInformation aia
;
357 enum ndr_err_code ndr_err
;
359 td
= talloc_zero(ctx
,struct pdb_trusted_domain
);
361 fprintf(stderr
, "talloc failed\n");
365 td
->domain_name
= talloc_strdup(td
, TRUST_DOM
);
366 td
->netbios_name
= talloc_strdup(td
, TRUST_DOM
);
367 if (!td
->domain_name
|| !td
->netbios_name
) {
368 fprintf(stderr
, "talloc failed\n");
372 td
->trust_auth_incoming
= data_blob_null
;
377 taiob
.current
.count
= 1;
378 taiob
.current
.array
= &aia
;
379 unix_to_nt_time(&aia
.LastUpdateTime
, time(NULL
));
380 aia
.AuthType
= TRUST_AUTH_TYPE_CLEAR
;
381 aia
.AuthInfo
.clear
.password
= (uint8_t *) talloc_strdup(ctx
, TRUST_PWD
);
382 aia
.AuthInfo
.clear
.size
= strlen(TRUST_PWD
);
384 taiob
.previous
.count
= 0;
385 taiob
.previous
.array
= NULL
;
387 ndr_err
= ndr_push_struct_blob(&td
->trust_auth_outgoing
,
389 (ndr_push_flags_fn_t
) ndr_push_trustAuthInOutBlob
);
390 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
391 fprintf(stderr
, "ndr_push_struct_blob failed.\n");
395 td
->trust_direction
= LSA_TRUST_DIRECTION_OUTBOUND
;
396 td
->trust_type
= LSA_TRUST_TYPE_DOWNLEVEL
;
397 td
->trust_attributes
= 0;
398 td
->trust_forest_trust_info
= data_blob_null
;
400 rv
= pdb
->set_trusted_domain(pdb
, TRUST_DOM
, td
);
401 if (!NT_STATUS_IS_OK(rv
)) {
402 fprintf(stderr
, "Error in set_trusted_domain %s\n",
403 get_friendly_nt_error_msg(rv
));
407 rv
= pdb
->get_trusted_domain(pdb
, ctx
, TRUST_DOM
, &new_td
);
408 if (!NT_STATUS_IS_OK(rv
)) {
409 fprintf(stderr
, "Error in set_trusted_domain %s\n",
410 get_friendly_nt_error_msg(rv
));
414 if (!strequal(td
->domain_name
, new_td
->domain_name
) ||
415 !strequal(td
->netbios_name
, new_td
->netbios_name
) ||
416 !dom_sid_equal(&td
->security_identifier
,
417 &new_td
->security_identifier
) ||
418 td
->trust_direction
!= new_td
->trust_direction
||
419 td
->trust_type
!= new_td
->trust_type
||
420 td
->trust_attributes
!= new_td
->trust_attributes
||
421 td
->trust_auth_incoming
.length
!= new_td
->trust_auth_incoming
.length
||
422 td
->trust_forest_trust_info
.length
!= new_td
->trust_forest_trust_info
.length
||
423 data_blob_cmp(&td
->trust_auth_outgoing
, &new_td
->trust_auth_outgoing
) != 0) {
424 fprintf(stderr
, "Old and new trusdet domain data do not match\n");
432 int main(int argc
, char **argv
)
435 struct samu
*out
= NULL
;
436 struct samu
*in
= NULL
;
443 uint32 expire
, min_age
, history
;
444 struct pdb_methods
*pdb
;
446 static const char *backend
= NULL
;
447 static const char *unix_user
= "nobody";
448 struct poptOption long_options
[] = {
449 {"username", 'u', POPT_ARG_STRING
, &unix_user
, 0, "Unix user to use for testing", "USERNAME" },
450 {"backend", 'b', POPT_ARG_STRING
, &backend
, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
456 ctx
= talloc_stackframe();
460 pc
= poptGetContext("pdbtest", argc
, (const char **) argv
,
463 poptSetOtherOptionHelp(pc
, "backend[:settings] username");
465 while(poptGetNextOpt(pc
) != -1);
469 /* Load configuration */
470 lp_load_global(get_dyn_CONFIGFILE());
471 setup_logging("pdbtest", DEBUG_STDOUT
);
474 if (backend
== NULL
) {
475 backend
= lp_passdb_backend();
478 rv
= make_pdb_method_name(&pdb
, backend
);
479 if (NT_STATUS_IS_ERR(rv
)) {
480 fprintf(stderr
, "Error initializing '%s': %s\n", backend
, get_friendly_nt_error_msg(rv
));
484 if (!(out
= samu_new(ctx
))) {
485 fprintf(stderr
, "Can't create samu structure.\n");
489 if ((pwd
= Get_Pwnam_alloc(ctx
, unix_user
)) == NULL
) {
490 fprintf(stderr
, "Error getting user information for %s\n", unix_user
);
494 samu_set_unix(out
, pwd
);
496 pdb_set_profile_path(out
, "\\\\torture\\profile", PDB_SET
);
497 pdb_set_homedir(out
, "\\\\torture\\home", PDB_SET
);
498 pdb_set_logon_script(out
, "torture_script.cmd", PDB_SET
);
500 pdb_set_acct_ctrl(out
, ACB_NORMAL
, PDB_SET
);
502 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY
, &history
);
503 if (history
* PW_HISTORY_ENTRY_LEN
< NT_HASH_LEN
) {
504 buf
= (uint8
*)TALLOC(ctx
, NT_HASH_LEN
);
506 buf
= (uint8
*)TALLOC(ctx
, history
* PW_HISTORY_ENTRY_LEN
);
509 /* Generate some random hashes */
512 for (i
= 0; i
< NT_HASH_LEN
; i
++) {
513 buf
[i
] = (uint8
) rand();
515 pdb_set_nt_passwd(out
, buf
, PDB_SET
);
516 for (i
= 0; i
< LM_HASH_LEN
; i
++) {
517 buf
[i
] = (uint8
) rand();
519 pdb_set_lanman_passwd(out
, buf
, PDB_SET
);
520 for (i
= 0; i
< history
* PW_HISTORY_ENTRY_LEN
; i
++) {
521 buf
[i
] = (uint8
) rand();
523 pdb_set_pw_history(out
, buf
, history
, PDB_SET
);
525 pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE
, &expire
);
526 pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE
, &min_age
);
527 pdb_set_pass_last_set_time(out
, time(NULL
), PDB_SET
);
529 if (min_age
== (uint32
)-1) {
530 pdb_set_pass_can_change_time(out
, 0, PDB_SET
);
532 pdb_set_pass_can_change_time(out
, time(NULL
)+min_age
, PDB_SET
);
535 pdb_set_logon_time(out
, time(NULL
)-3600, PDB_SET
);
537 pdb_set_logoff_time(out
, time(NULL
), PDB_SET
);
539 pdb_set_kickoff_time(out
, time(NULL
)+3600, PDB_SET
);
542 if (!NT_STATUS_IS_OK(rv
= pdb
->add_sam_account(pdb
, out
))) {
543 fprintf(stderr
, "Error in add_sam_account: %s\n",
544 get_friendly_nt_error_msg(rv
));
548 if (!(in
= samu_new(ctx
))) {
549 fprintf(stderr
, "Can't create samu structure.\n");
553 /* Get account information through getsampwnam() */
554 rv
= pdb
->getsampwnam(pdb
, in
, out
->username
);
555 if (NT_STATUS_IS_ERR(rv
)) {
556 fprintf(stderr
, "Error getting sampw of added user %s: %s\n",
557 out
->username
, nt_errstr(rv
));
558 if (!NT_STATUS_IS_OK(rv
= pdb
->delete_sam_account(pdb
, out
))) {
559 fprintf(stderr
, "Error in delete_sam_account %s\n",
560 get_friendly_nt_error_msg(rv
));
566 /* Verify integrity */
567 if (samu_correct(out
, in
)) {
568 printf("User info written correctly\n");
570 printf("User info NOT written correctly\n");
574 if (test_auth(ctx
, out
)) {
575 printf("Authentication module test passed\n");
577 printf("Authentication module test failed!\n");
583 if (!NT_STATUS_IS_OK(rv
= pdb
->delete_sam_account(pdb
, out
))) {
584 fprintf(stderr
, "Error in delete_sam_account %s\n",
585 get_friendly_nt_error_msg(rv
));
588 if (pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX
) {
589 if (!test_trusted_domains(ctx
, pdb
, &error
)) {
590 fprintf(stderr
, "failed testing trusted domains.\n");