1 /*
2    Unix SMB/CIFS implementation.
3 
4    test suite for netlogon rpc operations
5 
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
8    Copyright (C) Tim Potter      2003
9 
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 #include "includes.h"
25 #include "../lib/util/dlinklist.h"
26 #include "../lib/crypto/crypto.h"
27 #include "system/time.h"
28 #include "torture/rpc/torture_rpc.h"
29 #include "auth/gensec/gensec.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "libcli/samsync/samsync.h"
32 #include "libcli/security/security.h"
33 #include "librpc/gen_ndr/ndr_netlogon.h"
34 #include "librpc/gen_ndr/ndr_netlogon_c.h"
35 #include "librpc/gen_ndr/ndr_lsa_c.h"
36 #include "librpc/gen_ndr/ndr_samr_c.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "param/param.h"
39 #include "lib/crypto/gnutls_helpers.h"
40 
41 #define TEST_MACHINE_NAME "samsynctest"
42 #define TEST_WKSTA_MACHINE_NAME "samsynctest2"
43 #define TEST_USER_NAME "samsynctestuser"
44 
45 /*
46   try a netlogon SamLogon
47 */
test_SamLogon(struct torture_context * tctx,struct dcerpc_pipe * p,TALLOC_CTX * mem_ctx,struct netlogon_creds_CredentialState * creds,const char * domain,const char * account_name,const char * workstation,struct samr_Password * lm_hash,struct samr_Password * nt_hash,struct netr_SamInfo3 ** info3)48 static NTSTATUS test_SamLogon(struct torture_context *tctx,
49 			      struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
50 			      struct netlogon_creds_CredentialState *creds,
51 			      const char *domain, const char *account_name,
52 			      const char *workstation,
53 			      struct samr_Password *lm_hash,
54 			      struct samr_Password *nt_hash,
55 			      struct netr_SamInfo3 **info3)
56 {
57 	NTSTATUS status;
58 	struct netr_LogonSamLogon r;
59 	struct netr_Authenticator auth, auth2;
60 	struct netr_NetworkInfo ninfo;
61 	union netr_LogonLevel logon;
62 	union netr_Validation validation;
63 	uint8_t authoritative;
64 	struct dcerpc_binding_handle *b = p->binding_handle;
65 	int rc;
66 
67 	ninfo.identity_info.domain_name.string = domain;
68 	ninfo.identity_info.parameter_control = 0;
69 	ninfo.identity_info.logon_id = 0;
70 	ninfo.identity_info.account_name.string = account_name;
71 	ninfo.identity_info.workstation.string = workstation;
72 	generate_random_buffer(ninfo.challenge,
73 			       sizeof(ninfo.challenge));
74 	if (nt_hash) {
75 		ninfo.nt.length = 24;
76 		ninfo.nt.data = talloc_array(mem_ctx, uint8_t, 24);
77 		rc = SMBOWFencrypt(nt_hash->hash, ninfo.challenge,
78 				   ninfo.nt.data);
79 		if (rc != 0) {
80 			return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
81 		}
82 	} else {
83 		ninfo.nt.length = 0;
84 		ninfo.nt.data = NULL;
85 	}
86 
87 	if (lm_hash) {
88 		ninfo.lm.length = 24;
89 		ninfo.lm.data = talloc_array(mem_ctx, uint8_t, 24);
90 		rc = SMBOWFencrypt(lm_hash->hash, ninfo.challenge,
91 				   ninfo.lm.data);
92 		if (rc != 0) {
93 			return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
94 		}
95 	} else {
96 		ninfo.lm.length = 0;
97 		ninfo.lm.data = NULL;
98 	}
99 
100 	logon.network = &ninfo;
101 
102 	r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
103 	r.in.computer_name = workstation;
104 	r.in.credential = &auth;
105 	r.in.return_authenticator = &auth2;
106 	r.in.logon_level = NetlogonNetworkInformation;
107 	r.in.logon = &logon;
108 	r.out.validation = &validation;
109 	r.out.authoritative = &authoritative;
110 
111 	ZERO_STRUCT(auth2);
112 	netlogon_creds_client_authenticator(creds, &auth);
113 
114 	r.in.validation_level = 3;
115 
116 	status = dcerpc_netr_LogonSamLogon_r(b, mem_ctx, &r);
117 	if (!NT_STATUS_IS_OK(status)) {
118 		return status;
119 	}
120 
121 	if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) {
122 		torture_comment(tctx, "Credential chaining failed\n");
123 	}
124 
125 	if (info3) {
126 		*info3 = validation.sam3;
127 	}
128 
129 	return r.out.result;
130 }
131 
132 struct samsync_state {
133 /* we remember the sequence numbers so we can easily do a DatabaseDelta */
134 	uint64_t seq_num[3];
135 	const char *domain_name[2];
136 	struct samsync_secret *secrets;
137 	struct samsync_trusted_domain *trusted_domains;
138 	struct netlogon_creds_CredentialState *creds;
139 	struct netlogon_creds_CredentialState *creds_netlogon_wksta;
140 	struct policy_handle *connect_handle;
141 	struct policy_handle *domain_handle[2];
142 	struct dom_sid *sid[2];
143 	struct dcerpc_pipe *p;
144 	struct dcerpc_binding_handle *b;
145 	struct dcerpc_pipe *p_netlogon_wksta;
146 	struct dcerpc_pipe *p_samr;
147 	struct dcerpc_binding_handle *b_samr;
148 	struct dcerpc_pipe *p_lsa;
149 	struct dcerpc_binding_handle *b_lsa;
150 	struct policy_handle *lsa_handle;
151 };
152 
153 struct samsync_secret {
154 	struct samsync_secret *prev, *next;
155 	DATA_BLOB secret;
156 	const char *name;
157 	NTTIME mtime;
158 };
159 
160 struct samsync_trusted_domain {
161 	struct samsync_trusted_domain *prev, *next;
162         struct dom_sid *sid;
163 	const char *name;
164 };
165 
samsync_open_domain(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,const char * domain,struct dom_sid ** sid_p)166 static struct policy_handle *samsync_open_domain(struct torture_context *tctx,
167 						 TALLOC_CTX *mem_ctx,
168 						 struct samsync_state *samsync_state,
169 						 const char *domain,
170 						 struct dom_sid **sid_p)
171 {
172 	struct lsa_String name;
173 	struct samr_OpenDomain o;
174 	struct samr_LookupDomain l;
175 	struct dom_sid2 *sid = NULL;
176 	struct policy_handle *domain_handle = talloc(mem_ctx, struct policy_handle);
177 	NTSTATUS nt_status;
178 
179 	name.string = domain;
180 	l.in.connect_handle = samsync_state->connect_handle;
181 	l.in.domain_name = &name;
182 	l.out.sid = &sid;
183 
184 	nt_status = dcerpc_samr_LookupDomain_r(samsync_state->b_samr, mem_ctx, &l);
185 	if (!NT_STATUS_IS_OK(nt_status)) {
186 		torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(nt_status));
187 		return NULL;
188 	}
189 	if (!NT_STATUS_IS_OK(l.out.result)) {
190 		torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(l.out.result));
191 		return NULL;
192 	}
193 
194 	o.in.connect_handle = samsync_state->connect_handle;
195 	o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
196 	o.in.sid = *l.out.sid;
197 	o.out.domain_handle = domain_handle;
198 
199 	if (sid_p) {
200 		*sid_p = *l.out.sid;
201 	}
202 
203 	nt_status = dcerpc_samr_OpenDomain_r(samsync_state->b_samr, mem_ctx, &o);
204 	if (!NT_STATUS_IS_OK(nt_status)) {
205 		torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(nt_status));
206 		return NULL;
207 	}
208 	if (!NT_STATUS_IS_OK(o.out.result)) {
209 		torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(o.out.result));
210 		return NULL;
211 	}
212 
213 	return domain_handle;
214 }
215 
samsync_query_samr_sec_desc(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,struct policy_handle * handle)216 static struct sec_desc_buf *samsync_query_samr_sec_desc(struct torture_context *tctx,
217 							TALLOC_CTX *mem_ctx,
218 							struct samsync_state *samsync_state,
219 							struct policy_handle *handle)
220 {
221 	struct samr_QuerySecurity r;
222 	struct sec_desc_buf *sdbuf = NULL;
223 	NTSTATUS status;
224 
225 	r.in.handle = handle;
226 	r.in.sec_info = 0x7;
227 	r.out.sdbuf = &sdbuf;
228 
229 	status = dcerpc_samr_QuerySecurity_r(samsync_state->b_samr, mem_ctx, &r);
230 	if (!NT_STATUS_IS_OK(status)) {
231 		torture_comment(tctx, "SAMR QuerySecurity failed - %s\n", nt_errstr(status));
232 		return NULL;
233 	}
234 	if (!NT_STATUS_IS_OK(r.out.result)) {
235 		torture_comment(tctx, "SAMR QuerySecurity failed - %s\n", nt_errstr(r.out.result));
236 		return NULL;
237 	}
238 
239 	return sdbuf;
240 }
241 
samsync_query_lsa_sec_desc(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,struct policy_handle * handle)242 static struct sec_desc_buf *samsync_query_lsa_sec_desc(struct torture_context *tctx,
243 						       TALLOC_CTX *mem_ctx,
244 						       struct samsync_state *samsync_state,
245 						       struct policy_handle *handle)
246 {
247 	struct lsa_QuerySecurity r;
248 	struct sec_desc_buf *sdbuf = NULL;
249 	NTSTATUS status;
250 
251 	r.in.handle = handle;
252 	r.in.sec_info = 0x7;
253 	r.out.sdbuf = &sdbuf;
254 
255 	status = dcerpc_lsa_QuerySecurity_r(samsync_state->b_lsa, mem_ctx, &r);
256 	if (!NT_STATUS_IS_OK(status)) {
257 		torture_comment(tctx, "LSA QuerySecurity failed - %s\n", nt_errstr(status));
258 		return NULL;
259 	}
260 	if (!NT_STATUS_IS_OK(r.out.result)) {
261 		torture_comment(tctx, "LSA QuerySecurity failed - %s\n", nt_errstr(r.out.result));
262 		return NULL;
263 	}
264 
265 	return sdbuf;
266 }
267 
268 #define TEST_UINT64_EQUAL(i1, i2) do {\
269 	if (i1 != i2) {\
270               torture_comment(tctx, "%s: uint64 mismatch: " #i1 ": 0x%016llx (%lld) != " #i2 ": 0x%016llx (%lld)\n", \
271 		     __location__, \
272 		     (long long)i1, (long long)i1, \
273 		     (long long)i2, (long long)i2);\
274 	      ret = false;\
275 	} \
276 } while (0)
277 #define TEST_INT_EQUAL(i1, i2) do {\
278 	if (i1 != i2) {\
279 	      torture_comment(tctx, "%s: integer mismatch: " #i1 ": 0x%08x (%d) != " #i2 ": 0x%08x (%d)\n", \
280 		     __location__, i1, i1, i2, i2);			\
281 	      ret = false;\
282 	} \
283 } while (0)
284 #define TEST_TIME_EQUAL(t1, t2) do {\
285 	if (t1 != t2) {\
286 	      torture_comment(tctx, "%s: NTTIME mismatch: " #t1 ":%s != " #t2 ": %s\n", \
287 		     __location__, nt_time_string(mem_ctx, t1),  nt_time_string(mem_ctx, t2));\
288 	      ret = false;\
289 	} \
290 } while (0)
291 
292 #define TEST_STRING_EQUAL(s1, s2) do {\
293 	if (!((!s1.string || s1.string[0]=='\0') && (!s2.string || s2.string[0]=='\0')) \
294 	    && strcmp_safe(s1.string, s2.string) != 0) {\
295 	      torture_comment(tctx, "%s: string mismatch: " #s1 ":%s != " #s2 ": %s\n", \
296 		     __location__, s1.string, s2.string);\
297 	      ret = false;\
298 	} \
299 } while (0)
300 
301 #define TEST_BINARY_STRING_EQUAL(s1, s2) do {\
302 	if (!((!s1.array || s1.array[0]=='\0') && (!s2.array || s2.array[0]=='\0')) \
303 	    && memcmp(s1.array, s2.array, s1.length * 2) != 0) {\
304 	      torture_comment(tctx, "%s: string mismatch: " #s1 ":%s != " #s2 ": %s\n", \
305 		     __location__, (const char *)s1.array, (const char *)s2.array);\
306 	      ret = false;\
307 	} \
308 } while (0)
309 
310 #define TEST_SID_EQUAL(s1, s2) do {\
311 	if (!dom_sid_equal(s1, s2)) {\
312 	      torture_comment(tctx, "%s: dom_sid mismatch: " #s1 ":%s != " #s2 ": %s\n", \
313 		     __location__, dom_sid_string(mem_ctx, s1), dom_sid_string(mem_ctx, s2));\
314 	      ret = false;\
315 	} \
316 } while (0)
317 
318 /* The ~SEC_DESC_SACL_PRESENT is because we don't, as administrator,
319  * get back the SACL part of the SD when we ask over SAMR */
320 
321 #define TEST_SEC_DESC_EQUAL(sd1, pipe, handle) do {\
322         struct sec_desc_buf *sdbuf = samsync_query_ ##pipe## _sec_desc(tctx, mem_ctx, samsync_state, \
323 						            handle); \
324 	if (!sdbuf || !sdbuf->sd) { \
325                 torture_comment(tctx, "Could not obtain security descriptor to match " #sd1 "\n");\
326 	        ret = false; \
327         } else {\
328 		if (!security_descriptor_mask_equal(sd1.sd, sdbuf->sd, \
329  			    ~SEC_DESC_SACL_PRESENT)) {\
330 			torture_comment(tctx, "Security Descriptor Mismatch for %s:\n", #sd1);\
331 		        ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, "SamSync", sd1.sd);\
332 		        ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, "SamR", sdbuf->sd);\
333 			ret = false;\
334 		}\
335 	}\
336 } while (0)
337 
samsync_handle_domain(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)338 static bool samsync_handle_domain(struct torture_context *tctx, TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
339 			   int database_id, struct netr_DELTA_ENUM *delta)
340 {
341 	struct netr_DELTA_DOMAIN *domain = delta->delta_union.domain;
342 	struct dom_sid *dom_sid;
343 	struct samr_QueryDomainInfo q[14]; /* q[0] will be unused simple for clarity */
344 	union samr_DomainInfo *info[14];
345 	uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
346 	int i;
347 	bool ret = true;
348 
349 	samsync_state->seq_num[database_id] =
350 		domain->sequence_num;
351 	switch (database_id) {
352 	case SAM_DATABASE_DOMAIN:
353 		break;
354 	case SAM_DATABASE_BUILTIN:
355 		if (strcasecmp_m("BUILTIN", domain->domain_name.string) != 0) {
356 			torture_comment(tctx, "BUILTIN domain has different name: %s\n", domain->domain_name.string);
357 		}
358 		break;
359 	case SAM_DATABASE_PRIVS:
360 		torture_comment(tctx, "DOMAIN entry on privs DB!\n");
361 		return false;
362 		break;
363 	}
364 
365 	if (!samsync_state->domain_name[database_id]) {
366 		samsync_state->domain_name[database_id] =
367 			talloc_strdup(samsync_state, domain->domain_name.string);
368 	} else {
369 		if (strcasecmp_m(samsync_state->domain_name[database_id], domain->domain_name.string) != 0) {
370 			torture_comment(tctx, "Domain has name varies!: %s != %s\n", samsync_state->domain_name[database_id],
371 			       domain->domain_name.string);
372 			return false;
373 		}
374 	}
375 
376 	if (!samsync_state->domain_handle[database_id]) {
377 		samsync_state->domain_handle[database_id] =
378 			samsync_open_domain(tctx,
379 					    samsync_state,
380 					    samsync_state,
381 					    samsync_state->domain_name[database_id],
382 					    &dom_sid);
383 	}
384 	if (samsync_state->domain_handle[database_id]) {
385 		samsync_state->sid[database_id] = dom_sid_dup(samsync_state, dom_sid);
386 	}
387 
388 	torture_comment(tctx, "\tsequence_nums[%d/%s]=%llu\n",
389 	       database_id, domain->domain_name.string,
390 	       (long long)samsync_state->seq_num[database_id]);
391 
392 	for (i=0;i<ARRAY_SIZE(levels);i++) {
393 
394 		q[levels[i]].in.domain_handle = samsync_state->domain_handle[database_id];
395 		q[levels[i]].in.level = levels[i];
396 		q[levels[i]].out.info = &info[levels[i]];
397 
398 		torture_assert_ntstatus_ok(tctx,
399 			dcerpc_samr_QueryDomainInfo_r(samsync_state->b_samr, mem_ctx, &q[levels[i]]),
400 			talloc_asprintf(tctx, "QueryDomainInfo level %u failed", q[levels[i]].in.level));
401 		torture_assert_ntstatus_ok(tctx, q[levels[i]].out.result,
402 			talloc_asprintf(tctx, "QueryDomainInfo level %u failed", q[levels[i]].in.level));
403 	}
404 
405 	TEST_STRING_EQUAL(info[5]->info5.domain_name, domain->domain_name);
406 
407 	TEST_STRING_EQUAL(info[2]->general.oem_information, domain->oem_information);
408 	TEST_STRING_EQUAL(info[4]->oem.oem_information, domain->oem_information);
409 	TEST_TIME_EQUAL(info[2]->general.force_logoff_time, domain->force_logoff_time);
410 	TEST_TIME_EQUAL(info[3]->info3.force_logoff_time, domain->force_logoff_time);
411 
412 	TEST_TIME_EQUAL(info[1]->info1.min_password_length, domain->min_password_length);
413 	TEST_TIME_EQUAL(info[1]->info1.password_history_length, domain->password_history_length);
414 	TEST_TIME_EQUAL(info[1]->info1.max_password_age, domain->max_password_age);
415 	TEST_TIME_EQUAL(info[1]->info1.min_password_age, domain->min_password_age);
416 
417 	TEST_UINT64_EQUAL(info[8]->info8.sequence_num,
418 			domain->sequence_num);
419 	TEST_TIME_EQUAL(info[8]->info8.domain_create_time,
420 			domain->domain_create_time);
421 	TEST_TIME_EQUAL(info[13]->info13.domain_create_time,
422 			domain->domain_create_time);
423 
424 	TEST_SEC_DESC_EQUAL(domain->sdbuf, samr, samsync_state->domain_handle[database_id]);
425 
426 	return ret;
427 }
428 
samsync_handle_policy(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)429 static bool samsync_handle_policy(struct torture_context *tctx,
430 				  TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
431 			   int database_id, struct netr_DELTA_ENUM *delta)
432 {
433 	struct netr_DELTA_POLICY *policy = delta->delta_union.policy;
434 
435 	switch (database_id) {
436 	case SAM_DATABASE_DOMAIN:
437 	case SAM_DATABASE_BUILTIN:
438 		break;
439 	case SAM_DATABASE_PRIVS:
440 		torture_comment(tctx, "DOMAIN entry on privs DB!\n");
441 		return false;
442 	}
443 
444 	samsync_state->seq_num[database_id] =
445 		policy->sequence_num;
446 
447 	if (!samsync_state->domain_name[SAM_DATABASE_DOMAIN]) {
448 		samsync_state->domain_name[SAM_DATABASE_DOMAIN] =
449 			talloc_strdup(samsync_state, policy->primary_domain_name.string);
450 	} else {
451 		if (strcasecmp_m(samsync_state->domain_name[SAM_DATABASE_DOMAIN], policy->primary_domain_name.string) != 0) {
452 			torture_comment(tctx, "PRIMARY domain has name varies between DOMAIN and POLICY!: %s != %s\n", samsync_state->domain_name[SAM_DATABASE_DOMAIN],
453 			       policy->primary_domain_name.string);
454 			return false;
455 		}
456 	}
457 
458 	if (!dom_sid_equal(samsync_state->sid[SAM_DATABASE_DOMAIN], policy->sid)) {
459 		torture_comment(tctx, "Domain SID from POLICY (%s) does not match domain sid from SAMR (%s)\n",
460 		       dom_sid_string(mem_ctx, policy->sid), dom_sid_string(mem_ctx, samsync_state->sid[SAM_DATABASE_DOMAIN]));
461 		return false;
462 	}
463 
464 	torture_comment(tctx, "\tsequence_nums[%d/PRIVS]=%llu\n",
465 	       database_id,
466 	       (long long)samsync_state->seq_num[database_id]);
467 	return true;
468 }
469 
samsync_handle_user(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)470 static bool samsync_handle_user(struct torture_context *tctx, TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
471 				int database_id, struct netr_DELTA_ENUM *delta)
472 {
473 	uint32_t rid = delta->delta_id_union.rid;
474 	struct netr_DELTA_USER *user = delta->delta_union.user;
475 	struct netr_SamInfo3 *info3 = NULL;
476 	struct samr_Password lm_hash;
477 	struct samr_Password nt_hash;
478 	struct samr_Password *lm_hash_p = NULL;
479 	struct samr_Password *nt_hash_p = NULL;
480 	const char *domain;
481 	const char *username = user->account_name.string;
482 	NTSTATUS nt_status;
483 	bool ret = true;
484 	struct samr_OpenUser r;
485 	struct samr_QueryUserInfo q;
486 	union samr_UserInfo *info;
487 	struct policy_handle user_handle;
488 	struct samr_GetGroupsForUser getgr;
489 	struct samr_RidWithAttributeArray *rids;
490 
491 	switch (database_id) {
492 	case SAM_DATABASE_DOMAIN:
493 	case SAM_DATABASE_BUILTIN:
494 		break;
495 	case SAM_DATABASE_PRIVS:
496 		torture_comment(tctx, "DOMAIN entry on privs DB!\n");
497 		return false;
498 	}
499 
500 	domain = samsync_state->domain_name[database_id];
501 
502 	if (domain == NULL ||
503 	    samsync_state->domain_handle[database_id] == NULL) {
504 		torture_comment(tctx, "SamSync needs domain information before the users\n");
505 		return false;
506 	}
507 
508 	r.in.domain_handle = samsync_state->domain_handle[database_id];
509 	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
510 	r.in.rid = rid;
511 	r.out.user_handle = &user_handle;
512 
513 	torture_assert_ntstatus_ok(tctx,
514 		dcerpc_samr_OpenUser_r(samsync_state->b_samr, mem_ctx, &r),
515 		talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
516 	torture_assert_ntstatus_ok(tctx, r.out.result,
517 		talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
518 
519 	q.in.user_handle = &user_handle;
520 	q.in.level = 21;
521 	q.out.info = &info;
522 
523 	TEST_SEC_DESC_EQUAL(user->sdbuf, samr, &user_handle);
524 
525 	torture_assert_ntstatus_ok(tctx,
526 		dcerpc_samr_QueryUserInfo_r(samsync_state->b_samr, mem_ctx, &q),
527 		talloc_asprintf(tctx, "OpenUserInfo level %u failed", q.in.level));
528 	torture_assert_ntstatus_ok(tctx, q.out.result,
529 		talloc_asprintf(tctx, "OpenUserInfo level %u failed", q.in.level));
530 
531 	getgr.in.user_handle = &user_handle;
532 	getgr.out.rids = &rids;
533 
534 	torture_assert_ntstatus_ok(tctx,
535 		dcerpc_samr_GetGroupsForUser_r(samsync_state->b_samr, mem_ctx, &getgr),
536 		"GetGroupsForUser failed");
537 	torture_assert_ntstatus_ok(tctx, getgr.out.result,
538 		"GetGroupsForUser failed");
539 
540 	if (!test_samr_handle_Close(samsync_state->b_samr, tctx, &user_handle)) {
541 		torture_comment(tctx, "samr_handle_Close failed\n");
542 		ret = false;
543 	}
544 	if (!ret) {
545 		return false;
546 	}
547 
548 	TEST_STRING_EQUAL(info->info21.account_name, user->account_name);
549 	TEST_STRING_EQUAL(info->info21.full_name, user->full_name);
550 	TEST_INT_EQUAL(info->info21.rid, user->rid);
551 	TEST_INT_EQUAL(info->info21.primary_gid, user->primary_gid);
552 	TEST_STRING_EQUAL(info->info21.home_directory, user->home_directory);
553 	TEST_STRING_EQUAL(info->info21.home_drive, user->home_drive);
554 	TEST_STRING_EQUAL(info->info21.logon_script, user->logon_script);
555 	TEST_STRING_EQUAL(info->info21.description, user->description);
556 	TEST_STRING_EQUAL(info->info21.workstations, user->workstations);
557 
558 	TEST_TIME_EQUAL(info->info21.last_logon, user->last_logon);
559 	TEST_TIME_EQUAL(info->info21.last_logoff, user->last_logoff);
560 
561 
562 	TEST_INT_EQUAL(info->info21.logon_hours.units_per_week,
563 		       user->logon_hours.units_per_week);
564 	if (ret) {
565 		if (memcmp(info->info21.logon_hours.bits, user->logon_hours.bits,
566 			   info->info21.logon_hours.units_per_week/8) != 0) {
567 			torture_comment(tctx, "Logon hours mismatch\n");
568 			ret = false;
569 		}
570 	}
571 
572 	TEST_INT_EQUAL(info->info21.bad_password_count,
573 		       user->bad_password_count);
574 	TEST_INT_EQUAL(info->info21.logon_count,
575 		       user->logon_count);
576 
577 	TEST_TIME_EQUAL(info->info21.last_password_change,
578 		       user->last_password_change);
579 	TEST_TIME_EQUAL(info->info21.acct_expiry,
580 		       user->acct_expiry);
581 
582 	TEST_INT_EQUAL((info->info21.acct_flags & ~ACB_PW_EXPIRED), user->acct_flags);
583 	if (user->acct_flags & ACB_PWNOEXP) {
584 		if (info->info21.acct_flags & ACB_PW_EXPIRED) {
585 			torture_comment(tctx, "ACB flags mismatch: both expired and no expiry!\n");
586 			ret = false;
587 		}
588 		if (info->info21.force_password_change != (NTTIME)0x7FFFFFFFFFFFFFFFULL) {
589 			torture_comment(tctx, "ACB flags mismatch: no password expiry, but force password change 0x%016llx (%lld) != 0x%016llx (%lld)\n",
590 			       (unsigned long long)info->info21.force_password_change,
591 			       (unsigned long long)info->info21.force_password_change,
592 			       (unsigned long long)0x7FFFFFFFFFFFFFFFULL, (unsigned long long)0x7FFFFFFFFFFFFFFFULL
593 				);
594 			ret = false;
595 		}
596 	}
597 
598 	TEST_INT_EQUAL(info->info21.nt_password_set, user->nt_password_present);
599 	TEST_INT_EQUAL(info->info21.lm_password_set, user->lm_password_present);
600 	TEST_INT_EQUAL(info->info21.password_expired, user->password_expired);
601 
602 	TEST_STRING_EQUAL(info->info21.comment, user->comment);
603 	TEST_BINARY_STRING_EQUAL(info->info21.parameters, user->parameters);
604 
605 	TEST_INT_EQUAL(info->info21.country_code, user->country_code);
606 	TEST_INT_EQUAL(info->info21.code_page, user->code_page);
607 
608 	TEST_STRING_EQUAL(info->info21.profile_path, user->profile_path);
609 
610 	if (user->lm_password_present) {
611 		lm_hash_p = &lm_hash;
612 	}
613 	if (user->nt_password_present) {
614 		nt_hash_p = &nt_hash;
615 	}
616 
617 	if (user->user_private_info.SensitiveData) {
618 		DATA_BLOB data;
619 		struct netr_USER_KEYS keys;
620 		enum ndr_err_code ndr_err;
621 		data.data = user->user_private_info.SensitiveData;
622 		data.length = user->user_private_info.DataLength;
623 		ndr_err = ndr_pull_struct_blob(&data, mem_ctx, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
624 		if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
625 			if (keys.keys.keys2.lmpassword.length == 16) {
626 				lm_hash_p = &lm_hash;
627 			}
628 			if (keys.keys.keys2.ntpassword.length == 16) {
629 				nt_hash_p = &nt_hash;
630 			}
631 		} else {
632 			torture_comment(tctx, "Failed to parse Sensitive Data for %s:\n", username);
633 #if 0
634 			dump_data(0, data.data, data.length);
635 #endif
636 			return false;
637 		}
638 	}
639 
640 	if (nt_hash_p) {
641 		DATA_BLOB nt_hash_blob = data_blob_const(nt_hash_p, 16);
642 		DEBUG(100,("ACCOUNT [%s\\%-25s] NTHASH %s\n", samsync_state->domain_name[0], username, data_blob_hex_string_upper(mem_ctx, &nt_hash_blob)));
643 	}
644 	if (lm_hash_p) {
645 		DATA_BLOB lm_hash_blob = data_blob_const(lm_hash_p, 16);
646 		DEBUG(100,("ACCOUNT [%s\\%-25s] LMHASH %s\n", samsync_state->domain_name[0], username, data_blob_hex_string_upper(mem_ctx, &lm_hash_blob)));
647 	}
648 
649 	nt_status = test_SamLogon(tctx,
650 				  samsync_state->p_netlogon_wksta, mem_ctx, samsync_state->creds_netlogon_wksta,
651 				  domain,
652 				  username,
653 				  TEST_WKSTA_MACHINE_NAME,
654 				  lm_hash_p,
655 				  nt_hash_p,
656 				  &info3);
657 
658 	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
659 		if (user->acct_flags & ACB_DISABLED) {
660 			return true;
661 		}
662 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)) {
663 		if (user->acct_flags & ACB_WSTRUST) {
664 			return true;
665 		}
666 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)) {
667 		if (user->acct_flags & ACB_SVRTRUST) {
668 			return true;
669 		}
670 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
671 		if (user->acct_flags & ACB_DOMTRUST) {
672 			return true;
673 		}
674 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
675 		if (user->acct_flags & ACB_DOMTRUST) {
676 			return true;
677 		}
678 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
679 		if (user->acct_flags & ACB_AUTOLOCK) {
680 			return true;
681 		}
682 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) {
683 		if (info->info21.acct_flags & ACB_PW_EXPIRED) {
684 			return true;
685 		}
686 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
687 		if (!lm_hash_p && !nt_hash_p) {
688 			return true;
689 		}
690 	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) {
691 		/* We would need to know the server's current time to test this properly */
692 		return true;
693 	} else if (NT_STATUS_IS_OK(nt_status)) {
694 		TEST_INT_EQUAL(user->rid, info3->base.rid);
695 		TEST_INT_EQUAL(user->primary_gid, info3->base.primary_gid);
696 		/* this is 0x0 from NT4 sp6 */
697 		if (info3->base.acct_flags) {
698 			TEST_INT_EQUAL(user->acct_flags, info3->base.acct_flags);
699 		}
700 		/* this is NULL from NT4 sp6 */
701 		if (info3->base.account_name.string) {
702 			TEST_STRING_EQUAL(user->account_name, info3->base.account_name);
703 		}
704 		/* this is NULL from Win2k3 */
705 		if (info3->base.full_name.string) {
706 			TEST_STRING_EQUAL(user->full_name, info3->base.full_name);
707 		}
708 		TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script);
709 		TEST_STRING_EQUAL(user->profile_path, info3->base.profile_path);
710 		TEST_STRING_EQUAL(user->home_directory, info3->base.home_directory);
711 		TEST_STRING_EQUAL(user->home_drive, info3->base.home_drive);
712 		TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script);
713 
714 
715 		TEST_TIME_EQUAL(user->last_logon, info3->base.logon_time);
716 		TEST_TIME_EQUAL(user->acct_expiry, info3->base.kickoff_time);
717 		TEST_TIME_EQUAL(user->last_password_change, info3->base.last_password_change);
718 		TEST_TIME_EQUAL(info->info21.force_password_change, info3->base.force_password_change);
719 
720 		/* Does the concept of a logoff time ever really
721 		 * exist? (not in any sensible way, according to the
722 		 * doco I read -- abartlet) */
723 
724 		/* This copes with the two different versions of 0 I see */
725 		/* with NT4 sp6 we have the || case */
726 		if (!((user->last_logoff == 0)
727 		      || (info3->base.logoff_time == 0x7fffffffffffffffLL))) {
728 			TEST_TIME_EQUAL(user->last_logoff, info3->base.logoff_time);
729 		}
730 
731 		TEST_INT_EQUAL(rids->count, info3->base.groups.count);
732 		if (rids->count == info3->base.groups.count) {
733 			int i, j;
734 			int count = rids->count;
735 			bool *matched = talloc_zero_array(mem_ctx, bool, rids->count);
736 
737 			for (i = 0; i < count; i++) {
738 				for (j = 0; j < count; j++) {
739 					if ((rids->rids[i].rid ==
740 					     info3->base.groups.rids[j].rid)
741 					    && (rids->rids[i].attributes ==
742 						info3->base.groups.rids[j].attributes)) {
743 							matched[i] = true;
744 						}
745 				}
746 			}
747 
748 			for (i = 0; i < rids->count; i++) {
749 				if (matched[i] == false) {
750 					ret = false;
751 					torture_comment(tctx, "Could not find group RID %u found in getgroups in NETLOGON reply\n",
752 					       rids->rids[i].rid);
753 				}
754 			}
755 		}
756 		return ret;
757 	} else {
758 		torture_comment(tctx, "Could not validate password for user %s\\%s: %s\n",
759 		       domain, username, nt_errstr(nt_status));
760 		return false;
761 	}
762 	return false;
763 }
764 
samsync_handle_alias(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)765 static bool samsync_handle_alias(struct torture_context *tctx,
766 				 TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
767 				 int database_id, struct netr_DELTA_ENUM *delta)
768 {
769 	uint32_t rid = delta->delta_id_union.rid;
770 	struct netr_DELTA_ALIAS *alias = delta->delta_union.alias;
771 	bool ret = true;
772 
773 	struct samr_OpenAlias r;
774 	struct samr_QueryAliasInfo q;
775 	union samr_AliasInfo *info;
776 	struct policy_handle alias_handle;
777 
778 	switch (database_id) {
779 	case SAM_DATABASE_DOMAIN:
780 	case SAM_DATABASE_BUILTIN:
781 		break;
782 	case SAM_DATABASE_PRIVS:
783 		torture_comment(tctx, "DOMAIN entry on privs DB!\n");
784 		return false;
785 	}
786 
787 	if (samsync_state->domain_name[database_id] == NULL ||
788 	    samsync_state->domain_handle[database_id] == NULL) {
789 		torture_comment(tctx, "SamSync needs domain information before the users\n");
790 		return false;
791 	}
792 
793 	r.in.domain_handle = samsync_state->domain_handle[database_id];
794 	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
795 	r.in.rid = rid;
796 	r.out.alias_handle = &alias_handle;
797 
798 	torture_assert_ntstatus_ok(tctx,
799 		dcerpc_samr_OpenAlias_r(samsync_state->b_samr, mem_ctx, &r),
800 		talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
801 	torture_assert_ntstatus_ok(tctx, r.out.result,
802 		talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
803 
804 	q.in.alias_handle = &alias_handle;
805 	q.in.level = 1;
806 	q.out.info = &info;
807 
808 	TEST_SEC_DESC_EQUAL(alias->sdbuf, samr, &alias_handle);
809 
810 	torture_assert_ntstatus_ok(tctx,
811 		dcerpc_samr_QueryAliasInfo_r(samsync_state->b_samr, mem_ctx, &q),
812 		"QueryAliasInfo failed");
813 	if (!test_samr_handle_Close(samsync_state->b_samr, tctx, &alias_handle)) {
814 		return false;
815 	}
816 
817 	if (!NT_STATUS_IS_OK(q.out.result)) {
818 		torture_comment(tctx, "QueryAliasInfo level %u failed - %s\n",
819 		       q.in.level, nt_errstr(q.out.result));
820 		return false;
821 	}
822 
823 	TEST_STRING_EQUAL(info->all.name, alias->alias_name);
824 	TEST_STRING_EQUAL(info->all.description, alias->description);
825 	return ret;
826 }
827 
samsync_handle_group(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)828 static bool samsync_handle_group(struct torture_context *tctx,
829 				 TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
830 				 int database_id, struct netr_DELTA_ENUM *delta)
831 {
832 	uint32_t rid = delta->delta_id_union.rid;
833 	struct netr_DELTA_GROUP *group = delta->delta_union.group;
834 	bool ret = true;
835 
836 	struct samr_OpenGroup r;
837 	struct samr_QueryGroupInfo q;
838 	union samr_GroupInfo *info;
839 	struct policy_handle group_handle;
840 
841 	switch (database_id) {
842 	case SAM_DATABASE_DOMAIN:
843 	case SAM_DATABASE_BUILTIN:
844 		break;
845 	case SAM_DATABASE_PRIVS:
846 		torture_comment(tctx, "DOMAIN entry on privs DB!\n");
847 		return false;
848 	}
849 
850 	if (samsync_state->domain_name[database_id] == NULL ||
851 	    samsync_state->domain_handle[database_id] == NULL) {
852 		torture_comment(tctx, "SamSync needs domain information before the users\n");
853 		return false;
854 	}
855 
856 	r.in.domain_handle = samsync_state->domain_handle[database_id];
857 	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
858 	r.in.rid = rid;
859 	r.out.group_handle = &group_handle;
860 
861 	torture_assert_ntstatus_ok(tctx,
862 		dcerpc_samr_OpenGroup_r(samsync_state->b_samr, mem_ctx, &r),
863 		talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
864 	torture_assert_ntstatus_ok(tctx, r.out.result,
865 		talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
866 
867 	q.in.group_handle = &group_handle;
868 	q.in.level = 1;
869 	q.out.info = &info;
870 
871 	TEST_SEC_DESC_EQUAL(group->sdbuf, samr, &group_handle);
872 
873 	torture_assert_ntstatus_ok(tctx,
874 		dcerpc_samr_QueryGroupInfo_r(samsync_state->b_samr, mem_ctx, &q),
875 		"QueryGroupInfo failed");
876 	if (!test_samr_handle_Close(samsync_state->b_samr, tctx, &group_handle)) {
877 		return false;
878 	}
879 
880 	if (!NT_STATUS_IS_OK(q.out.result)) {
881 		torture_comment(tctx, "QueryGroupInfo level %u failed - %s\n",
882 		       q.in.level, nt_errstr(q.out.result));
883 		return false;
884 	}
885 
886 	TEST_STRING_EQUAL(info->all.name, group->group_name);
887 	TEST_INT_EQUAL(info->all.attributes, group->attributes);
888 	TEST_STRING_EQUAL(info->all.description, group->description);
889 	return ret;
890 }
891 
samsync_handle_secret(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)892 static bool samsync_handle_secret(struct torture_context *tctx,
893 				  TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
894 				  int database_id, struct netr_DELTA_ENUM *delta)
895 {
896 	struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
897 	const char *name = delta->delta_id_union.name;
898 	struct samsync_secret *nsec = talloc(samsync_state, struct samsync_secret);
899 	struct samsync_secret *old = talloc(mem_ctx, struct samsync_secret);
900 	struct lsa_QuerySecret q;
901 	struct lsa_OpenSecret o;
902 	struct policy_handle sec_handle;
903 	struct lsa_DATA_BUF_PTR bufp1;
904 	struct lsa_DATA_BUF_PTR bufp2;
905 	NTTIME nsec_mtime;
906 	NTTIME old_mtime;
907 	bool ret = true;
908 	DATA_BLOB lsa_blob1, lsa_blob_out, session_key;
909 	NTSTATUS status;
910 
911 	nsec->name = talloc_strdup(nsec, name);
912 	nsec->secret = data_blob_talloc(nsec, secret->current_cipher.cipher_data, secret->current_cipher.maxlen);
913 	nsec->mtime = secret->current_cipher_set_time;
914 
915 	DLIST_ADD(samsync_state->secrets, nsec);
916 
917 	old->name = talloc_strdup(old, name);
918 	old->secret = data_blob_const(secret->old_cipher.cipher_data, secret->old_cipher.maxlen);
919 	old->mtime = secret->old_cipher_set_time;
920 
921 	o.in.handle = samsync_state->lsa_handle;
922 	o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
923 	o.in.name.string = name;
924 	o.out.sec_handle = &sec_handle;
925 
926 	torture_assert_ntstatus_ok(tctx,
927 		dcerpc_lsa_OpenSecret_r(samsync_state->b_lsa, mem_ctx, &o),
928 		"OpenSecret failed");
929 	torture_assert_ntstatus_ok(tctx, o.out.result,
930 		"OpenSecret failed");
931 
932 /*
933   We would like to do this, but it is NOT_SUPPORTED on win2k3
934   TEST_SEC_DESC_EQUAL(secret->sdbuf, lsa, &sec_handle);
935 */
936 	status = dcerpc_fetch_session_key(samsync_state->p_lsa, &session_key);
937 	if (!NT_STATUS_IS_OK(status)) {
938 		torture_comment(tctx, "dcerpc_fetch_session_key failed - %s\n", nt_errstr(status));
939 		return false;
940 	}
941 
942 
943 	ZERO_STRUCT(nsec_mtime);
944 	ZERO_STRUCT(old_mtime);
945 
946 	/* fetch the secret back again */
947 	q.in.sec_handle = &sec_handle;
948 	q.in.new_val = &bufp1;
949 	q.in.new_mtime = &nsec_mtime;
950 	q.in.old_val = &bufp2;
951 	q.in.old_mtime = &old_mtime;
952 
953 	bufp1.buf = NULL;
954 	bufp2.buf = NULL;
955 
956 	torture_assert_ntstatus_ok(tctx,
957 		dcerpc_lsa_QuerySecret_r(samsync_state->b_lsa, mem_ctx, &q),
958 		"QuerySecret failed");
959 	if (NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, q.out.result)) {
960 		/* some things are just off limits */
961 		return true;
962 	} else if (!NT_STATUS_IS_OK(q.out.result)) {
963 		torture_comment(tctx, "QuerySecret failed - %s\n", nt_errstr(q.out.result));
964 		return false;
965 	}
966 
967 	if (q.out.old_val->buf == NULL) {
968 		/* probably just not available due to ACLs */
969 	} else {
970 		lsa_blob1.data = q.out.old_val->buf->data;
971 		lsa_blob1.length = q.out.old_val->buf->length;
972 
973 		status = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key, &lsa_blob_out);
974 		if (!NT_STATUS_IS_OK(status)) {
975 			torture_comment(tctx, "Failed to decrypt secrets OLD blob: %s\n", nt_errstr(status));
976 			return false;
977 		}
978 
979 		if (!q.out.old_mtime) {
980 			torture_comment(tctx, "OLD mtime not available on LSA for secret %s\n", old->name);
981 			ret = false;
982 		}
983 		if (old->mtime != *q.out.old_mtime) {
984 			torture_comment(tctx, "OLD mtime on secret %s does not match between SAMSYNC (%s) and LSA (%s)\n",
985 			       old->name, nt_time_string(mem_ctx, old->mtime),
986 			       nt_time_string(mem_ctx, *q.out.old_mtime));
987 			ret = false;
988 		}
989 
990 		if (old->secret.length != lsa_blob_out.length) {
991 			torture_comment(tctx, "Returned secret %s doesn't match: %d != %d\n",
992 			       old->name, (int)old->secret.length, (int)lsa_blob_out.length);
993 			ret = false;
994 		} else if (memcmp(lsa_blob_out.data,
995 			   old->secret.data, old->secret.length) != 0) {
996 			torture_comment(tctx, "Returned secret %s doesn't match: \n",
997 			       old->name);
998 			DEBUG(1, ("SamSync Secret:\n"));
999 			dump_data(1, old->secret.data, old->secret.length);
1000 			DEBUG(1, ("LSA Secret:\n"));
1001 			dump_data(1, lsa_blob_out.data, lsa_blob_out.length);
1002 			ret = false;
1003 		}
1004 
1005 	}
1006 
1007 	if (q.out.new_val->buf == NULL) {
1008 		/* probably just not available due to ACLs */
1009 	} else {
1010 		lsa_blob1.data = q.out.new_val->buf->data;
1011 		lsa_blob1.length = q.out.new_val->buf->length;
1012 
1013 		status = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key, &lsa_blob_out);
1014 		if (!NT_STATUS_IS_OK(status)) {
1015 			torture_comment(tctx, "Failed to decrypt secrets OLD blob\n");
1016 			return false;
1017 		}
1018 
1019 		if (!q.out.new_mtime) {
1020 			torture_comment(tctx, "NEW mtime not available on LSA for secret %s\n", nsec->name);
1021 			ret = false;
1022 		}
1023 		if (nsec->mtime != *q.out.new_mtime) {
1024 			torture_comment(tctx, "NEW mtime on secret %s does not match between SAMSYNC (%s) and LSA (%s)\n",
1025 			       nsec->name, nt_time_string(mem_ctx, nsec->mtime),
1026 			       nt_time_string(mem_ctx, *q.out.new_mtime));
1027 			ret = false;
1028 		}
1029 
1030 		if (nsec->secret.length != lsa_blob_out.length) {
1031 			torture_comment(tctx, "Returned secret %s doesn't match: %d != %d\n",
1032 			       nsec->name, (int)nsec->secret.length, (int)lsa_blob_out.length);
1033 			ret = false;
1034 		} else if (memcmp(lsa_blob_out.data,
1035 			   nsec->secret.data, nsec->secret.length) != 0) {
1036 			torture_comment(tctx, "Returned secret %s doesn't match: \n",
1037 			       nsec->name);
1038 			DEBUG(1, ("SamSync Secret:\n"));
1039 			dump_data(1, nsec->secret.data, nsec->secret.length);
1040 			DEBUG(1, ("LSA Secret:\n"));
1041 			dump_data(1, lsa_blob_out.data, lsa_blob_out.length);
1042 			ret = false;
1043 		}
1044 	}
1045 
1046 	return ret;
1047 }
1048 
samsync_handle_trusted_domain(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)1049 static bool samsync_handle_trusted_domain(struct torture_context *tctx,
1050 					  TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
1051 					  int database_id, struct netr_DELTA_ENUM *delta)
1052 {
1053 	bool ret = true;
1054 	struct netr_DELTA_TRUSTED_DOMAIN *trusted_domain = delta->delta_union.trusted_domain;
1055 	struct dom_sid *dom_sid = delta->delta_id_union.sid;
1056 
1057 	struct samsync_trusted_domain *ndom = talloc(samsync_state, struct samsync_trusted_domain);
1058 	struct lsa_OpenTrustedDomain t;
1059 	struct policy_handle trustdom_handle;
1060 	struct lsa_QueryTrustedDomainInfo q;
1061 	union lsa_TrustedDomainInfo *info[9];
1062 	union lsa_TrustedDomainInfo *_info = NULL;
1063 	int levels [] = {1, 3, 8};
1064 	int i;
1065 
1066 	ndom->name = talloc_strdup(ndom, trusted_domain->domain_name.string);
1067 	ndom->sid = dom_sid_dup(ndom, dom_sid);
1068 
1069 	t.in.handle = samsync_state->lsa_handle;
1070 	t.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1071 	t.in.sid = dom_sid;
1072 	t.out.trustdom_handle = &trustdom_handle;
1073 
1074 	torture_assert_ntstatus_ok(tctx,
1075 		dcerpc_lsa_OpenTrustedDomain_r(samsync_state->b_lsa, mem_ctx, &t),
1076 		"OpenTrustedDomain failed");
1077 	torture_assert_ntstatus_ok(tctx, t.out.result,
1078 		"OpenTrustedDomain failed");
1079 
1080 	for (i=0; i< ARRAY_SIZE(levels); i++) {
1081 		q.in.trustdom_handle = &trustdom_handle;
1082 		q.in.level = levels[i];
1083 		q.out.info = &_info;
1084 		torture_assert_ntstatus_ok(tctx,
1085 			dcerpc_lsa_QueryTrustedDomainInfo_r(samsync_state->b_lsa, mem_ctx, &q),
1086 			"QueryTrustedDomainInfo failed");
1087 		if (!NT_STATUS_IS_OK(q.out.result)) {
1088 			if (q.in.level == 8 && NT_STATUS_EQUAL(q.out.result, NT_STATUS_INVALID_PARAMETER)) {
1089 				info[levels[i]] = NULL;
1090 				continue;
1091 			}
1092 			torture_comment(tctx, "QueryInfoTrustedDomain level %d failed - %s\n",
1093 			       levels[i], nt_errstr(q.out.result));
1094 			return false;
1095 		}
1096 		info[levels[i]]  = _info;
1097 	}
1098 
1099 	if (info[8]) {
1100 		TEST_SID_EQUAL(info[8]->full_info.info_ex.sid, dom_sid);
1101 		TEST_STRING_EQUAL(info[8]->full_info.info_ex.netbios_name, trusted_domain->domain_name);
1102 	}
1103 	TEST_STRING_EQUAL(info[1]->name.netbios_name, trusted_domain->domain_name);
1104 	TEST_INT_EQUAL(info[3]->posix_offset.posix_offset, trusted_domain->posix_offset);
1105 /*
1106   We would like to do this, but it is NOT_SUPPORTED on win2k3
1107 	TEST_SEC_DESC_EQUAL(trusted_domain->sdbuf, lsa, &trustdom_handle);
1108 */
1109 	DLIST_ADD(samsync_state->trusted_domains, ndom);
1110 
1111 	return ret;
1112 }
1113 
samsync_handle_account(struct torture_context * tctx,TALLOC_CTX * mem_ctx,struct samsync_state * samsync_state,int database_id,struct netr_DELTA_ENUM * delta)1114 static bool samsync_handle_account(struct torture_context *tctx,
1115 				   TALLOC_CTX *mem_ctx, struct samsync_state *samsync_state,
1116 					  int database_id, struct netr_DELTA_ENUM *delta)
1117 {
1118 	bool ret = true;
1119 	struct netr_DELTA_ACCOUNT *account = delta->delta_union.account;
1120 	struct dom_sid *dom_sid = delta->delta_id_union.sid;
1121 
1122 	struct lsa_OpenAccount a;
1123 	struct policy_handle acct_handle;
1124 	struct lsa_EnumPrivsAccount e;
1125 	struct lsa_PrivilegeSet *privs = NULL;
1126 	struct lsa_LookupPrivName r;
1127 
1128 	int i, j;
1129 
1130 	bool *found_priv_in_lsa;
1131 
1132 	a.in.handle = samsync_state->lsa_handle;
1133 	a.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1134 	a.in.sid = dom_sid;
1135 	a.out.acct_handle = &acct_handle;
1136 
1137 	torture_assert_ntstatus_ok(tctx,
1138 		dcerpc_lsa_OpenAccount_r(samsync_state->b_lsa, mem_ctx, &a),
1139 		"OpenAccount failed");
1140 	torture_assert_ntstatus_ok(tctx, a.out.result,
1141 		"OpenAccount failed");
1142 
1143 	TEST_SEC_DESC_EQUAL(account->sdbuf, lsa, &acct_handle);
1144 
1145 	found_priv_in_lsa = talloc_zero_array(mem_ctx, bool, account->privilege_entries);
1146 
1147 	e.in.handle = &acct_handle;
1148 	e.out.privs = &privs;
1149 
1150 	torture_assert_ntstatus_ok(tctx,
1151 		dcerpc_lsa_EnumPrivsAccount_r(samsync_state->b_lsa, mem_ctx, &e),
1152 		"EnumPrivsAccount failed");
1153 	torture_assert_ntstatus_ok(tctx, e.out.result,
1154 		"EnumPrivsAccount failed");
1155 
1156 	if ((account->privilege_entries && !privs)) {
1157 		torture_comment(tctx, "Account %s has privileges in SamSync, but not LSA\n",
1158 		       dom_sid_string(mem_ctx, dom_sid));
1159 		return false;
1160 	}
1161 
1162 	if (!account->privilege_entries && privs && privs->count) {
1163 		torture_comment(tctx, "Account %s has privileges in LSA, but not SamSync\n",
1164 		       dom_sid_string(mem_ctx, dom_sid));
1165 		return false;
1166 	}
1167 
1168 	TEST_INT_EQUAL(account->privilege_entries, privs->count);
1169 
1170 	for (i=0;i< privs->count; i++) {
1171 
1172 		struct lsa_StringLarge *name = NULL;
1173 
1174 		r.in.handle = samsync_state->lsa_handle;
1175 		r.in.luid = &privs->set[i].luid;
1176 		r.out.name = &name;
1177 
1178 		torture_assert_ntstatus_ok(tctx,
1179 			dcerpc_lsa_LookupPrivName_r(samsync_state->b_lsa, mem_ctx, &r),
1180 			"\nLookupPrivName failed");
1181 		torture_assert_ntstatus_ok(tctx, r.out.result,
1182 			"\nLookupPrivName failed");
1183 
1184 		if (!r.out.name) {
1185 			torture_comment(tctx, "\nLookupPrivName failed to return a name\n");
1186 			return false;
1187 		}
1188 		for (j=0;j<account->privilege_entries; j++) {
1189 			if (strcmp(name->string, account->privilege_name[j].string) == 0) {
1190 				found_priv_in_lsa[j] = true;
1191 				break;
1192 			}
1193 		}
1194 	}
1195 	for (j=0;j<account->privilege_entries; j++) {
1196 		if (!found_priv_in_lsa[j]) {
1197 			torture_comment(tctx, "Privilege %s on account %s not found in LSA\n", account->privilege_name[j].string,
1198 			       dom_sid_string(mem_ctx, dom_sid));
1199 			ret = false;
1200 		}
1201 	}
1202 	return ret;
1203 }
1204 
1205 /*
1206   try a netlogon DatabaseSync
1207 */
test_DatabaseSync(struct torture_context * tctx,struct samsync_state * samsync_state,TALLOC_CTX * mem_ctx)1208 static bool test_DatabaseSync(struct torture_context *tctx,
1209 							  struct samsync_state *samsync_state,
1210 							  TALLOC_CTX *mem_ctx)
1211 {
1212 	TALLOC_CTX *loop_ctx, *delta_ctx, *trustdom_ctx;
1213 	struct netr_DatabaseSync r;
1214 	const enum netr_SamDatabaseID database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS};
1215 	int i, d;
1216 	bool ret = true;
1217 	struct samsync_trusted_domain *t;
1218 	struct samsync_secret *s;
1219 	struct netr_Authenticator return_authenticator, credential;
1220 	struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
1221 
1222 	const char *domain, *username;
1223 
1224 	ZERO_STRUCT(return_authenticator);
1225 
1226 	r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(samsync_state->p));
1227 	r.in.computername = TEST_MACHINE_NAME;
1228 	r.in.preferredmaximumlength = (uint32_t)-1;
1229 	r.in.return_authenticator = &return_authenticator;
1230 	r.out.return_authenticator = &return_authenticator;
1231 	r.out.delta_enum_array = &delta_enum_array;
1232 
1233 	for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1234 
1235 		uint32_t sync_context = 0;
1236 
1237 		r.in.database_id = database_ids[i];
1238 		r.in.sync_context = &sync_context;
1239 		r.out.sync_context = &sync_context;
1240 
1241 		torture_comment(tctx, "Testing DatabaseSync of id %d\n", r.in.database_id);
1242 
1243 		do {
1244 			loop_ctx = talloc_named(mem_ctx, 0, "DatabaseSync loop context");
1245 			netlogon_creds_client_authenticator(samsync_state->creds, &credential);
1246 
1247 			r.in.credential = &credential;
1248 
1249 			torture_assert_ntstatus_ok(tctx,
1250 				dcerpc_netr_DatabaseSync_r(samsync_state->b, loop_ctx, &r),
1251 				"DatabaseSync failed");
1252 			if (!NT_STATUS_IS_OK(r.out.result) &&
1253 			    !NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
1254 				torture_comment(tctx, "DatabaseSync - %s\n", nt_errstr(r.out.result));
1255 				ret = false;
1256 				break;
1257 			}
1258 
1259 			if (!netlogon_creds_client_check(samsync_state->creds, &r.out.return_authenticator->cred)) {
1260 				torture_comment(tctx, "Credential chaining failed\n");
1261 			}
1262 
1263 			r.in.sync_context = r.out.sync_context;
1264 
1265 			for (d=0; d < delta_enum_array->num_deltas; d++) {
1266 				delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context");
1267 
1268 				if (!NT_STATUS_IS_OK(samsync_fix_delta(delta_ctx, samsync_state->creds,
1269 								       r.in.database_id,
1270 								       &delta_enum_array->delta_enum[d]))) {
1271 					torture_comment(tctx, "Failed to decrypt delta\n");
1272 					ret = false;
1273 				}
1274 
1275 				switch (delta_enum_array->delta_enum[d].delta_type) {
1276 				case NETR_DELTA_DOMAIN:
1277 					if (!samsync_handle_domain(tctx, delta_ctx, samsync_state,
1278 								   r.in.database_id, &delta_enum_array->delta_enum[d])) {
1279 						torture_comment(tctx, "Failed to handle DELTA_DOMAIN\n");
1280 						ret = false;
1281 					}
1282 					break;
1283 				case NETR_DELTA_GROUP:
1284 					if (!samsync_handle_group(tctx, delta_ctx, samsync_state,
1285 								  r.in.database_id, &delta_enum_array->delta_enum[d])) {
1286 						torture_comment(tctx, "Failed to handle DELTA_USER\n");
1287 						ret = false;
1288 					}
1289 					break;
1290 				case NETR_DELTA_USER:
1291 					if (!samsync_handle_user(tctx, delta_ctx, samsync_state,
1292 								 r.in.database_id, &delta_enum_array->delta_enum[d])) {
1293 						torture_comment(tctx, "Failed to handle DELTA_USER\n");
1294 						ret = false;
1295 					}
1296 					break;
1297 				case NETR_DELTA_ALIAS:
1298 					if (!samsync_handle_alias(tctx, delta_ctx, samsync_state,
1299 								  r.in.database_id, &delta_enum_array->delta_enum[d])) {
1300 						torture_comment(tctx, "Failed to handle DELTA_ALIAS\n");
1301 						ret = false;
1302 					}
1303 					break;
1304 				case NETR_DELTA_POLICY:
1305 					if (!samsync_handle_policy(tctx, delta_ctx, samsync_state,
1306 								   r.in.database_id, &delta_enum_array->delta_enum[d])) {
1307 						torture_comment(tctx, "Failed to handle DELTA_POLICY\n");
1308 						ret = false;
1309 					}
1310 					break;
1311 				case NETR_DELTA_TRUSTED_DOMAIN:
1312 					if (!samsync_handle_trusted_domain(tctx, delta_ctx, samsync_state,
1313 									   r.in.database_id, &delta_enum_array->delta_enum[d])) {
1314 						torture_comment(tctx, "Failed to handle DELTA_TRUSTED_DOMAIN\n");
1315 						ret = false;
1316 					}
1317 					break;
1318 				case NETR_DELTA_ACCOUNT:
1319 					if (!samsync_handle_account(tctx, delta_ctx, samsync_state,
1320 								    r.in.database_id, &delta_enum_array->delta_enum[d])) {
1321 						torture_comment(tctx, "Failed to handle DELTA_ACCOUNT\n");
1322 						ret = false;
1323 					}
1324 					break;
1325 				case NETR_DELTA_SECRET:
1326 					if (!samsync_handle_secret(tctx, delta_ctx, samsync_state,
1327 								   r.in.database_id, &delta_enum_array->delta_enum[d])) {
1328 						torture_comment(tctx, "Failed to handle DELTA_SECRET\n");
1329 						ret = false;
1330 					}
1331 					break;
1332 				case NETR_DELTA_GROUP_MEMBER:
1333 				case NETR_DELTA_ALIAS_MEMBER:
1334 					/* These are harder to cross-check, and we expect them */
1335 					break;
1336 				case NETR_DELTA_DELETE_GROUP:
1337 				case NETR_DELTA_RENAME_GROUP:
1338 				case NETR_DELTA_DELETE_USER:
1339 				case NETR_DELTA_RENAME_USER:
1340 				case NETR_DELTA_DELETE_ALIAS:
1341 				case NETR_DELTA_RENAME_ALIAS:
1342 				case NETR_DELTA_DELETE_TRUST:
1343 				case NETR_DELTA_DELETE_ACCOUNT:
1344 				case NETR_DELTA_DELETE_SECRET:
1345 				case NETR_DELTA_DELETE_GROUP2:
1346 				case NETR_DELTA_DELETE_USER2:
1347 				case NETR_DELTA_MODIFY_COUNT:
1348 				default:
1349 					torture_comment(tctx, "Uxpected delta type %d\n", delta_enum_array->delta_enum[d].delta_type);
1350 					ret = false;
1351 					break;
1352 				}
1353 				talloc_free(delta_ctx);
1354 			}
1355 			talloc_free(loop_ctx);
1356 		} while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1357 
1358 	}
1359 
1360 	domain = samsync_state->domain_name[SAM_DATABASE_DOMAIN];
1361 	if (!domain) {
1362 		torture_comment(tctx, "Never got a DOMAIN object in samsync!\n");
1363 		return false;
1364 	}
1365 
1366 	trustdom_ctx = talloc_named(mem_ctx, 0, "test_DatabaseSync Trusted domains context");
1367 
1368 	username = talloc_asprintf(trustdom_ctx, "%s$", domain);
1369 	for (t=samsync_state->trusted_domains; t; t=t->next) {
1370 		char *secret_name = talloc_asprintf(trustdom_ctx, "G$$%s", t->name);
1371 		for (s=samsync_state->secrets; s; s=s->next) {
1372 			if (strcasecmp_m(s->name, secret_name) == 0) {
1373 				NTSTATUS nt_status;
1374 				struct samr_Password nt_hash;
1375 				mdfour(nt_hash.hash, s->secret.data, s->secret.length);
1376 
1377 				torture_comment(tctx, "Checking password for %s\\%s\n", t->name, username);
1378 				nt_status = test_SamLogon(tctx,
1379 							  samsync_state->p_netlogon_wksta, trustdom_ctx, samsync_state->creds_netlogon_wksta,
1380 							  t->name,
1381 							  username,
1382 							  TEST_WKSTA_MACHINE_NAME,
1383 							  NULL,
1384 							  &nt_hash,
1385 							  NULL);
1386 				if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_LOGON_SERVERS)) {
1387 					torture_comment(tctx, "Verifiction of trust password to %s failed: %s (the trusted domain is not available)\n",
1388 					       t->name, nt_errstr(nt_status));
1389 
1390 					break;
1391 				}
1392 				if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
1393 					torture_comment(tctx, "Verifiction of trust password to %s: should have failed (nologon interdomain trust account), instead: %s\n",
1394 					       t->name, nt_errstr(nt_status));
1395 					ret = false;
1396 				}
1397 
1398 				/* break it */
1399 				nt_hash.hash[0]++;
1400 				nt_status = test_SamLogon(tctx,
1401 							  samsync_state->p_netlogon_wksta, trustdom_ctx, samsync_state->creds_netlogon_wksta,
1402 							  t->name,
1403 							  username,
1404 							  TEST_WKSTA_MACHINE_NAME,
1405 							  NULL,
1406 							  &nt_hash,
1407 							  NULL);
1408 
1409 				if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
1410 					torture_comment(tctx, "Verifiction of trust password to %s: should have failed (wrong password), instead: %s\n",
1411 					       t->name, nt_errstr(nt_status));
1412 					ret = false;
1413 				}
1414 
1415 				break;
1416 			}
1417 		}
1418 	}
1419 	talloc_free(trustdom_ctx);
1420 	return ret;
1421 }
1422 
1423 
1424 /*
1425   try a netlogon DatabaseDeltas
1426 */
test_DatabaseDeltas(struct torture_context * tctx,struct samsync_state * samsync_state,TALLOC_CTX * mem_ctx)1427 static bool test_DatabaseDeltas(struct torture_context *tctx,
1428 				struct samsync_state *samsync_state, TALLOC_CTX *mem_ctx)
1429 {
1430 	TALLOC_CTX *loop_ctx;
1431 	struct netr_DatabaseDeltas r;
1432 	struct netr_Authenticator credential;
1433 	struct netr_Authenticator return_authenticator;
1434 	struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
1435 	const uint32_t database_ids[] = {0, 1, 2};
1436 	int i;
1437 	bool ret = true;
1438 
1439 	ZERO_STRUCT(return_authenticator);
1440 
1441 	r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(samsync_state->p));
1442 	r.in.computername = TEST_MACHINE_NAME;
1443 	r.in.credential = &credential;
1444 	r.in.preferredmaximumlength = (uint32_t)-1;
1445 	r.in.return_authenticator = &return_authenticator;
1446 	r.out.return_authenticator = &return_authenticator;
1447 	r.out.delta_enum_array = &delta_enum_array;
1448 
1449 	for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1450 
1451 		uint64_t seq_num = samsync_state->seq_num[i];
1452 
1453 		r.in.database_id = database_ids[i];
1454 		r.in.sequence_num = &seq_num;
1455 		r.out.sequence_num = &seq_num;
1456 
1457 		if (seq_num == 0) continue;
1458 
1459 		/* this shows that the bdc doesn't need to do a single call for
1460 		 * each seqnumber, and the pdc doesn't need to know about old values
1461 		 * -- metze
1462 		 */
1463 		seq_num -= 10;
1464 
1465 		torture_comment(tctx, "Testing DatabaseDeltas of id %d at %llu\n",
1466 		       r.in.database_id, (long long)seq_num);
1467 
1468 		do {
1469 			loop_ctx = talloc_named(mem_ctx, 0, "test_DatabaseDeltas loop context");
1470 			netlogon_creds_client_authenticator(samsync_state->creds, &credential);
1471 
1472 			torture_assert_ntstatus_ok(tctx,
1473 				dcerpc_netr_DatabaseDeltas_r(samsync_state->b, loop_ctx, &r),
1474 				"DatabaseDeltas failed");
1475 			if (!NT_STATUS_IS_OK(r.out.result) &&
1476 			    !NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
1477 			    !NT_STATUS_EQUAL(r.out.result, NT_STATUS_SYNCHRONIZATION_REQUIRED)) {
1478 				torture_comment(tctx, "DatabaseDeltas - %s\n", nt_errstr(r.out.result));
1479 				ret = false;
1480 			}
1481 
1482 			if (!netlogon_creds_client_check(samsync_state->creds, &return_authenticator.cred)) {
1483 				torture_comment(tctx, "Credential chaining failed\n");
1484 			}
1485 
1486 			seq_num++;
1487 			talloc_free(loop_ctx);
1488 		} while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1489 	}
1490 
1491 	return ret;
1492 }
1493 
1494 
1495 /*
1496   try a netlogon DatabaseSync2
1497 */
test_DatabaseSync2(struct torture_context * tctx,struct dcerpc_pipe * p,TALLOC_CTX * mem_ctx,struct netlogon_creds_CredentialState * creds)1498 static bool test_DatabaseSync2(struct torture_context *tctx,
1499 			       struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1500 			       struct netlogon_creds_CredentialState *creds)
1501 {
1502 	TALLOC_CTX *loop_ctx;
1503 	struct netr_DatabaseSync2 r;
1504 	const uint32_t database_ids[] = {0, 1, 2};
1505 	int i;
1506 	bool ret = true;
1507 	struct netr_Authenticator return_authenticator, credential;
1508 	struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
1509 	struct dcerpc_binding_handle *b = p->binding_handle;
1510 
1511 	ZERO_STRUCT(return_authenticator);
1512 
1513 	r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1514 	r.in.computername = TEST_MACHINE_NAME;
1515 	r.in.preferredmaximumlength = (uint32_t)-1;
1516 	r.in.return_authenticator = &return_authenticator;
1517 	r.out.return_authenticator = &return_authenticator;
1518 	r.out.delta_enum_array = &delta_enum_array;
1519 
1520 	for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1521 
1522 		uint32_t sync_context = 0;
1523 
1524 		r.in.database_id = database_ids[i];
1525 		r.in.sync_context = &sync_context;
1526 		r.out.sync_context = &sync_context;
1527 		r.in.restart_state = 0;
1528 
1529 		torture_comment(tctx, "Testing DatabaseSync2 of id %d\n", r.in.database_id);
1530 
1531 		do {
1532 			loop_ctx = talloc_named(mem_ctx, 0, "test_DatabaseSync2 loop context");
1533 			netlogon_creds_client_authenticator(creds, &credential);
1534 
1535 			r.in.credential = &credential;
1536 
1537 			torture_assert_ntstatus_ok(tctx,
1538 				dcerpc_netr_DatabaseSync2_r(b, loop_ctx, &r),
1539 				"DatabaseSync2 failed");
1540 			if (!NT_STATUS_IS_OK(r.out.result) &&
1541 			    !NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
1542 				torture_comment(tctx, "DatabaseSync2 - %s\n", nt_errstr(r.out.result));
1543 				ret = false;
1544 			}
1545 
1546 			if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) {
1547 				torture_comment(tctx, "Credential chaining failed\n");
1548 			}
1549 
1550 			talloc_free(loop_ctx);
1551 		} while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1552 	}
1553 
1554 	return ret;
1555 }
1556 
1557 
1558 
torture_rpc_samsync(struct torture_context * torture)1559 bool torture_rpc_samsync(struct torture_context *torture)
1560 {
1561         NTSTATUS status;
1562 	TALLOC_CTX *mem_ctx;
1563 	bool ret = true;
1564 	struct test_join *join_ctx;
1565 	struct test_join *join_ctx2;
1566 	struct test_join *user_ctx;
1567 	const char *machine_password;
1568 	const char *wksta_machine_password;
1569 	struct dcerpc_binding *b;
1570 	struct dcerpc_binding *b_netlogon_wksta;
1571 	struct samr_Connect c;
1572 	struct samr_SetDomainInfo s;
1573 	struct policy_handle *domain_policy;
1574 
1575 	struct lsa_ObjectAttribute attr;
1576 	struct lsa_QosInfo qos;
1577 	struct lsa_OpenPolicy2 r;
1578 	struct cli_credentials *credentials;
1579 	struct cli_credentials *credentials_wksta;
1580 
1581 	struct samsync_state *samsync_state;
1582 
1583 	char *test_machine_account;
1584 
1585 	char *test_wksta_machine_account;
1586 
1587 	mem_ctx = talloc_init("torture_rpc_netlogon");
1588 
1589 	test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1590 	join_ctx = torture_create_testuser(torture, test_machine_account,
1591 					   lpcfg_workgroup(torture->lp_ctx), ACB_SVRTRUST,
1592 					   &machine_password);
1593 	if (!join_ctx) {
1594 		talloc_free(mem_ctx);
1595 		torture_comment(torture, "Failed to join as BDC\n");
1596 		return false;
1597 	}
1598 
1599 	test_wksta_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_WKSTA_MACHINE_NAME);
1600 	join_ctx2 = torture_create_testuser(torture, test_wksta_machine_account, lpcfg_workgroup(torture->lp_ctx), ACB_WSTRUST, &wksta_machine_password);
1601 	if (!join_ctx2) {
1602 		talloc_free(mem_ctx);
1603 		torture_comment(torture, "Failed to join as member\n");
1604 		return false;
1605 	}
1606 
1607 	user_ctx = torture_create_testuser(torture, TEST_USER_NAME,
1608 					   lpcfg_workgroup(torture->lp_ctx),
1609 					   ACB_NORMAL, NULL);
1610 	if (!user_ctx) {
1611 		talloc_free(mem_ctx);
1612 		torture_comment(torture, "Failed to create test account\n");
1613 		return false;
1614 	}
1615 
1616 	samsync_state = talloc_zero(mem_ctx, struct samsync_state);
1617 
1618 	samsync_state->p_samr = torture_join_samr_pipe(join_ctx);
1619 	samsync_state->b_samr = samsync_state->p_samr->binding_handle;
1620 	samsync_state->connect_handle = talloc_zero(samsync_state, struct policy_handle);
1621 	samsync_state->lsa_handle = talloc_zero(samsync_state, struct policy_handle);
1622 	c.in.system_name = NULL;
1623 	c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1624 	c.out.connect_handle = samsync_state->connect_handle;
1625 
1626 	torture_assert_ntstatus_ok_goto(torture,
1627 		dcerpc_samr_Connect_r(samsync_state->b_samr, mem_ctx, &c),
1628 		ret, failed,
1629 		"samr_Connect failed");
1630 	torture_assert_ntstatus_ok_goto(torture, c.out.result,
1631 		ret, failed,
1632 		"samr_Connect failed");
1633 
1634 	domain_policy = samsync_open_domain(torture, mem_ctx, samsync_state, lpcfg_workgroup(torture->lp_ctx), NULL);
1635 	if (!domain_policy) {
1636 		torture_comment(torture, "samrsync_open_domain failed\n");
1637 		ret = false;
1638 		goto failed;
1639 	}
1640 
1641 	s.in.domain_handle = domain_policy;
1642 	s.in.level = 4;
1643 	s.in.info = talloc(mem_ctx, union samr_DomainInfo);
1644 
1645 	s.in.info->oem.oem_information.string
1646 		= talloc_asprintf(mem_ctx,
1647 				  "Tortured by Samba4: %s",
1648 				  timestring(mem_ctx, time(NULL)));
1649 	torture_assert_ntstatus_ok_goto(torture,
1650 		dcerpc_samr_SetDomainInfo_r(samsync_state->b_samr, mem_ctx, &s),
1651 		ret, failed,
1652 		"SetDomainInfo failed");
1653 
1654 	if (!test_samr_handle_Close(samsync_state->b_samr, torture, domain_policy)) {
1655 		ret = false;
1656 		goto failed;
1657 	}
1658 
1659 	torture_assert_ntstatus_ok_goto(torture, s.out.result,
1660 		ret, failed,
1661 		talloc_asprintf(torture, "SetDomainInfo level %u failed", s.in.level));
1662 
1663 	status = torture_rpc_connection(torture,
1664 					&samsync_state->p_lsa,
1665 					&ndr_table_lsarpc);
1666 
1667 	if (!NT_STATUS_IS_OK(status)) {
1668 		ret = false;
1669 		goto failed;
1670 	}
1671 	samsync_state->b_lsa = samsync_state->p_lsa->binding_handle;
1672 
1673 	qos.len = 0;
1674 	qos.impersonation_level = 2;
1675 	qos.context_mode = 1;
1676 	qos.effective_only = 0;
1677 
1678 	attr.len = 0;
1679 	attr.root_dir = NULL;
1680 	attr.object_name = NULL;
1681 	attr.attributes = 0;
1682 	attr.sec_desc = NULL;
1683 	attr.sec_qos = &qos;
1684 
1685 	r.in.system_name = "\\";
1686 	r.in.attr = &attr;
1687 	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1688 	r.out.handle = samsync_state->lsa_handle;
1689 
1690 	torture_assert_ntstatus_ok_goto(torture,
1691 		dcerpc_lsa_OpenPolicy2_r(samsync_state->b_lsa, mem_ctx, &r),
1692 		ret, failed,
1693 		"OpenPolicy2 failed");
1694 	torture_assert_ntstatus_ok_goto(torture, r.out.result,
1695 		ret, failed,
1696 		"OpenPolicy2 failed");
1697 
1698 	status = torture_rpc_binding(torture, &b);
1699 	if (!NT_STATUS_IS_OK(status)) {
1700 		ret = false;
1701 		goto failed;
1702 	}
1703 
1704 	status = dcerpc_binding_set_flags(b,
1705 					  DCERPC_SCHANNEL | DCERPC_SIGN,
1706 					  DCERPC_AUTH_OPTIONS);
1707 	torture_assert_ntstatus_ok(torture, status, "set flags");
1708 
1709 	credentials = cli_credentials_init(mem_ctx);
1710 
1711 	cli_credentials_set_workstation(credentials, TEST_MACHINE_NAME, CRED_SPECIFIED);
1712 	cli_credentials_set_domain(credentials, lpcfg_workgroup(torture->lp_ctx), CRED_SPECIFIED);
1713 	cli_credentials_set_username(credentials, test_machine_account, CRED_SPECIFIED);
1714 	cli_credentials_set_password(credentials, machine_password, CRED_SPECIFIED);
1715 	cli_credentials_set_secure_channel_type(credentials,
1716 						SEC_CHAN_BDC);
1717 
1718 	status = dcerpc_pipe_connect_b(samsync_state,
1719 				       &samsync_state->p, b,
1720 					   &ndr_table_netlogon,
1721 				       credentials, torture->ev, torture->lp_ctx);
1722 
1723 	if (!NT_STATUS_IS_OK(status)) {
1724 		torture_comment(torture, "Failed to connect to server as a BDC: %s\n", nt_errstr(status));
1725 		ret = false;
1726 		goto failed;
1727 	}
1728 	samsync_state->b = samsync_state->p->binding_handle;
1729 
1730 	samsync_state->creds = cli_credentials_get_netlogon_creds(credentials);
1731 	if (samsync_state->creds == NULL) {
1732 		ret = false;
1733 	}
1734 
1735 
1736 
1737 	status = torture_rpc_binding(torture, &b_netlogon_wksta);
1738 	if (!NT_STATUS_IS_OK(status)) {
1739 		ret = false;
1740 		goto failed;
1741 	}
1742 
1743 	status = dcerpc_binding_set_flags(b_netlogon_wksta,
1744 					  DCERPC_SCHANNEL | DCERPC_SIGN,
1745 					  DCERPC_AUTH_OPTIONS);
1746 	torture_assert_ntstatus_ok(torture, status, "set flags");
1747 
1748 	credentials_wksta = cli_credentials_init(mem_ctx);
1749 
1750 	cli_credentials_set_workstation(credentials_wksta, TEST_WKSTA_MACHINE_NAME, CRED_SPECIFIED);
1751 	cli_credentials_set_domain(credentials_wksta, lpcfg_workgroup(torture->lp_ctx), CRED_SPECIFIED);
1752 	cli_credentials_set_username(credentials_wksta, test_wksta_machine_account, CRED_SPECIFIED);
1753 	cli_credentials_set_password(credentials_wksta, wksta_machine_password, CRED_SPECIFIED);
1754 	cli_credentials_set_secure_channel_type(credentials_wksta,
1755 						SEC_CHAN_WKSTA);
1756 
1757 	status = dcerpc_pipe_connect_b(samsync_state,
1758 				       &samsync_state->p_netlogon_wksta,
1759 				       b_netlogon_wksta,
1760 					   &ndr_table_netlogon,
1761 				       credentials_wksta, torture->ev, torture->lp_ctx);
1762 
1763 	if (!NT_STATUS_IS_OK(status)) {
1764 		torture_comment(torture, "Failed to connect to server as a Workstation: %s\n", nt_errstr(status));
1765 		ret = false;
1766 		goto failed;
1767 	}
1768 
1769 	samsync_state->creds_netlogon_wksta = cli_credentials_get_netlogon_creds(credentials_wksta);
1770 	if (samsync_state->creds_netlogon_wksta == NULL) {
1771 		torture_comment(torture, "Failed to obtail schanel creds!\n");
1772 		ret = false;
1773 	}
1774 
1775 	if (!test_DatabaseSync(torture, samsync_state, mem_ctx)) {
1776 		torture_comment(torture, "DatabaseSync failed\n");
1777 		ret = false;
1778 	}
1779 
1780 	if (!test_DatabaseDeltas(torture, samsync_state, mem_ctx)) {
1781 		torture_comment(torture, "DatabaseDeltas failed\n");
1782 		ret = false;
1783 	}
1784 
1785 	if (!test_DatabaseSync2(torture, samsync_state->p, mem_ctx, samsync_state->creds)) {
1786 		torture_comment(torture, "DatabaseSync2 failed\n");
1787 		ret = false;
1788 	}
1789 failed:
1790 
1791 	torture_leave_domain(torture, join_ctx);
1792 	torture_leave_domain(torture, join_ctx2);
1793 	torture_leave_domain(torture, user_ctx);
1794 
1795 	talloc_free(mem_ctx);
1796 
1797 	return ret;
1798 }
1799