Line data Source code
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 : */
48 0 : 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 0 : NTSTATUS status;
58 0 : struct netr_LogonSamLogon r;
59 0 : struct netr_Authenticator auth, auth2;
60 0 : struct netr_NetworkInfo ninfo;
61 0 : union netr_LogonLevel logon;
62 0 : union netr_Validation validation;
63 0 : uint8_t authoritative;
64 0 : struct dcerpc_binding_handle *b = p->binding_handle;
65 0 : int rc;
66 :
67 0 : ninfo.identity_info.domain_name.string = domain;
68 0 : ninfo.identity_info.parameter_control = 0;
69 0 : ninfo.identity_info.logon_id = 0;
70 0 : ninfo.identity_info.account_name.string = account_name;
71 0 : ninfo.identity_info.workstation.string = workstation;
72 0 : generate_random_buffer(ninfo.challenge,
73 : sizeof(ninfo.challenge));
74 0 : if (nt_hash) {
75 0 : ninfo.nt.length = 24;
76 0 : ninfo.nt.data = talloc_array(mem_ctx, uint8_t, 24);
77 0 : rc = SMBOWFencrypt(nt_hash->hash, ninfo.challenge,
78 : ninfo.nt.data);
79 0 : if (rc != 0) {
80 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
81 : }
82 : } else {
83 0 : ninfo.nt.length = 0;
84 0 : ninfo.nt.data = NULL;
85 : }
86 :
87 0 : if (lm_hash) {
88 0 : ninfo.lm.length = 24;
89 0 : ninfo.lm.data = talloc_array(mem_ctx, uint8_t, 24);
90 0 : rc = SMBOWFencrypt(lm_hash->hash, ninfo.challenge,
91 : ninfo.lm.data);
92 0 : if (rc != 0) {
93 0 : return gnutls_error_to_ntstatus(rc, NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER);
94 : }
95 : } else {
96 0 : ninfo.lm.length = 0;
97 0 : ninfo.lm.data = NULL;
98 : }
99 :
100 0 : logon.network = &ninfo;
101 :
102 0 : r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
103 0 : r.in.computer_name = workstation;
104 0 : r.in.credential = &auth;
105 0 : r.in.return_authenticator = &auth2;
106 0 : r.in.logon_level = NetlogonNetworkInformation;
107 0 : r.in.logon = &logon;
108 0 : r.out.validation = &validation;
109 0 : r.out.authoritative = &authoritative;
110 :
111 0 : ZERO_STRUCT(auth2);
112 0 : netlogon_creds_client_authenticator(creds, &auth);
113 :
114 0 : r.in.validation_level = 3;
115 :
116 0 : status = dcerpc_netr_LogonSamLogon_r(b, mem_ctx, &r);
117 0 : if (!NT_STATUS_IS_OK(status)) {
118 0 : return status;
119 : }
120 :
121 0 : if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) {
122 0 : torture_comment(tctx, "Credential chaining failed\n");
123 : }
124 :
125 0 : if (info3) {
126 0 : *info3 = validation.sam3;
127 : }
128 :
129 0 : 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 :
166 0 : 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 0 : struct lsa_String name;
173 0 : struct samr_OpenDomain o;
174 0 : struct samr_LookupDomain l;
175 0 : struct dom_sid2 *sid = NULL;
176 0 : struct policy_handle *domain_handle = talloc(mem_ctx, struct policy_handle);
177 0 : NTSTATUS nt_status;
178 :
179 0 : name.string = domain;
180 0 : l.in.connect_handle = samsync_state->connect_handle;
181 0 : l.in.domain_name = &name;
182 0 : l.out.sid = &sid;
183 :
184 0 : nt_status = dcerpc_samr_LookupDomain_r(samsync_state->b_samr, mem_ctx, &l);
185 0 : if (!NT_STATUS_IS_OK(nt_status)) {
186 0 : torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(nt_status));
187 0 : return NULL;
188 : }
189 0 : if (!NT_STATUS_IS_OK(l.out.result)) {
190 0 : torture_comment(tctx, "LookupDomain failed - %s\n", nt_errstr(l.out.result));
191 0 : return NULL;
192 : }
193 :
194 0 : o.in.connect_handle = samsync_state->connect_handle;
195 0 : o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
196 0 : o.in.sid = *l.out.sid;
197 0 : o.out.domain_handle = domain_handle;
198 :
199 0 : if (sid_p) {
200 0 : *sid_p = *l.out.sid;
201 : }
202 :
203 0 : nt_status = dcerpc_samr_OpenDomain_r(samsync_state->b_samr, mem_ctx, &o);
204 0 : if (!NT_STATUS_IS_OK(nt_status)) {
205 0 : torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(nt_status));
206 0 : return NULL;
207 : }
208 0 : if (!NT_STATUS_IS_OK(o.out.result)) {
209 0 : torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(o.out.result));
210 0 : return NULL;
211 : }
212 :
213 0 : return domain_handle;
214 : }
215 :
216 0 : 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 0 : struct samr_QuerySecurity r;
222 0 : struct sec_desc_buf *sdbuf = NULL;
223 0 : NTSTATUS status;
224 :
225 0 : r.in.handle = handle;
226 0 : r.in.sec_info = 0x7;
227 0 : r.out.sdbuf = &sdbuf;
228 :
229 0 : status = dcerpc_samr_QuerySecurity_r(samsync_state->b_samr, mem_ctx, &r);
230 0 : if (!NT_STATUS_IS_OK(status)) {
231 0 : torture_comment(tctx, "SAMR QuerySecurity failed - %s\n", nt_errstr(status));
232 0 : return NULL;
233 : }
234 0 : if (!NT_STATUS_IS_OK(r.out.result)) {
235 0 : torture_comment(tctx, "SAMR QuerySecurity failed - %s\n", nt_errstr(r.out.result));
236 0 : return NULL;
237 : }
238 :
239 0 : return sdbuf;
240 : }
241 :
242 0 : 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 0 : struct lsa_QuerySecurity r;
248 0 : struct sec_desc_buf *sdbuf = NULL;
249 0 : NTSTATUS status;
250 :
251 0 : r.in.handle = handle;
252 0 : r.in.sec_info = 0x7;
253 0 : r.out.sdbuf = &sdbuf;
254 :
255 0 : status = dcerpc_lsa_QuerySecurity_r(samsync_state->b_lsa, mem_ctx, &r);
256 0 : if (!NT_STATUS_IS_OK(status)) {
257 0 : torture_comment(tctx, "LSA QuerySecurity failed - %s\n", nt_errstr(status));
258 0 : return NULL;
259 : }
260 0 : if (!NT_STATUS_IS_OK(r.out.result)) {
261 0 : torture_comment(tctx, "LSA QuerySecurity failed - %s\n", nt_errstr(r.out.result));
262 0 : return NULL;
263 : }
264 :
265 0 : 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(security_descriptor, sd1.sd);\
332 : NDR_PRINT_DEBUG(security_descriptor, sdbuf->sd);\
333 : ret = false;\
334 : }\
335 : }\
336 : } while (0)
337 :
338 0 : 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 0 : struct netr_DELTA_DOMAIN *domain = delta->delta_union.domain;
342 0 : struct dom_sid *dom_sid;
343 0 : struct samr_QueryDomainInfo q[14]; /* q[0] will be unused simple for clarity */
344 0 : union samr_DomainInfo *info[14];
345 0 : uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
346 0 : int i;
347 0 : bool ret = true;
348 :
349 0 : samsync_state->seq_num[database_id] =
350 0 : domain->sequence_num;
351 0 : switch (database_id) {
352 0 : case SAM_DATABASE_DOMAIN:
353 0 : break;
354 0 : case SAM_DATABASE_BUILTIN:
355 0 : if (strcasecmp_m("BUILTIN", domain->domain_name.string) != 0) {
356 0 : torture_comment(tctx, "BUILTIN domain has different name: %s\n", domain->domain_name.string);
357 : }
358 0 : break;
359 0 : case SAM_DATABASE_PRIVS:
360 0 : torture_comment(tctx, "DOMAIN entry on privs DB!\n");
361 0 : return false;
362 0 : break;
363 : }
364 :
365 0 : if (!samsync_state->domain_name[database_id]) {
366 0 : samsync_state->domain_name[database_id] =
367 0 : talloc_strdup(samsync_state, domain->domain_name.string);
368 : } else {
369 0 : if (strcasecmp_m(samsync_state->domain_name[database_id], domain->domain_name.string) != 0) {
370 0 : torture_comment(tctx, "Domain has name varies!: %s != %s\n", samsync_state->domain_name[database_id],
371 : domain->domain_name.string);
372 0 : return false;
373 : }
374 : }
375 :
376 0 : if (!samsync_state->domain_handle[database_id]) {
377 0 : samsync_state->domain_handle[database_id] =
378 0 : samsync_open_domain(tctx,
379 : samsync_state,
380 : samsync_state,
381 : samsync_state->domain_name[database_id],
382 : &dom_sid);
383 : }
384 0 : if (samsync_state->domain_handle[database_id]) {
385 0 : samsync_state->sid[database_id] = dom_sid_dup(samsync_state, dom_sid);
386 : }
387 :
388 0 : torture_comment(tctx, "\tsequence_nums[%d/%s]=%llu\n",
389 : database_id, domain->domain_name.string,
390 0 : (long long)samsync_state->seq_num[database_id]);
391 :
392 0 : for (i=0;i<ARRAY_SIZE(levels);i++) {
393 :
394 0 : q[levels[i]].in.domain_handle = samsync_state->domain_handle[database_id];
395 0 : q[levels[i]].in.level = levels[i];
396 0 : q[levels[i]].out.info = &info[levels[i]];
397 :
398 0 : 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 0 : 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 0 : TEST_STRING_EQUAL(info[5]->info5.domain_name, domain->domain_name);
406 :
407 0 : TEST_STRING_EQUAL(info[2]->general.oem_information, domain->oem_information);
408 0 : TEST_STRING_EQUAL(info[4]->oem.oem_information, domain->oem_information);
409 0 : TEST_TIME_EQUAL(info[2]->general.force_logoff_time, domain->force_logoff_time);
410 0 : TEST_TIME_EQUAL(info[3]->info3.force_logoff_time, domain->force_logoff_time);
411 :
412 0 : TEST_TIME_EQUAL(info[1]->info1.min_password_length, domain->min_password_length);
413 0 : TEST_TIME_EQUAL(info[1]->info1.password_history_length, domain->password_history_length);
414 0 : TEST_TIME_EQUAL(info[1]->info1.max_password_age, domain->max_password_age);
415 0 : TEST_TIME_EQUAL(info[1]->info1.min_password_age, domain->min_password_age);
416 :
417 0 : TEST_UINT64_EQUAL(info[8]->info8.sequence_num,
418 : domain->sequence_num);
419 0 : TEST_TIME_EQUAL(info[8]->info8.domain_create_time,
420 : domain->domain_create_time);
421 0 : TEST_TIME_EQUAL(info[13]->info13.domain_create_time,
422 : domain->domain_create_time);
423 :
424 0 : TEST_SEC_DESC_EQUAL(domain->sdbuf, samr, samsync_state->domain_handle[database_id]);
425 :
426 0 : return ret;
427 : }
428 :
429 0 : 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 0 : struct netr_DELTA_POLICY *policy = delta->delta_union.policy;
434 :
435 0 : switch (database_id) {
436 0 : case SAM_DATABASE_DOMAIN:
437 : case SAM_DATABASE_BUILTIN:
438 0 : break;
439 0 : case SAM_DATABASE_PRIVS:
440 0 : torture_comment(tctx, "DOMAIN entry on privs DB!\n");
441 0 : return false;
442 : }
443 :
444 0 : samsync_state->seq_num[database_id] =
445 0 : policy->sequence_num;
446 :
447 0 : if (!samsync_state->domain_name[SAM_DATABASE_DOMAIN]) {
448 0 : samsync_state->domain_name[SAM_DATABASE_DOMAIN] =
449 0 : talloc_strdup(samsync_state, policy->primary_domain_name.string);
450 : } else {
451 0 : if (strcasecmp_m(samsync_state->domain_name[SAM_DATABASE_DOMAIN], policy->primary_domain_name.string) != 0) {
452 0 : 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 0 : return false;
455 : }
456 : }
457 :
458 0 : if (!dom_sid_equal(samsync_state->sid[SAM_DATABASE_DOMAIN], policy->sid)) {
459 0 : torture_comment(tctx, "Domain SID from POLICY (%s) does not match domain sid from SAMR (%s)\n",
460 0 : dom_sid_string(mem_ctx, policy->sid), dom_sid_string(mem_ctx, samsync_state->sid[SAM_DATABASE_DOMAIN]));
461 0 : return false;
462 : }
463 :
464 0 : torture_comment(tctx, "\tsequence_nums[%d/PRIVS]=%llu\n",
465 : database_id,
466 0 : (long long)samsync_state->seq_num[database_id]);
467 0 : return true;
468 : }
469 :
470 0 : 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 0 : uint32_t rid = delta->delta_id_union.rid;
474 0 : struct netr_DELTA_USER *user = delta->delta_union.user;
475 0 : struct netr_SamInfo3 *info3 = NULL;
476 0 : struct samr_Password lm_hash;
477 0 : struct samr_Password nt_hash;
478 0 : struct samr_Password *lm_hash_p = NULL;
479 0 : struct samr_Password *nt_hash_p = NULL;
480 0 : const char *domain;
481 0 : const char *username = user->account_name.string;
482 0 : NTSTATUS nt_status;
483 0 : bool ret = true;
484 0 : struct samr_OpenUser r;
485 0 : struct samr_QueryUserInfo q;
486 0 : union samr_UserInfo *info;
487 0 : struct policy_handle user_handle;
488 0 : struct samr_GetGroupsForUser getgr;
489 0 : struct samr_RidWithAttributeArray *rids;
490 :
491 0 : switch (database_id) {
492 0 : case SAM_DATABASE_DOMAIN:
493 : case SAM_DATABASE_BUILTIN:
494 0 : break;
495 0 : case SAM_DATABASE_PRIVS:
496 0 : torture_comment(tctx, "DOMAIN entry on privs DB!\n");
497 0 : return false;
498 : }
499 :
500 0 : domain = samsync_state->domain_name[database_id];
501 :
502 0 : if (domain == NULL ||
503 0 : samsync_state->domain_handle[database_id] == NULL) {
504 0 : torture_comment(tctx, "SamSync needs domain information before the users\n");
505 0 : return false;
506 : }
507 :
508 0 : r.in.domain_handle = samsync_state->domain_handle[database_id];
509 0 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
510 0 : r.in.rid = rid;
511 0 : r.out.user_handle = &user_handle;
512 :
513 0 : 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 0 : torture_assert_ntstatus_ok(tctx, r.out.result,
517 : talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
518 :
519 0 : q.in.user_handle = &user_handle;
520 0 : q.in.level = 21;
521 0 : q.out.info = &info;
522 :
523 0 : TEST_SEC_DESC_EQUAL(user->sdbuf, samr, &user_handle);
524 :
525 0 : 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 0 : torture_assert_ntstatus_ok(tctx, q.out.result,
529 : talloc_asprintf(tctx, "OpenUserInfo level %u failed", q.in.level));
530 :
531 0 : getgr.in.user_handle = &user_handle;
532 0 : getgr.out.rids = &rids;
533 :
534 0 : torture_assert_ntstatus_ok(tctx,
535 : dcerpc_samr_GetGroupsForUser_r(samsync_state->b_samr, mem_ctx, &getgr),
536 : "GetGroupsForUser failed");
537 0 : torture_assert_ntstatus_ok(tctx, getgr.out.result,
538 : "GetGroupsForUser failed");
539 :
540 0 : if (!test_samr_handle_Close(samsync_state->b_samr, tctx, &user_handle)) {
541 0 : torture_comment(tctx, "samr_handle_Close failed\n");
542 0 : ret = false;
543 : }
544 0 : if (!ret) {
545 0 : return false;
546 : }
547 :
548 0 : TEST_STRING_EQUAL(info->info21.account_name, user->account_name);
549 0 : TEST_STRING_EQUAL(info->info21.full_name, user->full_name);
550 0 : TEST_INT_EQUAL(info->info21.rid, user->rid);
551 0 : TEST_INT_EQUAL(info->info21.primary_gid, user->primary_gid);
552 0 : TEST_STRING_EQUAL(info->info21.home_directory, user->home_directory);
553 0 : TEST_STRING_EQUAL(info->info21.home_drive, user->home_drive);
554 0 : TEST_STRING_EQUAL(info->info21.logon_script, user->logon_script);
555 0 : TEST_STRING_EQUAL(info->info21.description, user->description);
556 0 : TEST_STRING_EQUAL(info->info21.workstations, user->workstations);
557 :
558 0 : TEST_TIME_EQUAL(info->info21.last_logon, user->last_logon);
559 0 : TEST_TIME_EQUAL(info->info21.last_logoff, user->last_logoff);
560 :
561 :
562 0 : TEST_INT_EQUAL(info->info21.logon_hours.units_per_week,
563 : user->logon_hours.units_per_week);
564 0 : if (ret) {
565 0 : if (memcmp(info->info21.logon_hours.bits, user->logon_hours.bits,
566 0 : info->info21.logon_hours.units_per_week/8) != 0) {
567 0 : torture_comment(tctx, "Logon hours mismatch\n");
568 0 : ret = false;
569 : }
570 : }
571 :
572 0 : TEST_INT_EQUAL(info->info21.bad_password_count,
573 : user->bad_password_count);
574 0 : TEST_INT_EQUAL(info->info21.logon_count,
575 : user->logon_count);
576 :
577 0 : TEST_TIME_EQUAL(info->info21.last_password_change,
578 : user->last_password_change);
579 0 : TEST_TIME_EQUAL(info->info21.acct_expiry,
580 : user->acct_expiry);
581 :
582 0 : TEST_INT_EQUAL((info->info21.acct_flags & ~ACB_PW_EXPIRED), user->acct_flags);
583 0 : if (user->acct_flags & ACB_PWNOEXP) {
584 0 : if (info->info21.acct_flags & ACB_PW_EXPIRED) {
585 0 : torture_comment(tctx, "ACB flags mismatch: both expired and no expiry!\n");
586 0 : ret = false;
587 : }
588 0 : if (info->info21.force_password_change != (NTTIME)0x7FFFFFFFFFFFFFFFULL) {
589 0 : torture_comment(tctx, "ACB flags mismatch: no password expiry, but force password change 0x%016llx (%lld) != 0x%016llx (%lld)\n",
590 0 : (unsigned long long)info->info21.force_password_change,
591 0 : (unsigned long long)info->info21.force_password_change,
592 : (unsigned long long)0x7FFFFFFFFFFFFFFFULL, (unsigned long long)0x7FFFFFFFFFFFFFFFULL
593 : );
594 0 : ret = false;
595 : }
596 : }
597 :
598 0 : TEST_INT_EQUAL(info->info21.nt_password_set, user->nt_password_present);
599 0 : TEST_INT_EQUAL(info->info21.lm_password_set, user->lm_password_present);
600 0 : TEST_INT_EQUAL(info->info21.password_expired, user->password_expired);
601 :
602 0 : TEST_STRING_EQUAL(info->info21.comment, user->comment);
603 0 : TEST_BINARY_STRING_EQUAL(info->info21.parameters, user->parameters);
604 :
605 0 : TEST_INT_EQUAL(info->info21.country_code, user->country_code);
606 0 : TEST_INT_EQUAL(info->info21.code_page, user->code_page);
607 :
608 0 : TEST_STRING_EQUAL(info->info21.profile_path, user->profile_path);
609 :
610 0 : if (user->lm_password_present) {
611 0 : lm_hash_p = &lm_hash;
612 : }
613 0 : if (user->nt_password_present) {
614 0 : nt_hash_p = &nt_hash;
615 : }
616 :
617 0 : if (user->user_private_info.SensitiveData) {
618 0 : DATA_BLOB data;
619 0 : struct netr_USER_KEYS keys;
620 0 : enum ndr_err_code ndr_err;
621 0 : data.data = user->user_private_info.SensitiveData;
622 0 : data.length = user->user_private_info.DataLength;
623 0 : ndr_err = ndr_pull_struct_blob(&data, mem_ctx, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
624 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
625 0 : if (keys.keys.keys2.lmpassword.length == 16) {
626 0 : lm_hash_p = &lm_hash;
627 : }
628 0 : if (keys.keys.keys2.ntpassword.length == 16) {
629 0 : nt_hash_p = &nt_hash;
630 : }
631 : } else {
632 0 : 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 0 : return false;
637 : }
638 : }
639 :
640 0 : if (nt_hash_p) {
641 0 : DATA_BLOB nt_hash_blob = data_blob_const(nt_hash_p, 16);
642 0 : 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 0 : if (lm_hash_p) {
645 0 : DATA_BLOB lm_hash_blob = data_blob_const(lm_hash_p, 16);
646 0 : 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 0 : 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 0 : if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
659 0 : if (user->acct_flags & ACB_DISABLED) {
660 0 : return true;
661 : }
662 0 : } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)) {
663 0 : if (user->acct_flags & ACB_WSTRUST) {
664 0 : return true;
665 : }
666 0 : } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)) {
667 0 : if (user->acct_flags & ACB_SVRTRUST) {
668 0 : return true;
669 : }
670 0 : } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
671 0 : if (user->acct_flags & ACB_DOMTRUST) {
672 0 : return true;
673 : }
674 0 : } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
675 0 : if (user->acct_flags & ACB_DOMTRUST) {
676 0 : return true;
677 : }
678 0 : } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
679 0 : if (user->acct_flags & ACB_AUTOLOCK) {
680 0 : return true;
681 : }
682 0 : } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) {
683 0 : if (info->info21.acct_flags & ACB_PW_EXPIRED) {
684 0 : return true;
685 : }
686 0 : } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
687 0 : if (!lm_hash_p && !nt_hash_p) {
688 0 : return true;
689 : }
690 0 : } 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 0 : return true;
693 0 : } else if (NT_STATUS_IS_OK(nt_status)) {
694 0 : TEST_INT_EQUAL(user->rid, info3->base.rid);
695 0 : TEST_INT_EQUAL(user->primary_gid, info3->base.primary_gid);
696 : /* this is 0x0 from NT4 sp6 */
697 0 : if (info3->base.acct_flags) {
698 0 : TEST_INT_EQUAL(user->acct_flags, info3->base.acct_flags);
699 : }
700 : /* this is NULL from NT4 sp6 */
701 0 : if (info3->base.account_name.string) {
702 0 : TEST_STRING_EQUAL(user->account_name, info3->base.account_name);
703 : }
704 : /* this is NULL from Win2k3 */
705 0 : if (info3->base.full_name.string) {
706 0 : TEST_STRING_EQUAL(user->full_name, info3->base.full_name);
707 : }
708 0 : TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script);
709 0 : TEST_STRING_EQUAL(user->profile_path, info3->base.profile_path);
710 0 : TEST_STRING_EQUAL(user->home_directory, info3->base.home_directory);
711 0 : TEST_STRING_EQUAL(user->home_drive, info3->base.home_drive);
712 0 : TEST_STRING_EQUAL(user->logon_script, info3->base.logon_script);
713 :
714 :
715 0 : TEST_TIME_EQUAL(user->last_logon, info3->base.logon_time);
716 0 : TEST_TIME_EQUAL(user->acct_expiry, info3->base.kickoff_time);
717 0 : TEST_TIME_EQUAL(user->last_password_change, info3->base.last_password_change);
718 0 : 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 0 : if (!((user->last_logoff == 0)
727 0 : || (info3->base.logoff_time == 0x7fffffffffffffffLL))) {
728 0 : TEST_TIME_EQUAL(user->last_logoff, info3->base.logoff_time);
729 : }
730 :
731 0 : TEST_INT_EQUAL(rids->count, info3->base.groups.count);
732 0 : if (rids->count == info3->base.groups.count) {
733 0 : int i, j;
734 0 : int count = rids->count;
735 0 : bool *matched = talloc_zero_array(mem_ctx, bool, rids->count);
736 :
737 0 : for (i = 0; i < count; i++) {
738 0 : for (j = 0; j < count; j++) {
739 0 : if ((rids->rids[i].rid ==
740 0 : info3->base.groups.rids[j].rid)
741 0 : && (rids->rids[i].attributes ==
742 0 : info3->base.groups.rids[j].attributes)) {
743 0 : matched[i] = true;
744 : }
745 : }
746 : }
747 :
748 0 : for (i = 0; i < rids->count; i++) {
749 0 : if (matched[i] == false) {
750 0 : ret = false;
751 0 : torture_comment(tctx, "Could not find group RID %u found in getgroups in NETLOGON reply\n",
752 0 : rids->rids[i].rid);
753 : }
754 : }
755 : }
756 0 : return ret;
757 : } else {
758 0 : torture_comment(tctx, "Could not validate password for user %s\\%s: %s\n",
759 : domain, username, nt_errstr(nt_status));
760 0 : return false;
761 : }
762 0 : return false;
763 : }
764 :
765 0 : 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 0 : uint32_t rid = delta->delta_id_union.rid;
770 0 : struct netr_DELTA_ALIAS *alias = delta->delta_union.alias;
771 0 : bool ret = true;
772 :
773 0 : struct samr_OpenAlias r;
774 0 : struct samr_QueryAliasInfo q;
775 0 : union samr_AliasInfo *info;
776 0 : struct policy_handle alias_handle;
777 :
778 0 : switch (database_id) {
779 0 : case SAM_DATABASE_DOMAIN:
780 : case SAM_DATABASE_BUILTIN:
781 0 : break;
782 0 : case SAM_DATABASE_PRIVS:
783 0 : torture_comment(tctx, "DOMAIN entry on privs DB!\n");
784 0 : return false;
785 : }
786 :
787 0 : if (samsync_state->domain_name[database_id] == NULL ||
788 0 : samsync_state->domain_handle[database_id] == NULL) {
789 0 : torture_comment(tctx, "SamSync needs domain information before the users\n");
790 0 : return false;
791 : }
792 :
793 0 : r.in.domain_handle = samsync_state->domain_handle[database_id];
794 0 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
795 0 : r.in.rid = rid;
796 0 : r.out.alias_handle = &alias_handle;
797 :
798 0 : 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 0 : torture_assert_ntstatus_ok(tctx, r.out.result,
802 : talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
803 :
804 0 : q.in.alias_handle = &alias_handle;
805 0 : q.in.level = 1;
806 0 : q.out.info = &info;
807 :
808 0 : TEST_SEC_DESC_EQUAL(alias->sdbuf, samr, &alias_handle);
809 :
810 0 : torture_assert_ntstatus_ok(tctx,
811 : dcerpc_samr_QueryAliasInfo_r(samsync_state->b_samr, mem_ctx, &q),
812 : "QueryAliasInfo failed");
813 0 : if (!test_samr_handle_Close(samsync_state->b_samr, tctx, &alias_handle)) {
814 0 : return false;
815 : }
816 :
817 0 : if (!NT_STATUS_IS_OK(q.out.result)) {
818 0 : torture_comment(tctx, "QueryAliasInfo level %u failed - %s\n",
819 0 : q.in.level, nt_errstr(q.out.result));
820 0 : return false;
821 : }
822 :
823 0 : TEST_STRING_EQUAL(info->all.name, alias->alias_name);
824 0 : TEST_STRING_EQUAL(info->all.description, alias->description);
825 0 : return ret;
826 : }
827 :
828 0 : 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 0 : uint32_t rid = delta->delta_id_union.rid;
833 0 : struct netr_DELTA_GROUP *group = delta->delta_union.group;
834 0 : bool ret = true;
835 :
836 0 : struct samr_OpenGroup r;
837 0 : struct samr_QueryGroupInfo q;
838 0 : union samr_GroupInfo *info;
839 0 : struct policy_handle group_handle;
840 :
841 0 : switch (database_id) {
842 0 : case SAM_DATABASE_DOMAIN:
843 : case SAM_DATABASE_BUILTIN:
844 0 : break;
845 0 : case SAM_DATABASE_PRIVS:
846 0 : torture_comment(tctx, "DOMAIN entry on privs DB!\n");
847 0 : return false;
848 : }
849 :
850 0 : if (samsync_state->domain_name[database_id] == NULL ||
851 0 : samsync_state->domain_handle[database_id] == NULL) {
852 0 : torture_comment(tctx, "SamSync needs domain information before the users\n");
853 0 : return false;
854 : }
855 :
856 0 : r.in.domain_handle = samsync_state->domain_handle[database_id];
857 0 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
858 0 : r.in.rid = rid;
859 0 : r.out.group_handle = &group_handle;
860 :
861 0 : 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 0 : torture_assert_ntstatus_ok(tctx, r.out.result,
865 : talloc_asprintf(tctx, "OpenUser(%u) failed", rid));
866 :
867 0 : q.in.group_handle = &group_handle;
868 0 : q.in.level = 1;
869 0 : q.out.info = &info;
870 :
871 0 : TEST_SEC_DESC_EQUAL(group->sdbuf, samr, &group_handle);
872 :
873 0 : torture_assert_ntstatus_ok(tctx,
874 : dcerpc_samr_QueryGroupInfo_r(samsync_state->b_samr, mem_ctx, &q),
875 : "QueryGroupInfo failed");
876 0 : if (!test_samr_handle_Close(samsync_state->b_samr, tctx, &group_handle)) {
877 0 : return false;
878 : }
879 :
880 0 : if (!NT_STATUS_IS_OK(q.out.result)) {
881 0 : torture_comment(tctx, "QueryGroupInfo level %u failed - %s\n",
882 0 : q.in.level, nt_errstr(q.out.result));
883 0 : return false;
884 : }
885 :
886 0 : TEST_STRING_EQUAL(info->all.name, group->group_name);
887 0 : TEST_INT_EQUAL(info->all.attributes, group->attributes);
888 0 : TEST_STRING_EQUAL(info->all.description, group->description);
889 0 : return ret;
890 : }
891 :
892 0 : 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 0 : struct netr_DELTA_SECRET *secret = delta->delta_union.secret;
897 0 : const char *name = delta->delta_id_union.name;
898 0 : struct samsync_secret *nsec = talloc(samsync_state, struct samsync_secret);
899 0 : struct samsync_secret *old = talloc(mem_ctx, struct samsync_secret);
900 0 : struct lsa_QuerySecret q;
901 0 : struct lsa_OpenSecret o;
902 0 : struct policy_handle sec_handle;
903 0 : struct lsa_DATA_BUF_PTR bufp1;
904 0 : struct lsa_DATA_BUF_PTR bufp2;
905 0 : NTTIME nsec_mtime;
906 0 : NTTIME old_mtime;
907 0 : bool ret = true;
908 0 : DATA_BLOB lsa_blob1, lsa_blob_out, session_key;
909 0 : NTSTATUS status;
910 :
911 0 : nsec->name = talloc_strdup(nsec, name);
912 0 : nsec->secret = data_blob_talloc(nsec, secret->current_cipher.cipher_data, secret->current_cipher.maxlen);
913 0 : nsec->mtime = secret->current_cipher_set_time;
914 :
915 0 : DLIST_ADD(samsync_state->secrets, nsec);
916 :
917 0 : old->name = talloc_strdup(old, name);
918 0 : old->secret = data_blob_const(secret->old_cipher.cipher_data, secret->old_cipher.maxlen);
919 0 : old->mtime = secret->old_cipher_set_time;
920 :
921 0 : o.in.handle = samsync_state->lsa_handle;
922 0 : o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
923 0 : o.in.name.string = name;
924 0 : o.out.sec_handle = &sec_handle;
925 :
926 0 : torture_assert_ntstatus_ok(tctx,
927 : dcerpc_lsa_OpenSecret_r(samsync_state->b_lsa, mem_ctx, &o),
928 : "OpenSecret failed");
929 0 : 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 0 : status = dcerpc_fetch_session_key(samsync_state->p_lsa, &session_key);
937 0 : if (!NT_STATUS_IS_OK(status)) {
938 0 : torture_comment(tctx, "dcerpc_fetch_session_key failed - %s\n", nt_errstr(status));
939 0 : return false;
940 : }
941 :
942 :
943 0 : ZERO_STRUCT(nsec_mtime);
944 0 : ZERO_STRUCT(old_mtime);
945 :
946 : /* fetch the secret back again */
947 0 : q.in.sec_handle = &sec_handle;
948 0 : q.in.new_val = &bufp1;
949 0 : q.in.new_mtime = &nsec_mtime;
950 0 : q.in.old_val = &bufp2;
951 0 : q.in.old_mtime = &old_mtime;
952 :
953 0 : bufp1.buf = NULL;
954 0 : bufp2.buf = NULL;
955 :
956 0 : torture_assert_ntstatus_ok(tctx,
957 : dcerpc_lsa_QuerySecret_r(samsync_state->b_lsa, mem_ctx, &q),
958 : "QuerySecret failed");
959 0 : if (NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, q.out.result)) {
960 : /* some things are just off limits */
961 0 : return true;
962 0 : } else if (!NT_STATUS_IS_OK(q.out.result)) {
963 0 : torture_comment(tctx, "QuerySecret failed - %s\n", nt_errstr(q.out.result));
964 0 : return false;
965 : }
966 :
967 0 : if (q.out.old_val->buf == NULL) {
968 : /* probably just not available due to ACLs */
969 : } else {
970 0 : lsa_blob1.data = q.out.old_val->buf->data;
971 0 : lsa_blob1.length = q.out.old_val->buf->length;
972 :
973 0 : status = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key, &lsa_blob_out);
974 0 : if (!NT_STATUS_IS_OK(status)) {
975 0 : torture_comment(tctx, "Failed to decrypt secrets OLD blob: %s\n", nt_errstr(status));
976 0 : return false;
977 : }
978 :
979 0 : if (!q.out.old_mtime) {
980 0 : torture_comment(tctx, "OLD mtime not available on LSA for secret %s\n", old->name);
981 0 : ret = false;
982 : }
983 0 : if (old->mtime != *q.out.old_mtime) {
984 0 : 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 0 : nt_time_string(mem_ctx, *q.out.old_mtime));
987 0 : ret = false;
988 : }
989 :
990 0 : if (old->secret.length != lsa_blob_out.length) {
991 0 : torture_comment(tctx, "Returned secret %s doesn't match: %d != %d\n",
992 0 : old->name, (int)old->secret.length, (int)lsa_blob_out.length);
993 0 : ret = false;
994 0 : } else if (memcmp(lsa_blob_out.data,
995 0 : old->secret.data, old->secret.length) != 0) {
996 0 : torture_comment(tctx, "Returned secret %s doesn't match: \n",
997 : old->name);
998 0 : DEBUG(1, ("SamSync Secret:\n"));
999 0 : dump_data(1, old->secret.data, old->secret.length);
1000 0 : DEBUG(1, ("LSA Secret:\n"));
1001 0 : dump_data(1, lsa_blob_out.data, lsa_blob_out.length);
1002 0 : ret = false;
1003 : }
1004 :
1005 : }
1006 :
1007 0 : if (q.out.new_val->buf == NULL) {
1008 : /* probably just not available due to ACLs */
1009 : } else {
1010 0 : lsa_blob1.data = q.out.new_val->buf->data;
1011 0 : lsa_blob1.length = q.out.new_val->buf->length;
1012 :
1013 0 : status = sess_decrypt_blob(mem_ctx, &lsa_blob1, &session_key, &lsa_blob_out);
1014 0 : if (!NT_STATUS_IS_OK(status)) {
1015 0 : torture_comment(tctx, "Failed to decrypt secrets OLD blob\n");
1016 0 : return false;
1017 : }
1018 :
1019 0 : if (!q.out.new_mtime) {
1020 0 : torture_comment(tctx, "NEW mtime not available on LSA for secret %s\n", nsec->name);
1021 0 : ret = false;
1022 : }
1023 0 : if (nsec->mtime != *q.out.new_mtime) {
1024 0 : 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 0 : nt_time_string(mem_ctx, *q.out.new_mtime));
1027 0 : ret = false;
1028 : }
1029 :
1030 0 : if (nsec->secret.length != lsa_blob_out.length) {
1031 0 : torture_comment(tctx, "Returned secret %s doesn't match: %d != %d\n",
1032 0 : nsec->name, (int)nsec->secret.length, (int)lsa_blob_out.length);
1033 0 : ret = false;
1034 0 : } else if (memcmp(lsa_blob_out.data,
1035 0 : nsec->secret.data, nsec->secret.length) != 0) {
1036 0 : torture_comment(tctx, "Returned secret %s doesn't match: \n",
1037 : nsec->name);
1038 0 : DEBUG(1, ("SamSync Secret:\n"));
1039 0 : dump_data(1, nsec->secret.data, nsec->secret.length);
1040 0 : DEBUG(1, ("LSA Secret:\n"));
1041 0 : dump_data(1, lsa_blob_out.data, lsa_blob_out.length);
1042 0 : ret = false;
1043 : }
1044 : }
1045 :
1046 0 : return ret;
1047 : }
1048 :
1049 0 : 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 0 : bool ret = true;
1054 0 : struct netr_DELTA_TRUSTED_DOMAIN *trusted_domain = delta->delta_union.trusted_domain;
1055 0 : struct dom_sid *dom_sid = delta->delta_id_union.sid;
1056 :
1057 0 : struct samsync_trusted_domain *ndom = talloc(samsync_state, struct samsync_trusted_domain);
1058 0 : struct lsa_OpenTrustedDomain t;
1059 0 : struct policy_handle trustdom_handle;
1060 0 : struct lsa_QueryTrustedDomainInfo q;
1061 0 : union lsa_TrustedDomainInfo *info[9];
1062 0 : union lsa_TrustedDomainInfo *_info = NULL;
1063 0 : int levels [] = {1, 3, 8};
1064 0 : int i;
1065 :
1066 0 : ndom->name = talloc_strdup(ndom, trusted_domain->domain_name.string);
1067 0 : ndom->sid = dom_sid_dup(ndom, dom_sid);
1068 :
1069 0 : t.in.handle = samsync_state->lsa_handle;
1070 0 : t.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1071 0 : t.in.sid = dom_sid;
1072 0 : t.out.trustdom_handle = &trustdom_handle;
1073 :
1074 0 : torture_assert_ntstatus_ok(tctx,
1075 : dcerpc_lsa_OpenTrustedDomain_r(samsync_state->b_lsa, mem_ctx, &t),
1076 : "OpenTrustedDomain failed");
1077 0 : torture_assert_ntstatus_ok(tctx, t.out.result,
1078 : "OpenTrustedDomain failed");
1079 :
1080 0 : for (i=0; i< ARRAY_SIZE(levels); i++) {
1081 0 : q.in.trustdom_handle = &trustdom_handle;
1082 0 : q.in.level = levels[i];
1083 0 : q.out.info = &_info;
1084 0 : torture_assert_ntstatus_ok(tctx,
1085 : dcerpc_lsa_QueryTrustedDomainInfo_r(samsync_state->b_lsa, mem_ctx, &q),
1086 : "QueryTrustedDomainInfo failed");
1087 0 : if (!NT_STATUS_IS_OK(q.out.result)) {
1088 0 : if (q.in.level == 8 && NT_STATUS_EQUAL(q.out.result, NT_STATUS_INVALID_PARAMETER)) {
1089 0 : info[levels[i]] = NULL;
1090 0 : continue;
1091 : }
1092 0 : torture_comment(tctx, "QueryInfoTrustedDomain level %d failed - %s\n",
1093 : levels[i], nt_errstr(q.out.result));
1094 0 : return false;
1095 : }
1096 0 : info[levels[i]] = _info;
1097 : }
1098 :
1099 0 : if (info[8]) {
1100 0 : TEST_SID_EQUAL(info[8]->full_info.info_ex.sid, dom_sid);
1101 0 : TEST_STRING_EQUAL(info[8]->full_info.info_ex.netbios_name, trusted_domain->domain_name);
1102 : }
1103 0 : TEST_STRING_EQUAL(info[1]->name.netbios_name, trusted_domain->domain_name);
1104 0 : 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 0 : DLIST_ADD(samsync_state->trusted_domains, ndom);
1110 :
1111 0 : return ret;
1112 : }
1113 :
1114 0 : 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 0 : bool ret = true;
1119 0 : struct netr_DELTA_ACCOUNT *account = delta->delta_union.account;
1120 0 : struct dom_sid *dom_sid = delta->delta_id_union.sid;
1121 :
1122 0 : struct lsa_OpenAccount a;
1123 0 : struct policy_handle acct_handle;
1124 0 : struct lsa_EnumPrivsAccount e;
1125 0 : struct lsa_PrivilegeSet *privs = NULL;
1126 0 : struct lsa_LookupPrivName r;
1127 :
1128 0 : int i, j;
1129 :
1130 0 : bool *found_priv_in_lsa;
1131 :
1132 0 : a.in.handle = samsync_state->lsa_handle;
1133 0 : a.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1134 0 : a.in.sid = dom_sid;
1135 0 : a.out.acct_handle = &acct_handle;
1136 :
1137 0 : torture_assert_ntstatus_ok(tctx,
1138 : dcerpc_lsa_OpenAccount_r(samsync_state->b_lsa, mem_ctx, &a),
1139 : "OpenAccount failed");
1140 0 : torture_assert_ntstatus_ok(tctx, a.out.result,
1141 : "OpenAccount failed");
1142 :
1143 0 : TEST_SEC_DESC_EQUAL(account->sdbuf, lsa, &acct_handle);
1144 :
1145 0 : found_priv_in_lsa = talloc_zero_array(mem_ctx, bool, account->privilege_entries);
1146 :
1147 0 : e.in.handle = &acct_handle;
1148 0 : e.out.privs = &privs;
1149 :
1150 0 : torture_assert_ntstatus_ok(tctx,
1151 : dcerpc_lsa_EnumPrivsAccount_r(samsync_state->b_lsa, mem_ctx, &e),
1152 : "EnumPrivsAccount failed");
1153 0 : torture_assert_ntstatus_ok(tctx, e.out.result,
1154 : "EnumPrivsAccount failed");
1155 :
1156 0 : if ((account->privilege_entries && !privs)) {
1157 0 : torture_comment(tctx, "Account %s has privileges in SamSync, but not LSA\n",
1158 : dom_sid_string(mem_ctx, dom_sid));
1159 0 : return false;
1160 : }
1161 :
1162 0 : if (!account->privilege_entries && privs && privs->count) {
1163 0 : torture_comment(tctx, "Account %s has privileges in LSA, but not SamSync\n",
1164 : dom_sid_string(mem_ctx, dom_sid));
1165 0 : return false;
1166 : }
1167 :
1168 0 : TEST_INT_EQUAL(account->privilege_entries, privs->count);
1169 :
1170 0 : for (i=0;i< privs->count; i++) {
1171 :
1172 0 : struct lsa_StringLarge *name = NULL;
1173 :
1174 0 : r.in.handle = samsync_state->lsa_handle;
1175 0 : r.in.luid = &privs->set[i].luid;
1176 0 : r.out.name = &name;
1177 :
1178 0 : torture_assert_ntstatus_ok(tctx,
1179 : dcerpc_lsa_LookupPrivName_r(samsync_state->b_lsa, mem_ctx, &r),
1180 : "\nLookupPrivName failed");
1181 0 : torture_assert_ntstatus_ok(tctx, r.out.result,
1182 : "\nLookupPrivName failed");
1183 :
1184 0 : if (!r.out.name) {
1185 0 : torture_comment(tctx, "\nLookupPrivName failed to return a name\n");
1186 0 : return false;
1187 : }
1188 0 : for (j=0;j<account->privilege_entries; j++) {
1189 0 : if (strcmp(name->string, account->privilege_name[j].string) == 0) {
1190 0 : found_priv_in_lsa[j] = true;
1191 0 : break;
1192 : }
1193 : }
1194 : }
1195 0 : for (j=0;j<account->privilege_entries; j++) {
1196 0 : if (!found_priv_in_lsa[j]) {
1197 0 : 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 0 : ret = false;
1200 : }
1201 : }
1202 0 : return ret;
1203 : }
1204 :
1205 : /*
1206 : try a netlogon DatabaseSync
1207 : */
1208 0 : static bool test_DatabaseSync(struct torture_context *tctx,
1209 : struct samsync_state *samsync_state,
1210 : TALLOC_CTX *mem_ctx)
1211 : {
1212 0 : TALLOC_CTX *loop_ctx, *delta_ctx, *trustdom_ctx;
1213 0 : struct netr_DatabaseSync r;
1214 0 : const enum netr_SamDatabaseID database_ids[] = {SAM_DATABASE_DOMAIN, SAM_DATABASE_BUILTIN, SAM_DATABASE_PRIVS};
1215 0 : int i, d;
1216 0 : bool ret = true;
1217 0 : struct samsync_trusted_domain *t;
1218 0 : struct samsync_secret *s;
1219 0 : struct netr_Authenticator return_authenticator, credential;
1220 0 : struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
1221 :
1222 0 : const char *domain, *username;
1223 :
1224 0 : ZERO_STRUCT(return_authenticator);
1225 :
1226 0 : r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(samsync_state->p));
1227 0 : r.in.computername = TEST_MACHINE_NAME;
1228 0 : r.in.preferredmaximumlength = (uint32_t)-1;
1229 0 : r.in.return_authenticator = &return_authenticator;
1230 0 : r.out.return_authenticator = &return_authenticator;
1231 0 : r.out.delta_enum_array = &delta_enum_array;
1232 :
1233 0 : for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1234 :
1235 0 : uint32_t sync_context = 0;
1236 :
1237 0 : r.in.database_id = database_ids[i];
1238 0 : r.in.sync_context = &sync_context;
1239 0 : r.out.sync_context = &sync_context;
1240 :
1241 0 : torture_comment(tctx, "Testing DatabaseSync of id %d\n", r.in.database_id);
1242 :
1243 0 : do {
1244 0 : loop_ctx = talloc_named(mem_ctx, 0, "DatabaseSync loop context");
1245 0 : netlogon_creds_client_authenticator(samsync_state->creds, &credential);
1246 :
1247 0 : r.in.credential = &credential;
1248 :
1249 0 : torture_assert_ntstatus_ok(tctx,
1250 : dcerpc_netr_DatabaseSync_r(samsync_state->b, loop_ctx, &r),
1251 : "DatabaseSync failed");
1252 0 : if (!NT_STATUS_IS_OK(r.out.result) &&
1253 0 : !NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
1254 0 : torture_comment(tctx, "DatabaseSync - %s\n", nt_errstr(r.out.result));
1255 0 : ret = false;
1256 0 : break;
1257 : }
1258 :
1259 0 : if (!netlogon_creds_client_check(samsync_state->creds, &r.out.return_authenticator->cred)) {
1260 0 : torture_comment(tctx, "Credential chaining failed\n");
1261 : }
1262 :
1263 0 : r.in.sync_context = r.out.sync_context;
1264 :
1265 0 : for (d=0; d < delta_enum_array->num_deltas; d++) {
1266 0 : delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context");
1267 :
1268 0 : 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 0 : torture_comment(tctx, "Failed to decrypt delta\n");
1272 0 : ret = false;
1273 : }
1274 :
1275 0 : switch (delta_enum_array->delta_enum[d].delta_type) {
1276 0 : case NETR_DELTA_DOMAIN:
1277 0 : if (!samsync_handle_domain(tctx, delta_ctx, samsync_state,
1278 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1279 0 : torture_comment(tctx, "Failed to handle DELTA_DOMAIN\n");
1280 0 : ret = false;
1281 : }
1282 0 : break;
1283 0 : case NETR_DELTA_GROUP:
1284 0 : if (!samsync_handle_group(tctx, delta_ctx, samsync_state,
1285 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1286 0 : torture_comment(tctx, "Failed to handle DELTA_USER\n");
1287 0 : ret = false;
1288 : }
1289 0 : break;
1290 0 : case NETR_DELTA_USER:
1291 0 : if (!samsync_handle_user(tctx, delta_ctx, samsync_state,
1292 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1293 0 : torture_comment(tctx, "Failed to handle DELTA_USER\n");
1294 0 : ret = false;
1295 : }
1296 0 : break;
1297 0 : case NETR_DELTA_ALIAS:
1298 0 : if (!samsync_handle_alias(tctx, delta_ctx, samsync_state,
1299 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1300 0 : torture_comment(tctx, "Failed to handle DELTA_ALIAS\n");
1301 0 : ret = false;
1302 : }
1303 0 : break;
1304 0 : case NETR_DELTA_POLICY:
1305 0 : if (!samsync_handle_policy(tctx, delta_ctx, samsync_state,
1306 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1307 0 : torture_comment(tctx, "Failed to handle DELTA_POLICY\n");
1308 0 : ret = false;
1309 : }
1310 0 : break;
1311 0 : case NETR_DELTA_TRUSTED_DOMAIN:
1312 0 : if (!samsync_handle_trusted_domain(tctx, delta_ctx, samsync_state,
1313 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1314 0 : torture_comment(tctx, "Failed to handle DELTA_TRUSTED_DOMAIN\n");
1315 0 : ret = false;
1316 : }
1317 0 : break;
1318 0 : case NETR_DELTA_ACCOUNT:
1319 0 : if (!samsync_handle_account(tctx, delta_ctx, samsync_state,
1320 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1321 0 : torture_comment(tctx, "Failed to handle DELTA_ACCOUNT\n");
1322 0 : ret = false;
1323 : }
1324 0 : break;
1325 0 : case NETR_DELTA_SECRET:
1326 0 : if (!samsync_handle_secret(tctx, delta_ctx, samsync_state,
1327 0 : r.in.database_id, &delta_enum_array->delta_enum[d])) {
1328 0 : torture_comment(tctx, "Failed to handle DELTA_SECRET\n");
1329 0 : ret = false;
1330 : }
1331 0 : break;
1332 0 : case NETR_DELTA_GROUP_MEMBER:
1333 : case NETR_DELTA_ALIAS_MEMBER:
1334 : /* These are harder to cross-check, and we expect them */
1335 0 : break;
1336 0 : 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 0 : torture_comment(tctx, "Uxpected delta type %d\n", delta_enum_array->delta_enum[d].delta_type);
1350 0 : ret = false;
1351 0 : break;
1352 : }
1353 0 : talloc_free(delta_ctx);
1354 : }
1355 0 : talloc_free(loop_ctx);
1356 0 : } while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1357 :
1358 : }
1359 :
1360 0 : domain = samsync_state->domain_name[SAM_DATABASE_DOMAIN];
1361 0 : if (!domain) {
1362 0 : torture_comment(tctx, "Never got a DOMAIN object in samsync!\n");
1363 0 : return false;
1364 : }
1365 :
1366 0 : trustdom_ctx = talloc_named(mem_ctx, 0, "test_DatabaseSync Trusted domains context");
1367 :
1368 0 : username = talloc_asprintf(trustdom_ctx, "%s$", domain);
1369 0 : for (t=samsync_state->trusted_domains; t; t=t->next) {
1370 0 : char *secret_name = talloc_asprintf(trustdom_ctx, "G$$%s", t->name);
1371 0 : for (s=samsync_state->secrets; s; s=s->next) {
1372 0 : if (strcasecmp_m(s->name, secret_name) == 0) {
1373 0 : NTSTATUS nt_status;
1374 0 : struct samr_Password nt_hash;
1375 0 : mdfour(nt_hash.hash, s->secret.data, s->secret.length);
1376 :
1377 0 : torture_comment(tctx, "Checking password for %s\\%s\n", t->name, username);
1378 0 : 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 0 : if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_LOGON_SERVERS)) {
1387 0 : 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 0 : break;
1391 : }
1392 0 : if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
1393 0 : 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 0 : ret = false;
1396 : }
1397 :
1398 : /* break it */
1399 0 : nt_hash.hash[0]++;
1400 0 : 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 0 : if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
1410 0 : 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 0 : ret = false;
1413 : }
1414 :
1415 0 : break;
1416 : }
1417 : }
1418 : }
1419 0 : talloc_free(trustdom_ctx);
1420 0 : return ret;
1421 : }
1422 :
1423 :
1424 : /*
1425 : try a netlogon DatabaseDeltas
1426 : */
1427 0 : static bool test_DatabaseDeltas(struct torture_context *tctx,
1428 : struct samsync_state *samsync_state, TALLOC_CTX *mem_ctx)
1429 : {
1430 0 : TALLOC_CTX *loop_ctx;
1431 0 : struct netr_DatabaseDeltas r;
1432 0 : struct netr_Authenticator credential;
1433 0 : struct netr_Authenticator return_authenticator;
1434 0 : struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
1435 0 : const uint32_t database_ids[] = {0, 1, 2};
1436 0 : int i;
1437 0 : bool ret = true;
1438 :
1439 0 : ZERO_STRUCT(return_authenticator);
1440 :
1441 0 : r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(samsync_state->p));
1442 0 : r.in.computername = TEST_MACHINE_NAME;
1443 0 : r.in.credential = &credential;
1444 0 : r.in.preferredmaximumlength = (uint32_t)-1;
1445 0 : r.in.return_authenticator = &return_authenticator;
1446 0 : r.out.return_authenticator = &return_authenticator;
1447 0 : r.out.delta_enum_array = &delta_enum_array;
1448 :
1449 0 : for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1450 :
1451 0 : uint64_t seq_num = samsync_state->seq_num[i];
1452 :
1453 0 : r.in.database_id = database_ids[i];
1454 0 : r.in.sequence_num = &seq_num;
1455 0 : r.out.sequence_num = &seq_num;
1456 :
1457 0 : 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 0 : seq_num -= 10;
1464 :
1465 0 : torture_comment(tctx, "Testing DatabaseDeltas of id %d at %llu\n",
1466 0 : r.in.database_id, (long long)seq_num);
1467 :
1468 0 : do {
1469 0 : loop_ctx = talloc_named(mem_ctx, 0, "test_DatabaseDeltas loop context");
1470 0 : netlogon_creds_client_authenticator(samsync_state->creds, &credential);
1471 :
1472 0 : torture_assert_ntstatus_ok(tctx,
1473 : dcerpc_netr_DatabaseDeltas_r(samsync_state->b, loop_ctx, &r),
1474 : "DatabaseDeltas failed");
1475 0 : if (!NT_STATUS_IS_OK(r.out.result) &&
1476 0 : !NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
1477 0 : !NT_STATUS_EQUAL(r.out.result, NT_STATUS_SYNCHRONIZATION_REQUIRED)) {
1478 0 : torture_comment(tctx, "DatabaseDeltas - %s\n", nt_errstr(r.out.result));
1479 0 : ret = false;
1480 : }
1481 :
1482 0 : if (!netlogon_creds_client_check(samsync_state->creds, &return_authenticator.cred)) {
1483 0 : torture_comment(tctx, "Credential chaining failed\n");
1484 : }
1485 :
1486 0 : seq_num++;
1487 0 : talloc_free(loop_ctx);
1488 0 : } while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1489 : }
1490 :
1491 0 : return ret;
1492 : }
1493 :
1494 :
1495 : /*
1496 : try a netlogon DatabaseSync2
1497 : */
1498 0 : 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 0 : TALLOC_CTX *loop_ctx;
1503 0 : struct netr_DatabaseSync2 r;
1504 0 : const uint32_t database_ids[] = {0, 1, 2};
1505 0 : int i;
1506 0 : bool ret = true;
1507 0 : struct netr_Authenticator return_authenticator, credential;
1508 0 : struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
1509 0 : struct dcerpc_binding_handle *b = p->binding_handle;
1510 :
1511 0 : ZERO_STRUCT(return_authenticator);
1512 :
1513 0 : r.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1514 0 : r.in.computername = TEST_MACHINE_NAME;
1515 0 : r.in.preferredmaximumlength = (uint32_t)-1;
1516 0 : r.in.return_authenticator = &return_authenticator;
1517 0 : r.out.return_authenticator = &return_authenticator;
1518 0 : r.out.delta_enum_array = &delta_enum_array;
1519 :
1520 0 : for (i=0;i<ARRAY_SIZE(database_ids);i++) {
1521 :
1522 0 : uint32_t sync_context = 0;
1523 :
1524 0 : r.in.database_id = database_ids[i];
1525 0 : r.in.sync_context = &sync_context;
1526 0 : r.out.sync_context = &sync_context;
1527 0 : r.in.restart_state = 0;
1528 :
1529 0 : torture_comment(tctx, "Testing DatabaseSync2 of id %d\n", r.in.database_id);
1530 :
1531 0 : do {
1532 0 : loop_ctx = talloc_named(mem_ctx, 0, "test_DatabaseSync2 loop context");
1533 0 : netlogon_creds_client_authenticator(creds, &credential);
1534 :
1535 0 : r.in.credential = &credential;
1536 :
1537 0 : torture_assert_ntstatus_ok(tctx,
1538 : dcerpc_netr_DatabaseSync2_r(b, loop_ctx, &r),
1539 : "DatabaseSync2 failed");
1540 0 : if (!NT_STATUS_IS_OK(r.out.result) &&
1541 0 : !NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
1542 0 : torture_comment(tctx, "DatabaseSync2 - %s\n", nt_errstr(r.out.result));
1543 0 : ret = false;
1544 : }
1545 :
1546 0 : if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) {
1547 0 : torture_comment(tctx, "Credential chaining failed\n");
1548 : }
1549 :
1550 0 : talloc_free(loop_ctx);
1551 0 : } while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES));
1552 : }
1553 :
1554 0 : return ret;
1555 : }
1556 :
1557 :
1558 :
1559 0 : bool torture_rpc_samsync(struct torture_context *torture)
1560 : {
1561 0 : NTSTATUS status;
1562 0 : TALLOC_CTX *mem_ctx;
1563 0 : bool ret = true;
1564 0 : struct test_join *join_ctx;
1565 0 : struct test_join *join_ctx2;
1566 0 : struct test_join *user_ctx;
1567 0 : const char *machine_password;
1568 0 : const char *wksta_machine_password;
1569 0 : struct dcerpc_binding *b;
1570 0 : struct dcerpc_binding *b_netlogon_wksta;
1571 0 : struct samr_Connect c;
1572 0 : struct samr_SetDomainInfo s;
1573 0 : struct policy_handle *domain_policy;
1574 :
1575 0 : struct lsa_ObjectAttribute attr;
1576 0 : struct lsa_QosInfo qos;
1577 0 : struct lsa_OpenPolicy2 r;
1578 0 : struct cli_credentials *credentials;
1579 0 : struct cli_credentials *credentials_wksta;
1580 :
1581 0 : struct samsync_state *samsync_state;
1582 :
1583 0 : char *test_machine_account;
1584 :
1585 0 : char *test_wksta_machine_account;
1586 :
1587 0 : mem_ctx = talloc_init("torture_rpc_netlogon");
1588 :
1589 0 : test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1590 0 : join_ctx = torture_create_testuser(torture, test_machine_account,
1591 : lpcfg_workgroup(torture->lp_ctx), ACB_SVRTRUST,
1592 : &machine_password);
1593 0 : if (!join_ctx) {
1594 0 : talloc_free(mem_ctx);
1595 0 : torture_comment(torture, "Failed to join as BDC\n");
1596 0 : return false;
1597 : }
1598 :
1599 0 : test_wksta_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_WKSTA_MACHINE_NAME);
1600 0 : join_ctx2 = torture_create_testuser(torture, test_wksta_machine_account, lpcfg_workgroup(torture->lp_ctx), ACB_WSTRUST, &wksta_machine_password);
1601 0 : if (!join_ctx2) {
1602 0 : talloc_free(mem_ctx);
1603 0 : torture_comment(torture, "Failed to join as member\n");
1604 0 : return false;
1605 : }
1606 :
1607 0 : user_ctx = torture_create_testuser(torture, TEST_USER_NAME,
1608 : lpcfg_workgroup(torture->lp_ctx),
1609 : ACB_NORMAL, NULL);
1610 0 : if (!user_ctx) {
1611 0 : talloc_free(mem_ctx);
1612 0 : torture_comment(torture, "Failed to create test account\n");
1613 0 : return false;
1614 : }
1615 :
1616 0 : samsync_state = talloc_zero(mem_ctx, struct samsync_state);
1617 :
1618 0 : samsync_state->p_samr = torture_join_samr_pipe(join_ctx);
1619 0 : samsync_state->b_samr = samsync_state->p_samr->binding_handle;
1620 0 : samsync_state->connect_handle = talloc_zero(samsync_state, struct policy_handle);
1621 0 : samsync_state->lsa_handle = talloc_zero(samsync_state, struct policy_handle);
1622 0 : c.in.system_name = NULL;
1623 0 : c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1624 0 : c.out.connect_handle = samsync_state->connect_handle;
1625 :
1626 0 : 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 0 : torture_assert_ntstatus_ok_goto(torture, c.out.result,
1631 : ret, failed,
1632 : "samr_Connect failed");
1633 :
1634 0 : domain_policy = samsync_open_domain(torture, mem_ctx, samsync_state, lpcfg_workgroup(torture->lp_ctx), NULL);
1635 0 : if (!domain_policy) {
1636 0 : torture_comment(torture, "samrsync_open_domain failed\n");
1637 0 : ret = false;
1638 0 : goto failed;
1639 : }
1640 :
1641 0 : s.in.domain_handle = domain_policy;
1642 0 : s.in.level = 4;
1643 0 : s.in.info = talloc(mem_ctx, union samr_DomainInfo);
1644 :
1645 0 : s.in.info->oem.oem_information.string
1646 0 : = talloc_asprintf(mem_ctx,
1647 : "Tortured by Samba4: %s",
1648 : timestring(mem_ctx, time(NULL)));
1649 0 : 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 0 : if (!test_samr_handle_Close(samsync_state->b_samr, torture, domain_policy)) {
1655 0 : ret = false;
1656 0 : goto failed;
1657 : }
1658 :
1659 0 : 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 0 : status = torture_rpc_connection(torture,
1664 : &samsync_state->p_lsa,
1665 : &ndr_table_lsarpc);
1666 :
1667 0 : if (!NT_STATUS_IS_OK(status)) {
1668 0 : ret = false;
1669 0 : goto failed;
1670 : }
1671 0 : samsync_state->b_lsa = samsync_state->p_lsa->binding_handle;
1672 :
1673 0 : qos.len = 0;
1674 0 : qos.impersonation_level = 2;
1675 0 : qos.context_mode = 1;
1676 0 : qos.effective_only = 0;
1677 :
1678 0 : attr.len = 0;
1679 0 : attr.root_dir = NULL;
1680 0 : attr.object_name = NULL;
1681 0 : attr.attributes = 0;
1682 0 : attr.sec_desc = NULL;
1683 0 : attr.sec_qos = &qos;
1684 :
1685 0 : r.in.system_name = "\\";
1686 0 : r.in.attr = &attr;
1687 0 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1688 0 : r.out.handle = samsync_state->lsa_handle;
1689 :
1690 0 : 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 0 : torture_assert_ntstatus_ok_goto(torture, r.out.result,
1695 : ret, failed,
1696 : "OpenPolicy2 failed");
1697 :
1698 0 : status = torture_rpc_binding(torture, &b);
1699 0 : if (!NT_STATUS_IS_OK(status)) {
1700 0 : ret = false;
1701 0 : goto failed;
1702 : }
1703 :
1704 0 : status = dcerpc_binding_set_flags(b,
1705 : DCERPC_SCHANNEL | DCERPC_SIGN,
1706 : DCERPC_AUTH_OPTIONS);
1707 0 : torture_assert_ntstatus_ok(torture, status, "set flags");
1708 :
1709 0 : credentials = cli_credentials_init(mem_ctx);
1710 :
1711 0 : cli_credentials_set_workstation(credentials, TEST_MACHINE_NAME, CRED_SPECIFIED);
1712 0 : cli_credentials_set_domain(credentials, lpcfg_workgroup(torture->lp_ctx), CRED_SPECIFIED);
1713 0 : cli_credentials_set_username(credentials, test_machine_account, CRED_SPECIFIED);
1714 0 : cli_credentials_set_password(credentials, machine_password, CRED_SPECIFIED);
1715 0 : cli_credentials_set_secure_channel_type(credentials,
1716 : SEC_CHAN_BDC);
1717 :
1718 0 : 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 0 : if (!NT_STATUS_IS_OK(status)) {
1724 0 : torture_comment(torture, "Failed to connect to server as a BDC: %s\n", nt_errstr(status));
1725 0 : ret = false;
1726 0 : goto failed;
1727 : }
1728 0 : samsync_state->b = samsync_state->p->binding_handle;
1729 :
1730 0 : samsync_state->creds = cli_credentials_get_netlogon_creds(credentials);
1731 0 : if (samsync_state->creds == NULL) {
1732 0 : ret = false;
1733 : }
1734 :
1735 :
1736 :
1737 0 : status = torture_rpc_binding(torture, &b_netlogon_wksta);
1738 0 : if (!NT_STATUS_IS_OK(status)) {
1739 0 : ret = false;
1740 0 : goto failed;
1741 : }
1742 :
1743 0 : status = dcerpc_binding_set_flags(b_netlogon_wksta,
1744 : DCERPC_SCHANNEL | DCERPC_SIGN,
1745 : DCERPC_AUTH_OPTIONS);
1746 0 : torture_assert_ntstatus_ok(torture, status, "set flags");
1747 :
1748 0 : credentials_wksta = cli_credentials_init(mem_ctx);
1749 :
1750 0 : cli_credentials_set_workstation(credentials_wksta, TEST_WKSTA_MACHINE_NAME, CRED_SPECIFIED);
1751 0 : cli_credentials_set_domain(credentials_wksta, lpcfg_workgroup(torture->lp_ctx), CRED_SPECIFIED);
1752 0 : cli_credentials_set_username(credentials_wksta, test_wksta_machine_account, CRED_SPECIFIED);
1753 0 : cli_credentials_set_password(credentials_wksta, wksta_machine_password, CRED_SPECIFIED);
1754 0 : cli_credentials_set_secure_channel_type(credentials_wksta,
1755 : SEC_CHAN_WKSTA);
1756 :
1757 0 : 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 0 : if (!NT_STATUS_IS_OK(status)) {
1764 0 : torture_comment(torture, "Failed to connect to server as a Workstation: %s\n", nt_errstr(status));
1765 0 : ret = false;
1766 0 : goto failed;
1767 : }
1768 :
1769 0 : samsync_state->creds_netlogon_wksta = cli_credentials_get_netlogon_creds(credentials_wksta);
1770 0 : if (samsync_state->creds_netlogon_wksta == NULL) {
1771 0 : torture_comment(torture, "Failed to obtail schanel creds!\n");
1772 0 : ret = false;
1773 : }
1774 :
1775 0 : if (!test_DatabaseSync(torture, samsync_state, mem_ctx)) {
1776 0 : torture_comment(torture, "DatabaseSync failed\n");
1777 0 : ret = false;
1778 : }
1779 :
1780 0 : if (!test_DatabaseDeltas(torture, samsync_state, mem_ctx)) {
1781 0 : torture_comment(torture, "DatabaseDeltas failed\n");
1782 0 : ret = false;
1783 : }
1784 :
1785 0 : if (!test_DatabaseSync2(torture, samsync_state->p, mem_ctx, samsync_state->creds)) {
1786 0 : torture_comment(torture, "DatabaseSync2 failed\n");
1787 0 : ret = false;
1788 : }
1789 0 : failed:
1790 :
1791 0 : torture_leave_domain(torture, join_ctx);
1792 0 : torture_leave_domain(torture, join_ctx2);
1793 0 : torture_leave_domain(torture, user_ctx);
1794 :
1795 0 : talloc_free(mem_ctx);
1796 :
1797 0 : return ret;
1798 : }
|