s4-torture: validate owf password hash and negotiate AES in forest trust test.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / forest_trust.c
blob220828083a72512dfdf5c3cfd8b65cf637f6cea6
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for forest trust
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 Copyright (C) Sumit Bose <sbose@redhat.com> 2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "librpc/gen_ndr/ndr_lsa_c.h"
26 #include "librpc/gen_ndr/ndr_drsblobs.h"
27 #include "librpc/gen_ndr/ndr_netlogon_c.h"
28 #include "libcli/security/security.h"
29 #include "libcli/auth/credentials.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "torture/rpc/torture_rpc.h"
32 #include "param/param.h"
33 #include "../lib/crypto/crypto.h"
35 #define TEST_DOM "torturedom"
36 #define TEST_DOM_DNS "torturedom.samba.example.com"
37 #define TEST_DOM_SID "S-1-5-21-97398-379795-10000"
38 #define TEST_MACHINE_NAME "lsatestmach"
41 static bool test_get_policy_handle(struct torture_context *tctx,
42 struct dcerpc_pipe *p,
43 uint32_t access_mask,
44 struct policy_handle **handle )
46 struct policy_handle *h;
47 struct lsa_OpenPolicy2 pr;
48 struct lsa_ObjectAttribute attr;
49 NTSTATUS status;
51 h = talloc(tctx, struct policy_handle);
52 if (!h) {
53 return false;
56 attr.len = 0;
57 attr.root_dir = NULL;
58 attr.object_name = NULL;
59 attr.attributes = 0;
60 attr.sec_desc = NULL;
61 attr.sec_qos = NULL;
63 pr.in.system_name = "\\";
64 pr.in.attr = &attr;
65 pr.in.access_mask = access_mask;
66 pr.out.handle = h;
68 status = dcerpc_lsa_OpenPolicy2_r(p->binding_handle, tctx, &pr);
69 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
70 "OpenPolicy2 failed");
71 if (!NT_STATUS_IS_OK(pr.out.result)) {
72 torture_comment(tctx, "OpenPolicy2 failed - %s\n",
73 nt_errstr(pr.out.result));
74 talloc_free(h);
75 return false;
78 *handle = h;
79 return true;
82 static bool test_create_trust_and_set_info(struct dcerpc_pipe *p,
83 struct torture_context *tctx,
84 const char *trust_name,
85 const char *trust_name_dns,
86 struct dom_sid *domsid,
87 struct lsa_TrustDomainInfoAuthInfoInternal *authinfo)
89 struct policy_handle *handle;
90 NTSTATUS status;
91 struct lsa_lsaRSetForestTrustInformation fti;
92 struct lsa_ForestTrustCollisionInfo *collision_info = NULL;
93 struct lsa_Close cr;
94 struct policy_handle closed_handle;
95 bool ret = true;
96 struct lsa_CreateTrustedDomainEx2 r;
97 struct lsa_TrustDomainInfoInfoEx trustinfo;
98 struct policy_handle trustdom_handle;
99 struct lsa_QueryTrustedDomainInfo q;
100 union lsa_TrustedDomainInfo *info = NULL;
102 if (!test_get_policy_handle(tctx, p,
103 (LSA_POLICY_VIEW_LOCAL_INFORMATION |
104 LSA_POLICY_TRUST_ADMIN |
105 LSA_POLICY_CREATE_SECRET), &handle)) {
106 return false;
109 torture_comment(tctx, "\nTesting CreateTrustedDomainEx2\n");
111 trustinfo.sid = domsid;
112 trustinfo.netbios_name.string = trust_name;
113 trustinfo.domain_name.string = trust_name_dns;
115 trustinfo.trust_direction = LSA_TRUST_DIRECTION_INBOUND |
116 LSA_TRUST_DIRECTION_OUTBOUND;
118 trustinfo.trust_type = LSA_TRUST_TYPE_UPLEVEL;
120 /* MS-LSAD: Section 3.1.4.7.10 makes it clear that Win2k3
121 * functional level and above return
122 * NT_STATUS_INVALID_DOMAIN_STATE if
123 * TRUST_ATTRIBUTE_FOREST_TRANSITIVE or
124 * TRUST_ATTRIBUTE_CROSS_ORGANIZATION is set here.
126 trustinfo.trust_attributes = 0;
128 r.in.policy_handle = handle;
129 r.in.info = &trustinfo;
130 r.in.auth_info_internal = authinfo;
131 /* LSA_TRUSTED_QUERY_DOMAIN_NAME is needed for for following
132 * QueryTrustedDomainInfo call, although it seems that Windows does not
133 * expect this */
134 r.in.access_mask = LSA_TRUSTED_SET_POSIX | LSA_TRUSTED_SET_AUTH | LSA_TRUSTED_QUERY_DOMAIN_NAME;
135 r.out.trustdom_handle = &trustdom_handle;
137 torture_assert_ntstatus_ok(tctx,
138 dcerpc_lsa_CreateTrustedDomainEx2_r(p->binding_handle, tctx, &r),
139 "CreateTrustedDomainEx2 failed");
140 if (!NT_STATUS_IS_OK(r.out.result)) {
141 torture_comment(tctx, "CreateTrustedDomainEx2 failed - %s\n", nt_errstr(r.out.result));
142 ret = false;
143 } else {
145 q.in.trustdom_handle = &trustdom_handle;
146 q.in.level = LSA_TRUSTED_DOMAIN_INFO_INFO_EX;
147 q.out.info = &info;
149 torture_assert_ntstatus_ok(tctx,
150 dcerpc_lsa_QueryTrustedDomainInfo_r(p->binding_handle, tctx, &q),
151 "QueryTrustedDomainInfo failed");
152 if (!NT_STATUS_IS_OK(q.out.result)) {
153 torture_comment(tctx,
154 "QueryTrustedDomainInfo level 1 failed - %s\n",
155 nt_errstr(q.out.result));
156 ret = false;
157 } else if (!q.out.info) {
158 torture_comment(tctx,
159 "QueryTrustedDomainInfo level 1 failed to return an info pointer\n");
160 ret = false;
161 } else {
162 if (strcmp(info->info_ex.netbios_name.string, trustinfo.netbios_name.string) != 0) {
163 torture_comment(tctx,
164 "QueryTrustedDomainInfo returned inconsistent short name: %s != %s\n",
165 info->info_ex.netbios_name.string,
166 trustinfo.netbios_name.string);
167 ret = false;
169 if (info->info_ex.trust_type != trustinfo.trust_type) {
170 torture_comment(tctx,
171 "QueryTrustedDomainInfo of %s returned incorrect trust type %d != %d\n",
172 trust_name,
173 info->info_ex.trust_type,
174 trustinfo.trust_type);
175 ret = false;
177 if (info->info_ex.trust_attributes != trustinfo.trust_attributes) {
178 torture_comment(tctx,
179 "QueryTrustedDomainInfo of %s returned incorrect trust attributes %d != %d\n",
180 trust_name,
181 info->info_ex.trust_attributes,
182 trustinfo.trust_attributes);
183 ret = false;
185 if (info->info_ex.trust_direction != trustinfo.trust_direction) {
186 torture_comment(tctx,
187 "QueryTrustedDomainInfo of %s returned incorrect trust direction %d != %d\n",
188 trust_name,
189 info->info_ex.trust_direction,
190 trustinfo.trust_direction);
191 ret = false;
196 if (ret != false) {
197 fti.in.handle = handle;
198 fti.in.trusted_domain_name = talloc_zero(tctx, struct lsa_StringLarge);
199 fti.in.trusted_domain_name->string = trust_name_dns;
200 fti.in.highest_record_type = 2;
201 fti.in.forest_trust_info = talloc_zero(tctx, struct lsa_ForestTrustInformation);
202 fti.in.forest_trust_info->count = 2;
203 fti.in.forest_trust_info->entries = talloc_array(tctx, struct lsa_ForestTrustRecord *, 2);
204 fti.in.forest_trust_info->entries[0] = talloc_zero(tctx, struct lsa_ForestTrustRecord);
205 fti.in.forest_trust_info->entries[0]->flags = 0;
206 fti.in.forest_trust_info->entries[0]->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
207 fti.in.forest_trust_info->entries[0]->time = 0;
208 fti.in.forest_trust_info->entries[0]->forest_trust_data.top_level_name.string = trust_name_dns;
209 fti.in.forest_trust_info->entries[1] = talloc_zero(tctx, struct lsa_ForestTrustRecord);
210 fti.in.forest_trust_info->entries[1]->flags = 0;
211 fti.in.forest_trust_info->entries[1]->type = LSA_FOREST_TRUST_DOMAIN_INFO;
212 fti.in.forest_trust_info->entries[1]->time = 0;
213 fti.in.forest_trust_info->entries[1]->forest_trust_data.domain_info.domain_sid = domsid;
214 fti.in.forest_trust_info->entries[1]->forest_trust_data.domain_info.dns_domain_name.string = trust_name_dns;
215 fti.in.forest_trust_info->entries[1]->forest_trust_data.domain_info.netbios_domain_name.string = trust_name;
216 fti.in.check_only = 0;
217 fti.out.collision_info = &collision_info;
219 torture_comment(tctx, "\nTesting SetForestTrustInformation\n");
221 torture_assert_ntstatus_ok(tctx,
222 dcerpc_lsa_lsaRSetForestTrustInformation_r(p->binding_handle, tctx, &fti),
223 "lsaRSetForestTrustInformation failed");
224 if (!NT_STATUS_IS_OK(fti.out.result)) {
225 torture_comment(tctx,
226 "lsaRSetForestTrustInformation failed - %s\n",
227 nt_errstr(fti.out.result));
228 ret = false;
232 cr.in.handle = handle;
233 cr.out.handle = &closed_handle;
234 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
235 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
236 "Close failed");
237 if (!NT_STATUS_IS_OK(cr.out.result)) {
238 torture_comment(tctx, "Close failed - %s\n",
239 nt_errstr(cr.out.result));
240 ret = false;
243 return ret;
246 struct get_set_info {
247 enum lsa_TrustDomInfoEnum info_level;
248 NTSTATUS get_result;
249 NTSTATUS set_result;
252 static bool get_and_set_info(struct dcerpc_pipe *p,
253 struct torture_context *tctx,
254 const char *name)
256 struct policy_handle *handle;
257 NTSTATUS status;
258 struct lsa_QueryTrustedDomainInfoByName qr;
259 struct lsa_SetTrustedDomainInfoByName sr;
260 union lsa_TrustedDomainInfo *info;
261 struct lsa_Close cr;
262 struct policy_handle closed_handle;
263 size_t c;
265 struct get_set_info il[] = {
266 {LSA_TRUSTED_DOMAIN_INFO_NAME, NT_STATUS_OK, NT_STATUS_INVALID_PARAMETER},
267 /* {LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS, NT_STATUS_INVALID_PARAMETER, NT_STATUS_INVALID_INFO_CLASS}, */
268 {LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET, NT_STATUS_OK, NT_STATUS_OK},
269 /* {LSA_TRUSTED_DOMAIN_INFO_PASSWORD, NT_STATUS_INVALID_PARAMETER, NT_STATUS_INVALID_INFO_CLASS}, */
270 /* {LSA_TRUSTED_DOMAIN_INFO_BASIC, NT_STATUS_INVALID_PARAMETER, NT_STATUS_INVALID_INFO_CLASS}, */
271 {LSA_TRUSTED_DOMAIN_INFO_INFO_EX, NT_STATUS_OK, NT_STATUS_OK},
272 /* {LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO, NT_STATUS_INVALID_PARAMETER, NT_STATUS_INVALID_INFO_CLASS}, */
273 {LSA_TRUSTED_DOMAIN_INFO_FULL_INFO, NT_STATUS_OK, NT_STATUS_OK},
274 /* {LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL, NT_STATUS_INVALID_PARAMETER, NT_STATUS_INVALID_INFO_CLASS}, */
275 /* {LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL, NT_STATUS_INVALID_PARAMETER, NT_STATUS_INVALID_INFO_CLASS}, */
276 /* {LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL, NT_STATUS_INVALID_PARAMETER, NT_STATUS_INVALID_INFO_CLASS}, */
277 {LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL, NT_STATUS_OK, NT_STATUS_INVALID_PARAMETER},
278 {LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES, NT_STATUS_OK, NT_STATUS_OK},
279 {-1, NT_STATUS_OK}
282 torture_comment(tctx, "\nGetting/Setting dom info\n");
284 if(!test_get_policy_handle(tctx, p, LSA_POLICY_VIEW_LOCAL_INFORMATION,
285 &handle)) {
286 return false;
289 qr.in.handle = handle;
290 qr.in.trusted_domain = talloc_zero(tctx, struct lsa_String);
291 qr.in.trusted_domain->string = name;
292 qr.out.info = &info;
294 sr.in.handle = handle;
295 sr.in.trusted_domain = talloc_zero(tctx, struct lsa_String);
296 sr.in.trusted_domain->string = name;
297 sr.in.info = info;
299 for (c = 0; il[c].info_level != -1; c++) {
300 torture_comment(tctx, "\nGetting/Setting dom info [%d]\n",il[c].info_level);
301 qr.in.level = il[c].info_level;
302 status = dcerpc_lsa_QueryTrustedDomainInfoByName_r(p->binding_handle,
303 tctx, &qr);
304 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
305 "QueryTrustedDomainInfoByName failed");
306 if (!NT_STATUS_EQUAL(qr.out.result, il[c].get_result)) {
307 torture_comment(tctx, "QueryTrustedDomainInfoByName did not return "
308 "%s but %s\n",
309 nt_errstr(il[c].get_result),
310 nt_errstr(qr.out.result));
312 /* We may be testing a server without support for this level */
313 if (qr.in.level == LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES && NT_STATUS_EQUAL(qr.out.result, NT_STATUS_INVALID_PARAMETER)) {
314 return true;
316 return false;
319 sr.in.level = il[c].info_level;
320 sr.in.info = info;
321 status = dcerpc_lsa_SetTrustedDomainInfoByName_r(p->binding_handle,
322 tctx, &sr);
323 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
324 "SetTrustedDomainInfoByName failed");
325 if (!NT_STATUS_EQUAL(sr.out.result, il[c].set_result)) {
326 torture_comment(tctx, "SetTrustedDomainInfoByName did not return "
327 "%s but %s\n",
328 nt_errstr(il[c].set_result),
329 nt_errstr(sr.out.result));
330 return false;
334 cr.in.handle = handle;
335 cr.out.handle = &closed_handle;
336 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
337 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
338 "Close failed");
339 if (!NT_STATUS_IS_OK(cr.out.result)) {
340 torture_comment(tctx, "Close failed - %s\n",
341 nt_errstr(cr.out.result));
342 return false;
345 return true;
348 static bool check_name(struct dcerpc_pipe *p, struct torture_context *tctx,
349 const char *name)
351 struct policy_handle *handle;
352 NTSTATUS status;
353 struct lsa_QueryTrustedDomainInfoByName qr;
354 union lsa_TrustedDomainInfo *info;
355 struct lsa_Close cr;
356 struct policy_handle closed_handle;
358 torture_comment(tctx, "\nGetting LSA_TRUSTED_DOMAIN_INFO_FULL_INFO\n");
360 if(!test_get_policy_handle(tctx, p, LSA_POLICY_VIEW_LOCAL_INFORMATION,
361 &handle)) {
362 return false;
365 qr.in.handle = handle;
366 qr.in.trusted_domain = talloc_zero(tctx, struct lsa_String);
367 qr.in.trusted_domain->string = name;
368 qr.in.level = LSA_TRUSTED_DOMAIN_INFO_FULL_INFO;
369 qr.out.info = &info;
370 status = dcerpc_lsa_QueryTrustedDomainInfoByName_r(p->binding_handle,
371 tctx, &qr);
372 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
373 "QueryInfoPolicy2 failed");
374 if (!NT_STATUS_EQUAL(qr.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
375 torture_comment(tctx, "QueryInfoPolicy2 did not return "
376 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n");
377 return false;
380 cr.in.handle = handle;
381 cr.out.handle = &closed_handle;
382 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
383 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
384 "Close failed");
385 if (!NT_STATUS_IS_OK(cr.out.result)) {
386 torture_comment(tctx, "Close failed - %s\n",
387 nt_errstr(cr.out.result));
388 return false;
391 return true;
394 static bool get_lsa_policy_info_dns(struct dcerpc_pipe *p,
395 struct torture_context *tctx,
396 union lsa_PolicyInformation **info)
398 struct policy_handle *handle;
399 NTSTATUS status;
400 struct lsa_QueryInfoPolicy2 qr;
401 struct lsa_Close cr;
402 struct policy_handle closed_handle;
404 torture_comment(tctx, "\nGetting LSA_POLICY_INFO_DNS\n");
406 if (!test_get_policy_handle(tctx, p, LSA_POLICY_VIEW_LOCAL_INFORMATION,
407 &handle)) {
408 return false;
411 qr.in.handle = handle;
412 qr.in.level = LSA_POLICY_INFO_DNS;
413 qr.out.info = info;
414 status = dcerpc_lsa_QueryInfoPolicy2_r(p->binding_handle, tctx, &qr);
415 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
416 "QueryInfoPolicy2 failed");
417 if (!NT_STATUS_IS_OK(qr.out.result)) {
418 torture_comment(tctx, "QueryInfoPolicy2 failed - %s\n",
419 nt_errstr(qr.out.result));
420 return false;
423 cr.in.handle = handle;
424 cr.out.handle = &closed_handle;
425 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
426 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
427 "Close failed");
428 if (!NT_STATUS_IS_OK(cr.out.result)) {
429 torture_comment(tctx, "Close failed - %s\n",
430 nt_errstr(cr.out.result));
431 return false;
434 return true;
437 static bool delete_trusted_domain_by_sid(struct dcerpc_pipe *p,
438 struct torture_context *tctx,
439 struct dom_sid *domsid)
441 struct policy_handle *handle;
442 NTSTATUS status;
443 struct lsa_Close cr;
444 struct policy_handle closed_handle;
445 struct lsa_DeleteTrustedDomain dr;
446 bool ret = true;
448 torture_comment(tctx, "\nDeleting trusted domain.\n");
450 /* Against a windows server it was sufficient to have
451 * LSA_POLICY_VIEW_LOCAL_INFORMATION although the documentations says
452 * otherwise. */
453 if (!test_get_policy_handle(tctx, p, LSA_POLICY_TRUST_ADMIN,
454 &handle)) {
455 return false;
458 dr.in.handle = handle;
459 dr.in.dom_sid = domsid;
461 torture_assert_ntstatus_ok(tctx,
462 dcerpc_lsa_DeleteTrustedDomain_r(p->binding_handle, tctx, &dr),
463 "DeleteTrustedDomain failed");
464 if (!NT_STATUS_IS_OK(dr.out.result)) {
465 torture_comment(tctx, "DeleteTrustedDomain failed - %s\n",
466 nt_errstr(dr.out.result));
467 return false;
470 cr.in.handle = handle;
471 cr.out.handle = &closed_handle;
472 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
473 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
474 "Close failed");
475 if (!NT_STATUS_IS_OK(cr.out.result)) {
476 torture_comment(tctx, "Close failed - %s\n",
477 nt_errstr(cr.out.result));
478 ret = false;
481 return ret;
484 static const uint8_t my_blob[] = {
485 0xa3,0x0b,0x32,0x45,0x8b,0x84,0x3b,0x01,0x68,0xe8,0x2b,0xbb,0x00,0x13,0x69,0x1f,
486 0x10,0x35,0x72,0xa9,0x4f,0x77,0xb7,0xeb,0x59,0x08,0x07,0xc3,0xe8,0x17,0x00,0xc5,
487 0xf2,0xa9,0x6d,0xb7,0x69,0x45,0x63,0x20,0xcb,0x44,0x44,0x22,0x02,0xe3,0x28,0x84,
488 0x9b,0xd5,0x43,0x6f,0x8d,0x36,0x9b,0x9b,0x3b,0x31,0x86,0x84,0x8b,0xf2,0x36,0xd4,
489 0xe8,0xc4,0xee,0x90,0x0c,0xcb,0x3e,0x11,0x2f,0x86,0xfe,0x87,0x6d,0xce,0xae,0x0c,
490 0x83,0xfb,0x21,0x22,0x6d,0x7f,0x5e,0x08,0x71,0x1a,0x35,0xf4,0x5a,0x76,0x9b,0xf7,
491 0x54,0x62,0xa5,0x4c,0xcd,0xf6,0xa5,0xb0,0x0b,0xc7,0x79,0xe1,0x6f,0x85,0x16,0x6f,
492 0x82,0xdd,0x15,0x11,0x4c,0x9d,0x26,0x01,0x74,0x7e,0xbb,0xec,0x88,0x1d,0x71,0x9e,
493 0x5f,0xb2,0x9c,0xab,0x66,0x20,0x08,0x3d,0xae,0x07,0x2d,0xbb,0xa6,0xfb,0xec,0xcc,
494 0x51,0x58,0x48,0x47,0x38,0x3b,0x47,0x66,0xe8,0x17,0xfa,0x54,0x5c,0x95,0x73,0x29,
495 0xdf,0x7e,0x4a,0xb4,0x45,0x30,0xf7,0xbf,0xc0,0x56,0x6d,0x80,0xf6,0x11,0x56,0x93,
496 0xeb,0x97,0xd5,0x10,0xd6,0xd6,0xf7,0x23,0xc3,0xc0,0x93,0xa7,0x5c,0xa9,0xc0,0x81,
497 0x55,0x3d,0xec,0x03,0x31,0x7e,0x9d,0xf9,0xd0,0x9e,0xb5,0xc7,0xef,0xa8,0x54,0xf6,
498 0x9c,0xdc,0x0d,0xd4,0xd7,0xee,0x8d,0x5f,0xbd,0x89,0x48,0x3b,0x63,0xff,0xe8,0xca,
499 0x10,0x64,0x61,0xdf,0xfd,0x50,0xff,0x51,0xa0,0x2c,0xd7,0x8a,0xf1,0x13,0x02,0x02,
500 0x71,0xe9,0xff,0x0d,0x03,0x48,0xf8,0x08,0x8d,0xd5,0xe6,0x31,0x9f,0xf0,0x26,0x07,
501 0x91,0x6d,0xd3,0x01,0x91,0x92,0xc7,0x28,0x18,0x58,0xd8,0xf6,0x1b,0x97,0x8d,0xd0,
502 0xd2,0xa1,0x7c,0xae,0xc1,0xca,0xfe,0x20,0x91,0x1c,0x4d,0x15,0x89,0x29,0x37,0xd5,
503 0xf5,0xca,0x40,0x2b,0x03,0x8f,0x7b,0xc2,0x10,0xb4,0xd3,0xe8,0x14,0xb0,0x9b,0x5d,
504 0x85,0x30,0xe5,0x13,0x24,0xf7,0x78,0xec,0xbe,0x0b,0x9a,0x3f,0xb5,0x76,0xd9,0x0d,
505 0x49,0x64,0xa4,0xa7,0x33,0x88,0xdd,0xe9,0xe2,0x5f,0x04,0x51,0xdd,0x89,0xe2,0x68,
506 0x5b,0x5f,0x64,0x35,0xe3,0x23,0x4a,0x0e,0x09,0x15,0xcc,0x97,0x47,0xf4,0xc2,0x4f,
507 0x06,0xc3,0x96,0xa9,0x2f,0xb3,0xde,0x29,0x10,0xc7,0xf5,0x16,0xc5,0x3c,0x84,0xd2,
508 0x9b,0x6b,0xaa,0x54,0x59,0x8d,0x94,0xde,0xd1,0x75,0xb6,0x08,0x0d,0x7d,0xf1,0x18,
509 0xc8,0xf5,0xdf,0xaa,0xcd,0xec,0xab,0xb6,0xd1,0xcb,0xdb,0xe7,0x75,0x5d,0xbe,0x76,
510 0xea,0x1d,0x01,0xc8,0x0b,0x2d,0x32,0xe9,0xa8,0x65,0xbb,0x4a,0xcb,0x72,0xbc,0xda,
511 0x04,0x7f,0x82,0xfb,0x04,0xeb,0xd8,0xe1,0xb9,0xb1,0x1e,0xdc,0xb3,0x60,0xf3,0x55,
512 0x1e,0xcf,0x90,0x6a,0x15,0x74,0x4d,0xff,0xb4,0xc7,0xc9,0xc2,0x4f,0x67,0x9e,0xeb,
513 0x00,0x61,0x02,0xe3,0x9e,0x59,0x88,0x20,0xf1,0x0c,0xbe,0xe0,0x26,0x69,0x63,0x67,
514 0x72,0x3c,0x06,0x00,0x9e,0x4f,0xc7,0xa6,0x4d,0x6c,0xbe,0x68,0x8e,0xf4,0x32,0x36,
515 0x2e,0x5f,0xa6,0xcf,0xa7,0x19,0x40,0x2b,0xbd,0xa2,0x22,0x73,0xc4,0xb6,0xe3,0x86,
516 0x64,0xeb,0xb1,0xc7,0x45,0x7d,0xd6,0xd9,0x36,0xf1,0x04,0xd4,0x61,0xdc,0x41,0xb7,
517 0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, 0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
518 0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x34,0x00,
519 0x35,0x00,0x36,0x00,0x37,0x00,0x38,0x00,0x39,0x00,0x30,0x00,0x01,0x00,0x00,0x00,
520 0x0c,0x00,0x00,0x00, 0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
521 0x14,0x00,0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x34,0x00,0x35,0x00,0x36,0x00,
522 0x37,0x00,0x38,0x00,0x39,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00
525 static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx,
526 const char *password,
527 DATA_BLOB *auth_blob)
529 struct trustDomainPasswords auth_struct;
530 struct AuthenticationInformation *auth_info_array;
531 enum ndr_err_code ndr_err;
532 size_t converted_size;
534 generate_random_buffer(auth_struct.confounder,
535 sizeof(auth_struct.confounder));
537 auth_info_array = talloc_array(mem_ctx,
538 struct AuthenticationInformation, 1);
539 if (auth_info_array == NULL) {
540 return false;
543 auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR;
544 if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
545 strlen(password),
546 &auth_info_array[0].AuthInfo.clear.password,
547 &converted_size)) {
548 return false;
551 auth_info_array[0].AuthInfo.clear.size = converted_size;
553 auth_struct.outgoing.count = 1;
554 auth_struct.outgoing.current.count = 1;
555 auth_struct.outgoing.current.array = auth_info_array;
556 auth_struct.outgoing.previous.count = 0;
557 auth_struct.outgoing.previous.array = NULL;
559 auth_struct.incoming.count = 1;
560 auth_struct.incoming.current.count = 1;
561 auth_struct.incoming.current.array = auth_info_array;
562 auth_struct.incoming.previous.count = 0;
563 auth_struct.incoming.previous.array = NULL;
565 ndr_err = ndr_push_struct_blob(auth_blob, mem_ctx, &auth_struct,
566 (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
567 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
568 return false;
571 return true;
574 static bool test_validate_trust(struct torture_context *tctx,
575 const char *binding,
576 const char *trusting_dom_name,
577 const char *trusting_dom_dns_name,
578 const char *trusted_dom_name,
579 const char *trusted_dom_dns_name,
580 const char *trust_password)
582 struct netr_ServerGetTrustInfo r;
584 struct netr_Authenticator a;
585 struct netr_Authenticator return_authenticator;
586 struct samr_Password new_owf_password;
587 struct samr_Password old_owf_password;
588 struct netr_TrustInfo *trust_info;
590 struct netlogon_creds_CredentialState *creds;
592 NTSTATUS status;
593 struct cli_credentials *credentials;
594 struct dcerpc_binding *b;
595 struct dcerpc_pipe *pipe;
597 struct netr_GetForestTrustInformation fr;
598 struct lsa_ForestTrustInformation *forest_trust_info;
599 int i;
600 struct samr_Password nt_hash;
602 status = dcerpc_parse_binding(tctx, binding, &b);
603 torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
605 credentials = cli_credentials_init(tctx);
606 if (credentials == NULL) {
607 return false;
610 char *dummy = talloc_asprintf(tctx, "%s$", trusted_dom_name);
611 cli_credentials_set_username(credentials, dummy,
612 CRED_SPECIFIED);
613 cli_credentials_set_domain(credentials, trusting_dom_name,
614 CRED_SPECIFIED);
615 cli_credentials_set_realm(credentials, trusting_dom_dns_name,
616 CRED_SPECIFIED);
617 cli_credentials_set_password(credentials, trust_password, CRED_SPECIFIED);
618 cli_credentials_set_workstation(credentials,
619 trusted_dom_name, CRED_SPECIFIED);
620 cli_credentials_set_secure_channel_type(credentials, SEC_CHAN_DOMAIN);
622 status = dcerpc_pipe_connect_b(tctx, &pipe, b,
623 &ndr_table_netlogon, credentials,
624 tctx->ev, tctx->lp_ctx);
626 if (NT_STATUS_IS_ERR(status)) {
627 torture_comment(tctx, "Failed to connect to remote server: %s with %s - %s\n",
628 binding,
629 cli_credentials_get_unparsed_name(credentials, tctx),
630 nt_errstr(status));
631 return false;
634 if (!test_SetupCredentials3(pipe, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES,
635 credentials, &creds)) {
636 torture_comment(tctx, "test_SetupCredentials3 failed.\n");
637 return false;
640 netlogon_creds_client_authenticator(creds, &a);
642 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
643 dcerpc_server_name(pipe));
644 r.in.account_name = talloc_asprintf(tctx, "%s$", trusted_dom_name);
645 r.in.secure_channel_type = cli_credentials_get_secure_channel_type(credentials);
646 r.in.computer_name = trusted_dom_name;
647 r.in.credential = &a;
649 r.out.return_authenticator = &return_authenticator;
650 r.out.new_owf_password = &new_owf_password;
651 r.out.old_owf_password = &old_owf_password;
652 r.out.trust_info = &trust_info;
654 torture_assert_ntstatus_ok(tctx,
655 dcerpc_netr_ServerGetTrustInfo_r(pipe->binding_handle, tctx, &r),
656 "ServerGetTrustInfo failed");
657 torture_assert_ntstatus_ok(tctx, r.out.result,
658 "ServerGetTrustInfo failed");
660 if (trust_info->count != 1) {
661 torture_comment(tctx, "Unexpected number of results, "
662 "expected %d, got %d.\n",
663 1, trust_info->count);
664 return false;
666 if (trust_info->data[0] != 0) {
667 torture_comment(tctx, "Unexpected result, "
668 "expected %d, got %d.\n",
670 trust_info->data[0]);
671 return false;
674 E_md4hash(cli_credentials_get_password(credentials), nt_hash.hash);
676 netlogon_creds_des_decrypt(creds, &new_owf_password);
678 dump_data(1, new_owf_password.hash, 16);
679 dump_data(1, nt_hash.hash, 16);
681 torture_assert_mem_equal(tctx, new_owf_password.hash, nt_hash.hash, 16,
682 "received unexpected owf password\n");
684 netlogon_creds_client_authenticator(creds, &a);
686 fr.in.server_name = talloc_asprintf(tctx, "\\\\%s",
687 dcerpc_server_name(pipe));
688 fr.in.computer_name = trusted_dom_name;
689 fr.in.credential = &a;
690 fr.in.flags = 0;
691 fr.out.return_authenticator = &return_authenticator;
692 fr.out.forest_trust_info = &forest_trust_info;
694 torture_assert_ntstatus_ok(tctx,
695 dcerpc_netr_GetForestTrustInformation_r(pipe->binding_handle, tctx, &fr),
696 "netr_GetForestTrustInformation failed");
697 if (NT_STATUS_IS_ERR(fr.out.result)) {
698 torture_comment(tctx,
699 "netr_GetForestTrustInformation failed - %s.\n",
700 nt_errstr(fr.out.result));
701 return false;
704 if (forest_trust_info->count != 2) {
705 torture_comment(tctx, "Unexpected number of results, "
706 "expected %d, got %d.\n", 2,
707 forest_trust_info->count);
708 return false;
710 for(i = 0; i < forest_trust_info->count; i++) {
711 switch(forest_trust_info->entries[i]->type) {
712 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
713 if (strcmp(forest_trust_info->entries[i]->forest_trust_data.top_level_name.string, trusting_dom_dns_name) != 0) {
714 torture_comment(tctx, "Unexpected result, "
715 "expected %s, got %s.\n",
716 trusting_dom_dns_name,
717 forest_trust_info->entries[i]->forest_trust_data.top_level_name.string);
718 return false;
720 break;
721 case LSA_FOREST_TRUST_DOMAIN_INFO:
722 if (strcmp(forest_trust_info->entries[i]->forest_trust_data.domain_info.netbios_domain_name.string, trusting_dom_name) != 0) {
723 torture_comment(tctx, "Unexpected result, "
724 "expected %s, got %s.\n",
725 trusting_dom_dns_name,
726 forest_trust_info->entries[i]->forest_trust_data.domain_info.netbios_domain_name.string);
727 return false;
729 if (strcmp(forest_trust_info->entries[i]->forest_trust_data.domain_info.dns_domain_name.string, trusting_dom_dns_name) != 0) {
730 torture_comment(tctx, "Unexpected result, "
731 "expected %s, got %s.\n",
732 trusting_dom_dns_name,
733 forest_trust_info->entries[i]->forest_trust_data.domain_info.dns_domain_name.string);
734 return false;
736 break;
737 default:
738 torture_comment(tctx, "Unexpected result type, "
739 "expected %d|%d, got %d.\n",
740 LSA_FOREST_TRUST_TOP_LEVEL_NAME,
741 LSA_FOREST_TRUST_DOMAIN_INFO,
742 forest_trust_info->entries[i]->type);
743 return false;
747 return true;
750 static bool test_setup_trust(struct torture_context *tctx,
751 struct dcerpc_pipe *p,
752 const char *netbios_name,
753 const char *dns_name,
754 struct dom_sid *sid,
755 DATA_BLOB *auth_blob)
758 DATA_BLOB session_key;
759 struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
760 NTSTATUS status;
762 if (!check_name(p, tctx, netbios_name)) {
763 return false;
765 if (!check_name(p, tctx, dns_name)) {
766 return false;
769 status = dcerpc_fetch_session_key(p, &session_key);
770 if (!NT_STATUS_IS_OK(status)) {
771 torture_comment(tctx, "dcerpc_fetch_session_key failed - %s\n",
772 nt_errstr(status));
773 return false;
776 authinfo.auth_blob.data = talloc_memdup(tctx, auth_blob->data,
777 auth_blob->length);
778 if (authinfo.auth_blob.data == NULL) {
779 return false;
781 authinfo.auth_blob.size = auth_blob->length;
783 arcfour_crypt_blob(authinfo.auth_blob.data, authinfo.auth_blob.size,
784 &session_key);
786 if (!test_create_trust_and_set_info(p, tctx, netbios_name,
787 dns_name, sid, &authinfo)) {
788 return false;
791 return true;
794 static bool testcase_ForestTrusts(struct torture_context *tctx,
795 struct dcerpc_pipe *p)
797 bool ret = true;
798 const char *dom2_binding_string;
799 const char * dom2_cred_string;
800 NTSTATUS status;
801 struct dom_sid *domsid;
802 DATA_BLOB auth_blob;
803 struct dcerpc_binding *dom2_binding;
804 struct dcerpc_pipe *dom2_p;
805 struct cli_credentials *dom2_credentials;
806 union lsa_PolicyInformation *dom1_info_dns = NULL;
807 union lsa_PolicyInformation *dom2_info_dns = NULL;
808 const char *binding = torture_setting_string(tctx, "binding", NULL);
809 char *test_password;
811 torture_comment(tctx, "Testing Forest Trusts\n");
813 test_password = generate_random_password(tctx, 32, 64);
814 torture_assert(tctx, test_password != NULL, "test password must be generated");
816 if (!get_trust_domain_passwords_auth_blob(tctx, test_password, &auth_blob)) {
817 torture_comment(tctx,
818 "get_trust_domain_passwords_auth_blob failed\n");
819 return false;
822 #if 0
823 /* Use the following if get_trust_domain_passwords_auth_blob() cannot
824 * generate a usable blob due to errors in the IDL */
825 auth_blob.data = talloc_memdup(tctx, my_blob, sizeof(my_blob));
826 auth_blob.length = sizeof(my_blob);
828 test_password = "1234567890"
829 #endif
831 domsid = dom_sid_parse_talloc(tctx, TEST_DOM_SID);
832 if (domsid == NULL) {
833 return false;
836 if (!test_setup_trust(tctx, p, TEST_DOM, TEST_DOM_DNS, domsid,
837 &auth_blob)) {
838 ret = false;
841 if (!get_lsa_policy_info_dns(p, tctx, &dom1_info_dns)) {
842 return false;
845 if (!get_and_set_info(p, tctx, TEST_DOM)) {
846 return false;
849 if (!test_validate_trust(tctx, binding,
850 dom1_info_dns->dns.name.string,
851 dom1_info_dns->dns.dns_domain.string,
852 TEST_DOM, TEST_DOM_DNS, test_password)) {
853 ret = false;
856 if (!delete_trusted_domain_by_sid(p, tctx, domsid)) {
857 ret = false;
860 dom2_binding_string = torture_setting_string(tctx,
861 "Forest_Trust_Dom2_Binding",
862 NULL);
863 if (dom2_binding_string == NULL) {
864 return ret;
867 status = dcerpc_parse_binding(tctx, dom2_binding_string, &dom2_binding);
868 if (NT_STATUS_IS_ERR(status)) {
869 DEBUG(0,("Failed to parse dcerpc binding '%s'\n",
870 dom2_binding_string));
871 return false;
874 dom2_cred_string = torture_setting_string(tctx,
875 "Forest_Trust_Dom2_Creds",
876 NULL);
877 if (dom2_cred_string == NULL) {
878 return false;
881 dom2_credentials = cli_credentials_init(tctx);
882 if (dom2_credentials == NULL) {
883 return false;
886 cli_credentials_parse_string(dom2_credentials, dom2_cred_string,
887 CRED_SPECIFIED);
888 cli_credentials_set_workstation(dom2_credentials,
889 TEST_MACHINE_NAME, CRED_SPECIFIED);
891 status = dcerpc_pipe_connect_b(tctx, &dom2_p, dom2_binding,
892 &ndr_table_lsarpc, dom2_credentials,
893 tctx->ev, tctx->lp_ctx);
895 if (NT_STATUS_IS_ERR(status)) {
896 torture_comment(tctx, "Failed to connect to remote server: %s %s\n",
897 dcerpc_binding_string(tctx, dom2_binding),
898 nt_errstr(status));
899 return false;
902 if (!get_lsa_policy_info_dns(dom2_p, tctx, &dom2_info_dns)) {
903 return false;
906 if (strcasecmp(dom1_info_dns->dns.name.string,
907 dom2_info_dns->dns.name.string) == 0 ||
908 strcasecmp(dom1_info_dns->dns.dns_domain.string,
909 dom2_info_dns->dns.dns_domain.string) == 0)
911 torture_comment(tctx, "Trusting and trusted domain have the "
912 "same name.\n");
913 return false;
916 if (!test_setup_trust(tctx, p, dom2_info_dns->dns.name.string,
917 dom2_info_dns->dns.dns_domain.string,
918 dom2_info_dns->dns.sid, &auth_blob)) {
919 ret = false;
921 if (!test_setup_trust(tctx, dom2_p, dom1_info_dns->dns.name.string,
922 dom1_info_dns->dns.dns_domain.string,
923 dom1_info_dns->dns.sid, &auth_blob)) {
924 ret = false;
927 if (!test_validate_trust(tctx, binding,
928 dom1_info_dns->dns.name.string,
929 dom1_info_dns->dns.dns_domain.string,
930 dom2_info_dns->dns.name.string,
931 dom2_info_dns->dns.dns_domain.string, test_password)) {
932 ret = false;
935 if (!test_validate_trust(tctx, dom2_binding_string,
936 dom2_info_dns->dns.name.string,
937 dom2_info_dns->dns.dns_domain.string,
938 dom1_info_dns->dns.name.string,
939 dom1_info_dns->dns.dns_domain.string, test_password)) {
940 ret = false;
943 if (!delete_trusted_domain_by_sid(p, tctx, dom2_info_dns->dns.sid)) {
944 ret = false;
947 if (!delete_trusted_domain_by_sid(dom2_p, tctx, dom1_info_dns->dns.sid)) {
948 ret = false;
951 return ret;
954 /* By default this test creates a trust object in the destination server to a
955 * dummy domain. If a second server from a different domain is specified on the
956 * command line a trust is created between those two domains.
958 * Example:
959 * smbtorture ncacn_np:srv1.dom1.test[print] RPC-LSA-FOREST-TRUST \
960 * -U 'dom1\testadm1%12345678' \
961 * --option=torture:Forest_Trust_Dom2_Binding=ncacn_np:srv2.dom2.test[print] \
962 * --option=torture:Forest_Trust_Dom2_Creds='dom2\testadm2%12345678'
965 struct torture_suite *torture_rpc_lsa_forest_trust(TALLOC_CTX *mem_ctx)
967 struct torture_suite *suite;
968 struct torture_rpc_tcase *tcase;
970 suite = torture_suite_create(mem_ctx, "lsa.forest.trust");
972 tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa-forest-trust",
973 &ndr_table_lsarpc);
974 torture_rpc_tcase_add_test(tcase, "ForestTrust", testcase_ForestTrusts);
976 return suite;