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
*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(mem_ctx
,
281 &user_info
, pdb_get_username(pdb_entry
), pdb_get_username(pdb_entry
),
282 pdb_get_domain(pdb_entry
), pdb_get_domain(pdb_entry
), lp_netbios_name(),
283 tsocket_address
, NULL
, &nt_resp
, NULL
, NULL
, NULL
,
284 AUTH_PASSWORD_RESPONSE
);
285 if (!NT_STATUS_IS_OK(status
)) {
286 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
290 status
= check_sam_security_info3(&challenge
, NULL
, user_info
, &info3_sam
);
291 if (!NT_STATUS_IS_OK(status
)) {
292 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
296 if (memcmp(info3_sam
->base
.key
.key
, local_nt_session_key
, 16) != 0) {
297 DEBUG(0, ("Returned NT session key is incorrect\n"));
301 status
= make_auth_context_fixed(NULL
, &auth_context
, challenge
.data
);
303 if (!NT_STATUS_IS_OK(status
)) {
304 DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status
)));
308 status
= auth_check_ntlm_password(mem_ctx
,
313 if (!NT_STATUS_IS_OK(status
)) {
314 DEBUG(0, ("Failed to test authentication with auth module: %s\n", nt_errstr(status
)));
318 info3_auth
= talloc_zero(mem_ctx
, struct netr_SamInfo3
);
319 if (info3_auth
== NULL
) {
323 status
= serverinfo_to_SamInfo3(server_info
, info3_auth
);
324 if (!NT_STATUS_IS_OK(status
)) {
325 DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
330 if (memcmp(info3_auth
->base
.key
.key
, local_nt_session_key
, 16) != 0) {
331 DEBUG(0, ("Returned NT session key is incorrect\n"));
335 if (!dom_sid_equal(info3_sam
->base
.domain_sid
, info3_auth
->base
.domain_sid
)) {
336 DEBUG(0, ("domain_sid in SAM info3 %s does not match domain_sid in AUTH info3 %s\n",
337 dom_sid_string(NULL
, info3_sam
->base
.domain_sid
),
338 dom_sid_string(NULL
, info3_auth
->base
.domain_sid
)));
343 * Compre more details from the two info3 structures,
344 * then test that an expired/disabled/pwdmustchange account
345 * returns the correct errors
351 static bool test_trusted_domains(TALLOC_CTX
*ctx
,
352 struct pdb_methods
*pdb
,
356 /* test trustdom calls */
357 struct pdb_trusted_domain
*td
;
358 struct pdb_trusted_domain
*new_td
;
359 struct trustAuthInOutBlob taiob
;
360 struct AuthenticationInformation aia
;
361 enum ndr_err_code ndr_err
;
363 td
= talloc_zero(ctx
,struct pdb_trusted_domain
);
365 fprintf(stderr
, "talloc failed\n");
369 td
->domain_name
= talloc_strdup(td
, TRUST_DOM
);
370 td
->netbios_name
= talloc_strdup(td
, TRUST_DOM
);
371 if (!td
->domain_name
|| !td
->netbios_name
) {
372 fprintf(stderr
, "talloc failed\n");
376 td
->trust_auth_incoming
= data_blob_null
;
381 taiob
.current
.count
= 1;
382 taiob
.current
.array
= &aia
;
383 unix_to_nt_time(&aia
.LastUpdateTime
, time(NULL
));
384 aia
.AuthType
= TRUST_AUTH_TYPE_CLEAR
;
385 aia
.AuthInfo
.clear
.password
= (uint8_t *) talloc_strdup(ctx
, TRUST_PWD
);
386 aia
.AuthInfo
.clear
.size
= strlen(TRUST_PWD
);
388 taiob
.previous
.count
= 0;
389 taiob
.previous
.array
= NULL
;
391 ndr_err
= ndr_push_struct_blob(&td
->trust_auth_outgoing
,
393 (ndr_push_flags_fn_t
) ndr_push_trustAuthInOutBlob
);
394 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
395 fprintf(stderr
, "ndr_push_struct_blob failed.\n");
399 td
->trust_direction
= LSA_TRUST_DIRECTION_OUTBOUND
;
400 td
->trust_type
= LSA_TRUST_TYPE_DOWNLEVEL
;
401 td
->trust_attributes
= 0;
402 td
->trust_forest_trust_info
= data_blob_null
;
404 rv
= pdb
->set_trusted_domain(pdb
, TRUST_DOM
, td
);
405 if (!NT_STATUS_IS_OK(rv
)) {
406 fprintf(stderr
, "Error in set_trusted_domain %s\n",
407 get_friendly_nt_error_msg(rv
));
411 rv
= pdb
->get_trusted_domain(pdb
, ctx
, TRUST_DOM
, &new_td
);
412 if (!NT_STATUS_IS_OK(rv
)) {
413 fprintf(stderr
, "Error in set_trusted_domain %s\n",
414 get_friendly_nt_error_msg(rv
));
418 if (!strequal(td
->domain_name
, new_td
->domain_name
) ||
419 !strequal(td
->netbios_name
, new_td
->netbios_name
) ||
420 !dom_sid_equal(&td
->security_identifier
,
421 &new_td
->security_identifier
) ||
422 td
->trust_direction
!= new_td
->trust_direction
||
423 td
->trust_type
!= new_td
->trust_type
||
424 td
->trust_attributes
!= new_td
->trust_attributes
||
425 td
->trust_auth_incoming
.length
!= new_td
->trust_auth_incoming
.length
||
426 td
->trust_forest_trust_info
.length
!= new_td
->trust_forest_trust_info
.length
||
427 data_blob_cmp(&td
->trust_auth_outgoing
, &new_td
->trust_auth_outgoing
) != 0) {
428 fprintf(stderr
, "Old and new trusdet domain data do not match\n");
436 int main(int argc
, const char **argv
)
439 struct samu
*out
= NULL
;
440 struct samu
*in
= NULL
;
447 uint32_t expire
, min_age
, history
;
448 struct pdb_methods
*pdb
;
450 static const char *backend
= NULL
;
451 static const char *unix_user
= "nobody";
452 struct poptOption long_options
[] = {
453 {"username", 'u', POPT_ARG_STRING
, &unix_user
, 0, "Unix user to use for testing", "USERNAME" },
454 {"backend", 'b', POPT_ARG_STRING
, &backend
, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
460 ctx
= talloc_stackframe();
464 pc
= poptGetContext("pdbtest", argc
, argv
, long_options
, 0);
466 poptSetOtherOptionHelp(pc
, "backend[:settings] username");
468 while(poptGetNextOpt(pc
) != -1);
472 /* Load configuration */
473 lp_load_global(get_dyn_CONFIGFILE());
474 setup_logging("pdbtest", DEBUG_STDOUT
);
477 if (backend
== NULL
) {
478 backend
= lp_passdb_backend();
481 rv
= make_pdb_method_name(&pdb
, backend
);
482 if (NT_STATUS_IS_ERR(rv
)) {
483 fprintf(stderr
, "Error initializing '%s': %s\n", backend
, get_friendly_nt_error_msg(rv
));
487 if (!(out
= samu_new(ctx
))) {
488 fprintf(stderr
, "Can't create samu structure.\n");
492 if ((pwd
= Get_Pwnam_alloc(ctx
, unix_user
)) == NULL
) {
493 fprintf(stderr
, "Error getting user information for %s\n", unix_user
);
497 samu_set_unix(out
, pwd
);
499 pdb_set_profile_path(out
, "\\\\torture\\profile", PDB_SET
);
500 pdb_set_homedir(out
, "\\\\torture\\home", PDB_SET
);
501 pdb_set_logon_script(out
, "torture_script.cmd", PDB_SET
);
503 pdb_set_acct_ctrl(out
, ACB_NORMAL
, PDB_SET
);
505 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY
, &history
);
506 if (history
* PW_HISTORY_ENTRY_LEN
< NT_HASH_LEN
) {
507 buf
= (uint8_t *)TALLOC(ctx
, NT_HASH_LEN
);
509 buf
= (uint8_t *)TALLOC(ctx
, history
* PW_HISTORY_ENTRY_LEN
);
512 /* Generate some random hashes */
515 for (i
= 0; i
< NT_HASH_LEN
; i
++) {
516 buf
[i
] = (uint8_t) rand();
518 pdb_set_nt_passwd(out
, buf
, PDB_SET
);
519 for (i
= 0; i
< LM_HASH_LEN
; i
++) {
520 buf
[i
] = (uint8_t) rand();
522 pdb_set_lanman_passwd(out
, buf
, PDB_SET
);
523 for (i
= 0; i
< history
* PW_HISTORY_ENTRY_LEN
; i
++) {
524 buf
[i
] = (uint8_t) rand();
526 pdb_set_pw_history(out
, buf
, history
, PDB_SET
);
528 pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE
, &expire
);
529 pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE
, &min_age
);
530 pdb_set_pass_last_set_time(out
, time(NULL
), PDB_SET
);
532 if (min_age
== (uint32_t)-1) {
533 pdb_set_pass_can_change_time(out
, 0, PDB_SET
);
535 pdb_set_pass_can_change_time(out
, time(NULL
)+min_age
, PDB_SET
);
538 pdb_set_logon_time(out
, time(NULL
)-3600, PDB_SET
);
540 pdb_set_logoff_time(out
, time(NULL
), PDB_SET
);
542 pdb_set_kickoff_time(out
, time(NULL
)+3600, PDB_SET
);
545 if (!NT_STATUS_IS_OK(rv
= pdb
->add_sam_account(pdb
, out
))) {
546 fprintf(stderr
, "Error in add_sam_account: %s\n",
547 get_friendly_nt_error_msg(rv
));
551 if (!(in
= samu_new(ctx
))) {
552 fprintf(stderr
, "Can't create samu structure.\n");
556 /* Get account information through getsampwnam() */
557 rv
= pdb
->getsampwnam(pdb
, in
, out
->username
);
558 if (NT_STATUS_IS_ERR(rv
)) {
559 fprintf(stderr
, "Error getting sampw of added user %s: %s\n",
560 out
->username
, nt_errstr(rv
));
561 if (!NT_STATUS_IS_OK(rv
= pdb
->delete_sam_account(pdb
, out
))) {
562 fprintf(stderr
, "Error in delete_sam_account %s\n",
563 get_friendly_nt_error_msg(rv
));
569 /* Verify integrity */
570 if (samu_correct(out
, in
)) {
571 printf("User info written correctly\n");
573 printf("User info NOT written correctly\n");
577 if (test_auth(ctx
, out
)) {
578 printf("Authentication module test passed\n");
580 printf("Authentication module test failed!\n");
586 if (!NT_STATUS_IS_OK(rv
= pdb
->delete_sam_account(pdb
, out
))) {
587 fprintf(stderr
, "Error in delete_sam_account %s\n",
588 get_friendly_nt_error_msg(rv
));
591 if (pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX
) {
592 if (!test_trusted_domains(ctx
, pdb
, &error
)) {
593 fprintf(stderr
, "failed testing trusted domains.\n");