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