s4-smbtorture: Fix for RPC-LSA-FOREST-TRUST.
[Samba/vl.git] / source4 / torture / rpc / forest_trust.c
blob2abb489eb43fa42428ae796b24a9af194d1b6455
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"
39 #define TPASS "1234567890"
42 static bool test_get_policy_handle(struct torture_context *tctx,
43 struct dcerpc_pipe *p,
44 uint32_t access_mask,
45 struct policy_handle **handle )
47 struct policy_handle *h;
48 struct lsa_OpenPolicy2 pr;
49 struct lsa_ObjectAttribute attr;
50 NTSTATUS status;
52 h = talloc(tctx, struct policy_handle);
53 if (!h) {
54 return false;
57 attr.len = 0;
58 attr.root_dir = NULL;
59 attr.object_name = NULL;
60 attr.attributes = 0;
61 attr.sec_desc = NULL;
62 attr.sec_qos = NULL;
64 pr.in.system_name = "\\";
65 pr.in.attr = &attr;
66 pr.in.access_mask = access_mask;
67 pr.out.handle = h;
69 status = dcerpc_lsa_OpenPolicy2_r(p->binding_handle, tctx, &pr);
70 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
71 "OpenPolicy2 failed");
72 if (!NT_STATUS_IS_OK(pr.out.result)) {
73 torture_comment(tctx, "OpenPolicy2 failed - %s\n",
74 nt_errstr(pr.out.result));
75 talloc_free(h);
76 return false;
79 *handle = h;
80 return true;
83 static bool test_create_trust_and_set_info(struct dcerpc_pipe *p,
84 struct torture_context *tctx,
85 const char *trust_name,
86 const char *trust_name_dns,
87 struct dom_sid *domsid,
88 struct lsa_TrustDomainInfoAuthInfoInternal *authinfo)
90 struct policy_handle *handle;
91 NTSTATUS status;
92 struct lsa_lsaRSetForestTrustInformation fti;
93 struct lsa_ForestTrustCollisionInfo *collision_info = NULL;
94 struct lsa_Close cr;
95 struct policy_handle closed_handle;
96 bool ret = true;
97 struct lsa_CreateTrustedDomainEx2 r;
98 struct lsa_TrustDomainInfoInfoEx trustinfo;
99 struct policy_handle trustdom_handle;
100 struct lsa_QueryTrustedDomainInfo q;
101 union lsa_TrustedDomainInfo *info = NULL;
103 if (!test_get_policy_handle(tctx, p,
104 (LSA_POLICY_VIEW_LOCAL_INFORMATION |
105 LSA_POLICY_TRUST_ADMIN |
106 LSA_POLICY_CREATE_SECRET), &handle)) {
107 return false;
110 torture_comment(tctx, "\nTesting CreateTrustedDomainEx2\n");
112 trustinfo.sid = domsid;
113 trustinfo.netbios_name.string = trust_name;
114 trustinfo.domain_name.string = trust_name_dns;
116 trustinfo.trust_direction = LSA_TRUST_DIRECTION_INBOUND |
117 LSA_TRUST_DIRECTION_OUTBOUND;
119 trustinfo.trust_type = LSA_TRUST_TYPE_UPLEVEL;
121 trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE;
123 r.in.policy_handle = handle;
124 r.in.info = &trustinfo;
125 r.in.auth_info = authinfo;
126 /* LSA_TRUSTED_QUERY_DOMAIN_NAME is needed for for following
127 * QueryTrustedDomainInfo call, although it seems that Windows does not
128 * expect this */
129 r.in.access_mask = LSA_TRUSTED_SET_POSIX | LSA_TRUSTED_SET_AUTH | LSA_TRUSTED_QUERY_DOMAIN_NAME;
130 r.out.trustdom_handle = &trustdom_handle;
132 torture_assert_ntstatus_ok(tctx,
133 dcerpc_lsa_CreateTrustedDomainEx2_r(p->binding_handle, tctx, &r),
134 "CreateTrustedDomainEx2 failed");
135 if (!NT_STATUS_IS_OK(r.out.result)) {
136 torture_comment(tctx, "CreateTrustedDomainEx failed2 - %s\n", nt_errstr(r.out.result));
137 ret = false;
138 } else {
140 q.in.trustdom_handle = &trustdom_handle;
141 q.in.level = LSA_TRUSTED_DOMAIN_INFO_INFO_EX;
142 q.out.info = &info;
144 torture_assert_ntstatus_ok(tctx,
145 dcerpc_lsa_QueryTrustedDomainInfo_r(p->binding_handle, tctx, &q),
146 "QueryTrustedDomainInfo failed");
147 if (!NT_STATUS_IS_OK(q.out.result)) {
148 torture_comment(tctx,
149 "QueryTrustedDomainInfo level 1 failed - %s\n",
150 nt_errstr(q.out.result));
151 ret = false;
152 } else if (!q.out.info) {
153 torture_comment(tctx,
154 "QueryTrustedDomainInfo level 1 failed to return an info pointer\n");
155 ret = false;
156 } else {
157 if (strcmp(info->info_ex.netbios_name.string, trustinfo.netbios_name.string) != 0) {
158 torture_comment(tctx,
159 "QueryTrustedDomainInfo returned inconsistant short name: %s != %s\n",
160 info->info_ex.netbios_name.string,
161 trustinfo.netbios_name.string);
162 ret = false;
164 if (info->info_ex.trust_type != trustinfo.trust_type) {
165 torture_comment(tctx,
166 "QueryTrustedDomainInfo of %s returned incorrect trust type %d != %d\n",
167 trust_name,
168 info->info_ex.trust_type,
169 trustinfo.trust_type);
170 ret = false;
172 if (info->info_ex.trust_attributes != trustinfo.trust_attributes) {
173 torture_comment(tctx,
174 "QueryTrustedDomainInfo of %s returned incorrect trust attributes %d != %d\n",
175 trust_name,
176 info->info_ex.trust_attributes,
177 trustinfo.trust_attributes);
178 ret = false;
180 if (info->info_ex.trust_direction != trustinfo.trust_direction) {
181 torture_comment(tctx,
182 "QueryTrustedDomainInfo of %s returned incorrect trust direction %d != %d\n",
183 trust_name,
184 info->info_ex.trust_direction,
185 trustinfo.trust_direction);
186 ret = false;
191 if (ret != false) {
192 fti.in.handle = &trustdom_handle;
193 fti.in.trusted_domain_name = talloc_zero(tctx, struct lsa_StringLarge);
194 fti.in.trusted_domain_name->string = trust_name_dns;
195 fti.in.highest_record_type = 2;
196 fti.in.forest_trust_info = talloc_zero(tctx, struct lsa_ForestTrustInformation);
197 fti.in.forest_trust_info->count = 2;
198 fti.in.forest_trust_info->entries = talloc_array(tctx, struct lsa_ForestTrustRecord *, 2);
199 fti.in.forest_trust_info->entries[0] = talloc_zero(tctx, struct lsa_ForestTrustRecord);
200 fti.in.forest_trust_info->entries[0]->flags = 0;
201 fti.in.forest_trust_info->entries[0]->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
202 fti.in.forest_trust_info->entries[0]->time = 0;
203 fti.in.forest_trust_info->entries[0]->forest_trust_data.top_level_name.string = trust_name_dns;
204 fti.in.forest_trust_info->entries[1] = talloc_zero(tctx, struct lsa_ForestTrustRecord);
205 fti.in.forest_trust_info->entries[1]->flags = 0;
206 fti.in.forest_trust_info->entries[1]->type = LSA_FOREST_TRUST_DOMAIN_INFO;
207 fti.in.forest_trust_info->entries[1]->time = 0;
208 fti.in.forest_trust_info->entries[1]->forest_trust_data.domain_info.domain_sid = domsid;
209 fti.in.forest_trust_info->entries[1]->forest_trust_data.domain_info.dns_domain_name.string = trust_name_dns;
210 fti.in.forest_trust_info->entries[1]->forest_trust_data.domain_info.netbios_domain_name.string = trust_name;
211 fti.in.check_only = 0;
212 fti.out.collision_info = &collision_info;
214 torture_comment(tctx, "\nTesting SetForestTrustInformation\n");
216 torture_assert_ntstatus_ok(tctx,
217 dcerpc_lsa_lsaRSetForestTrustInformation_r(p->binding_handle, tctx, &fti),
218 "lsaRSetForestTrustInformation failed");
219 if (!NT_STATUS_IS_OK(fti.out.result)) {
220 torture_comment(tctx,
221 "lsaRSetForestTrustInformation failed - %s\n",
222 nt_errstr(fti.out.result));
223 ret = false;
227 cr.in.handle = handle;
228 cr.out.handle = &closed_handle;
229 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
230 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
231 "Close failed");
232 if (!NT_STATUS_IS_OK(cr.out.result)) {
233 torture_comment(tctx, "Close failed - %s\n",
234 nt_errstr(cr.out.result));
235 ret = false;
238 return ret;
241 static bool check_name(struct dcerpc_pipe *p, struct torture_context *tctx,
242 const char *name)
244 struct policy_handle *handle;
245 NTSTATUS status;
246 struct lsa_QueryTrustedDomainInfoByName qr;
247 union lsa_TrustedDomainInfo *info;
248 struct lsa_Close cr;
249 struct policy_handle closed_handle;
251 torture_comment(tctx, "\nGetting LSA_TRUSTED_DOMAIN_INFO_FULL_INFO\n");
253 if(!test_get_policy_handle(tctx, p, LSA_POLICY_VIEW_LOCAL_INFORMATION,
254 &handle)) {
255 return false;
258 qr.in.handle = handle;
259 qr.in.trusted_domain = talloc_zero(tctx, struct lsa_String);
260 qr.in.trusted_domain->string = name;
261 qr.in.level = LSA_TRUSTED_DOMAIN_INFO_FULL_INFO;
262 qr.out.info = &info;
263 status = dcerpc_lsa_QueryTrustedDomainInfoByName_r(p->binding_handle,
264 tctx, &qr);
265 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
266 "QueryInfoPolicy2 failed");
267 if (!NT_STATUS_EQUAL(qr.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
268 torture_comment(tctx, "QueryInfoPolicy2 did not return "
269 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n");
270 return false;
273 cr.in.handle = handle;
274 cr.out.handle = &closed_handle;
275 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
276 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
277 "Close failed");
278 if (!NT_STATUS_IS_OK(cr.out.result)) {
279 torture_comment(tctx, "Close failed - %s\n",
280 nt_errstr(cr.out.result));
281 return false;
284 return true;
286 static bool get_lsa_policy_info_dns(struct dcerpc_pipe *p,
287 struct torture_context *tctx,
288 union lsa_PolicyInformation **info)
290 struct policy_handle *handle;
291 NTSTATUS status;
292 struct lsa_QueryInfoPolicy2 qr;
293 struct lsa_Close cr;
294 struct policy_handle closed_handle;
296 torture_comment(tctx, "\nGetting LSA_POLICY_INFO_DNS\n");
298 if (!test_get_policy_handle(tctx, p, LSA_POLICY_VIEW_LOCAL_INFORMATION,
299 &handle)) {
300 return false;
303 qr.in.handle = handle;
304 qr.in.level = LSA_POLICY_INFO_DNS;
305 qr.out.info = info;
306 status = dcerpc_lsa_QueryInfoPolicy2_r(p->binding_handle, tctx, &qr);
307 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
308 "QueryInfoPolicy2 failed");
309 if (!NT_STATUS_IS_OK(qr.out.result)) {
310 torture_comment(tctx, "QueryInfoPolicy2 failed - %s\n",
311 nt_errstr(qr.out.result));
312 return false;
315 cr.in.handle = handle;
316 cr.out.handle = &closed_handle;
317 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
318 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
319 "Close failed");
320 if (!NT_STATUS_IS_OK(cr.out.result)) {
321 torture_comment(tctx, "Close failed - %s\n",
322 nt_errstr(cr.out.result));
323 return false;
326 return true;
329 static bool delete_trusted_domain_by_sid(struct dcerpc_pipe *p,
330 struct torture_context *tctx,
331 struct dom_sid *domsid)
333 struct policy_handle *handle;
334 NTSTATUS status;
335 struct lsa_Close cr;
336 struct policy_handle closed_handle;
337 struct lsa_DeleteTrustedDomain dr;
338 bool ret = true;
340 torture_comment(tctx, "\nDeleting trusted domain.\n");
342 /* Against a windows server it was sufficient to have
343 * LSA_POLICY_VIEW_LOCAL_INFORMATION although the documentations says
344 * otherwise. */
345 if (!test_get_policy_handle(tctx, p, LSA_POLICY_TRUST_ADMIN,
346 &handle)) {
347 return false;
350 dr.in.handle = handle;
351 dr.in.dom_sid = domsid;
353 torture_assert_ntstatus_ok(tctx,
354 dcerpc_lsa_DeleteTrustedDomain_r(p->binding_handle, tctx, &dr),
355 "DeleteTrustedDomain failed");
356 if (!NT_STATUS_IS_OK(dr.out.result)) {
357 torture_comment(tctx, "DeleteTrustedDomain failed - %s\n",
358 nt_errstr(dr.out.result));
359 return false;
362 cr.in.handle = handle;
363 cr.out.handle = &closed_handle;
364 status = dcerpc_lsa_Close_r(p->binding_handle, tctx, &cr);
365 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK,
366 "Close failed");
367 if (!NT_STATUS_IS_OK(cr.out.result)) {
368 torture_comment(tctx, "Close failed - %s\n",
369 nt_errstr(cr.out.result));
370 ret = false;
373 return ret;
376 static const uint8_t my_blob[] = {
377 0xa3,0x0b,0x32,0x45,0x8b,0x84,0x3b,0x01,0x68,0xe8,0x2b,0xbb,0x00,0x13,0x69,0x1f,
378 0x10,0x35,0x72,0xa9,0x4f,0x77,0xb7,0xeb,0x59,0x08,0x07,0xc3,0xe8,0x17,0x00,0xc5,
379 0xf2,0xa9,0x6d,0xb7,0x69,0x45,0x63,0x20,0xcb,0x44,0x44,0x22,0x02,0xe3,0x28,0x84,
380 0x9b,0xd5,0x43,0x6f,0x8d,0x36,0x9b,0x9b,0x3b,0x31,0x86,0x84,0x8b,0xf2,0x36,0xd4,
381 0xe8,0xc4,0xee,0x90,0x0c,0xcb,0x3e,0x11,0x2f,0x86,0xfe,0x87,0x6d,0xce,0xae,0x0c,
382 0x83,0xfb,0x21,0x22,0x6d,0x7f,0x5e,0x08,0x71,0x1a,0x35,0xf4,0x5a,0x76,0x9b,0xf7,
383 0x54,0x62,0xa5,0x4c,0xcd,0xf6,0xa5,0xb0,0x0b,0xc7,0x79,0xe1,0x6f,0x85,0x16,0x6f,
384 0x82,0xdd,0x15,0x11,0x4c,0x9d,0x26,0x01,0x74,0x7e,0xbb,0xec,0x88,0x1d,0x71,0x9e,
385 0x5f,0xb2,0x9c,0xab,0x66,0x20,0x08,0x3d,0xae,0x07,0x2d,0xbb,0xa6,0xfb,0xec,0xcc,
386 0x51,0x58,0x48,0x47,0x38,0x3b,0x47,0x66,0xe8,0x17,0xfa,0x54,0x5c,0x95,0x73,0x29,
387 0xdf,0x7e,0x4a,0xb4,0x45,0x30,0xf7,0xbf,0xc0,0x56,0x6d,0x80,0xf6,0x11,0x56,0x93,
388 0xeb,0x97,0xd5,0x10,0xd6,0xd6,0xf7,0x23,0xc3,0xc0,0x93,0xa7,0x5c,0xa9,0xc0,0x81,
389 0x55,0x3d,0xec,0x03,0x31,0x7e,0x9d,0xf9,0xd0,0x9e,0xb5,0xc7,0xef,0xa8,0x54,0xf6,
390 0x9c,0xdc,0x0d,0xd4,0xd7,0xee,0x8d,0x5f,0xbd,0x89,0x48,0x3b,0x63,0xff,0xe8,0xca,
391 0x10,0x64,0x61,0xdf,0xfd,0x50,0xff,0x51,0xa0,0x2c,0xd7,0x8a,0xf1,0x13,0x02,0x02,
392 0x71,0xe9,0xff,0x0d,0x03,0x48,0xf8,0x08,0x8d,0xd5,0xe6,0x31,0x9f,0xf0,0x26,0x07,
393 0x91,0x6d,0xd3,0x01,0x91,0x92,0xc7,0x28,0x18,0x58,0xd8,0xf6,0x1b,0x97,0x8d,0xd0,
394 0xd2,0xa1,0x7c,0xae,0xc1,0xca,0xfe,0x20,0x91,0x1c,0x4d,0x15,0x89,0x29,0x37,0xd5,
395 0xf5,0xca,0x40,0x2b,0x03,0x8f,0x7b,0xc2,0x10,0xb4,0xd3,0xe8,0x14,0xb0,0x9b,0x5d,
396 0x85,0x30,0xe5,0x13,0x24,0xf7,0x78,0xec,0xbe,0x0b,0x9a,0x3f,0xb5,0x76,0xd9,0x0d,
397 0x49,0x64,0xa4,0xa7,0x33,0x88,0xdd,0xe9,0xe2,0x5f,0x04,0x51,0xdd,0x89,0xe2,0x68,
398 0x5b,0x5f,0x64,0x35,0xe3,0x23,0x4a,0x0e,0x09,0x15,0xcc,0x97,0x47,0xf4,0xc2,0x4f,
399 0x06,0xc3,0x96,0xa9,0x2f,0xb3,0xde,0x29,0x10,0xc7,0xf5,0x16,0xc5,0x3c,0x84,0xd2,
400 0x9b,0x6b,0xaa,0x54,0x59,0x8d,0x94,0xde,0xd1,0x75,0xb6,0x08,0x0d,0x7d,0xf1,0x18,
401 0xc8,0xf5,0xdf,0xaa,0xcd,0xec,0xab,0xb6,0xd1,0xcb,0xdb,0xe7,0x75,0x5d,0xbe,0x76,
402 0xea,0x1d,0x01,0xc8,0x0b,0x2d,0x32,0xe9,0xa8,0x65,0xbb,0x4a,0xcb,0x72,0xbc,0xda,
403 0x04,0x7f,0x82,0xfb,0x04,0xeb,0xd8,0xe1,0xb9,0xb1,0x1e,0xdc,0xb3,0x60,0xf3,0x55,
404 0x1e,0xcf,0x90,0x6a,0x15,0x74,0x4d,0xff,0xb4,0xc7,0xc9,0xc2,0x4f,0x67,0x9e,0xeb,
405 0x00,0x61,0x02,0xe3,0x9e,0x59,0x88,0x20,0xf1,0x0c,0xbe,0xe0,0x26,0x69,0x63,0x67,
406 0x72,0x3c,0x06,0x00,0x9e,0x4f,0xc7,0xa6,0x4d,0x6c,0xbe,0x68,0x8e,0xf4,0x32,0x36,
407 0x2e,0x5f,0xa6,0xcf,0xa7,0x19,0x40,0x2b,0xbd,0xa2,0x22,0x73,0xc4,0xb6,0xe3,0x86,
408 0x64,0xeb,0xb1,0xc7,0x45,0x7d,0xd6,0xd9,0x36,0xf1,0x04,0xd4,0x61,0xdc,0x41,0xb7,
409 0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, 0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
410 0x02,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x34,0x00,
411 0x35,0x00,0x36,0x00,0x37,0x00,0x38,0x00,0x39,0x00,0x30,0x00,0x01,0x00,0x00,0x00,
412 0x0c,0x00,0x00,0x00, 0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
413 0x14,0x00,0x00,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x34,0x00,0x35,0x00,0x36,0x00,
414 0x37,0x00,0x38,0x00,0x39,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00
417 static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx,
418 const char *password,
419 DATA_BLOB *auth_blob)
421 struct trustDomainPasswords auth_struct;
422 struct AuthenticationInformation *auth_info_array;
423 enum ndr_err_code ndr_err;
424 size_t converted_size;
426 generate_random_buffer(auth_struct.confounder,
427 sizeof(auth_struct.confounder));
429 auth_info_array = talloc_array(mem_ctx,
430 struct AuthenticationInformation, 1);
431 if (auth_info_array == NULL) {
432 return false;
435 auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR;
436 if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
437 strlen(password),
438 &auth_info_array[0].AuthInfo.clear.password,
439 &converted_size,
440 false)) {
441 return false;
444 auth_info_array[0].AuthInfo.clear.size = converted_size;
446 auth_struct.outgoing.count = 1;
447 auth_struct.outgoing.current.count = 1;
448 auth_struct.outgoing.current.array = auth_info_array;
449 auth_struct.outgoing.previous.count = 0;
450 auth_struct.outgoing.previous.array = NULL;
452 auth_struct.incoming.count = 1;
453 auth_struct.incoming.current.count = 1;
454 auth_struct.incoming.current.array = auth_info_array;
455 auth_struct.incoming.previous.count = 0;
456 auth_struct.incoming.previous.array = NULL;
458 ndr_err = ndr_push_struct_blob(auth_blob, mem_ctx, &auth_struct,
459 (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
460 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
461 return false;
464 return true;
467 static bool test_validate_trust(struct torture_context *tctx,
468 struct dcerpc_binding *binding,
469 const char *trusting_dom_name,
470 const char *trusting_dom_dns_name,
471 const char *trusted_dom_name,
472 const char *trusted_dom_dns_name)
474 struct netr_ServerGetTrustInfo r;
476 struct netr_Authenticator a;
477 struct netr_Authenticator return_authenticator;
478 struct samr_Password new_owf_password;
479 struct samr_Password old_owf_password;
480 struct netr_TrustInfo *trust_info;
482 struct netlogon_creds_CredentialState *creds;
484 NTSTATUS status;
485 struct cli_credentials *credentials;
486 struct dcerpc_pipe *pipe;
488 struct netr_GetForestTrustInformation fr;
489 struct lsa_ForestTrustInformation *forest_trust_info;
490 int i;
493 credentials = cli_credentials_init(tctx);
494 if (credentials == NULL) {
495 return false;
498 char *dummy = talloc_asprintf(tctx, "%s$", trusted_dom_name);
499 cli_credentials_set_username(credentials, dummy,
500 CRED_SPECIFIED);
501 cli_credentials_set_domain(credentials, trusting_dom_name,
502 CRED_SPECIFIED);
503 cli_credentials_set_realm(credentials, trusting_dom_dns_name,
504 CRED_SPECIFIED);
505 cli_credentials_set_password(credentials, TPASS, CRED_SPECIFIED);
506 cli_credentials_set_workstation(credentials,
507 trusted_dom_name, CRED_SPECIFIED);
508 cli_credentials_set_secure_channel_type(credentials, SEC_CHAN_DOMAIN);
510 status = dcerpc_pipe_connect_b(tctx, &pipe, binding,
511 &ndr_table_netlogon, credentials,
512 tctx->ev, tctx->lp_ctx);
514 if (NT_STATUS_IS_ERR(status)) {
515 torture_comment(tctx, "Failed to connect to remote server: %s with %s - %s\n",
516 dcerpc_binding_string(tctx, binding),
517 cli_credentials_get_unparsed_name(credentials, tctx),
518 nt_errstr(status));
519 return false;
522 if (!test_SetupCredentials3(pipe, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
523 credentials, &creds)) {
524 torture_comment(tctx, "test_SetupCredentials3 failed.\n");
525 return false;
528 netlogon_creds_client_authenticator(creds, &a);
530 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
531 dcerpc_server_name(pipe));
532 r.in.account_name = talloc_asprintf(tctx, "%s$", trusted_dom_name);
533 r.in.secure_channel_type = cli_credentials_get_secure_channel_type(credentials);
534 r.in.computer_name = trusted_dom_name;
535 r.in.credential = &a;
537 r.out.return_authenticator = &return_authenticator;
538 r.out.new_owf_password = &new_owf_password;
539 r.out.old_owf_password = &old_owf_password;
540 r.out.trust_info = &trust_info;
542 torture_assert_ntstatus_ok(tctx,
543 dcerpc_netr_ServerGetTrustInfo_r(pipe->binding_handle, tctx, &r),
544 "ServerGetTrustInfo failed");
545 torture_assert_ntstatus_ok(tctx, r.out.result,
546 "ServerGetTrustInfo failed");
548 if (trust_info->count != 1) {
549 torture_comment(tctx, "Unexpected number of results, "
550 "expected %d, got %d.\n",
551 1, trust_info->count);
552 return false;
554 if (trust_info->data[0] != LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
555 torture_comment(tctx, "Unexpected result, "
556 "expected %d, got %d.\n",
557 LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE,
558 trust_info->data[0]);
559 return false;
562 netlogon_creds_client_authenticator(creds, &a);
564 fr.in.server_name = talloc_asprintf(tctx, "\\\\%s",
565 dcerpc_server_name(pipe));
566 fr.in.computer_name = trusted_dom_name;
567 fr.in.credential = &a;
568 fr.in.flags = 0;
569 fr.out.return_authenticator = &return_authenticator;
570 fr.out.forest_trust_info = &forest_trust_info;
572 torture_assert_ntstatus_ok(tctx,
573 dcerpc_netr_GetForestTrustInformation_r(pipe->binding_handle, tctx, &fr),
574 "netr_GetForestTrustInformation failed");
575 if (NT_STATUS_IS_ERR(fr.out.result)) {
576 torture_comment(tctx,
577 "netr_GetForestTrustInformation failed - %s.\n",
578 nt_errstr(fr.out.result));
579 return false;
582 if (forest_trust_info->count != 2) {
583 torture_comment(tctx, "Unexpected number of results, "
584 "expected %d, got %d.\n", 2,
585 forest_trust_info->count);
586 return false;
588 for(i = 0; i < forest_trust_info->count; i++) {
589 switch(forest_trust_info->entries[i]->type) {
590 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
591 if (strcmp(forest_trust_info->entries[i]->forest_trust_data.top_level_name.string, trusting_dom_dns_name) != 0) {
592 torture_comment(tctx, "Unexpected result, "
593 "expected %s, got %s.\n",
594 trusting_dom_dns_name,
595 forest_trust_info->entries[i]->forest_trust_data.top_level_name.string);
596 return false;
598 break;
599 case LSA_FOREST_TRUST_DOMAIN_INFO:
600 if (strcmp(forest_trust_info->entries[i]->forest_trust_data.domain_info.netbios_domain_name.string, trusting_dom_name) != 0) {
601 torture_comment(tctx, "Unexpected result, "
602 "expected %s, got %s.\n",
603 trusting_dom_dns_name,
604 forest_trust_info->entries[i]->forest_trust_data.domain_info.netbios_domain_name.string);
605 return false;
607 if (strcmp(forest_trust_info->entries[i]->forest_trust_data.domain_info.dns_domain_name.string, trusting_dom_dns_name) != 0) {
608 torture_comment(tctx, "Unexpected result, "
609 "expected %s, got %s.\n",
610 trusting_dom_dns_name,
611 forest_trust_info->entries[i]->forest_trust_data.domain_info.dns_domain_name.string);
612 return false;
614 break;
615 default:
616 torture_comment(tctx, "Unexpected result type, "
617 "expected %d|%d, got %d.\n",
618 LSA_FOREST_TRUST_TOP_LEVEL_NAME,
619 LSA_FOREST_TRUST_DOMAIN_INFO,
620 forest_trust_info->entries[i]->type);
621 return false;
625 return true;
628 static bool test_setup_trust(struct torture_context *tctx,
629 struct dcerpc_pipe *p,
630 const char *netbios_name,
631 const char *dns_name,
632 struct dom_sid *sid,
633 DATA_BLOB *auth_blob)
636 DATA_BLOB session_key;
637 struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
638 NTSTATUS status;
640 if (!check_name(p, tctx, netbios_name)) {
641 return false;
643 if (!check_name(p, tctx, dns_name)) {
644 return false;
647 status = dcerpc_fetch_session_key(p, &session_key);
648 if (!NT_STATUS_IS_OK(status)) {
649 torture_comment(tctx, "dcerpc_fetch_session_key failed - %s\n",
650 nt_errstr(status));
651 return false;
654 authinfo.auth_blob.data = talloc_memdup(tctx, auth_blob->data,
655 auth_blob->length);
656 if (authinfo.auth_blob.data == NULL) {
657 return false;
659 authinfo.auth_blob.size = auth_blob->length;
661 arcfour_crypt_blob(authinfo.auth_blob.data, authinfo.auth_blob.size,
662 &session_key);
664 if (!test_create_trust_and_set_info(p, tctx, netbios_name,
665 dns_name, sid, &authinfo)) {
666 return false;
669 return true;
672 static bool testcase_ForestTrusts(struct torture_context *tctx,
673 struct dcerpc_pipe *p)
675 bool ret = true;
676 const char *dom2_binding_string;
677 const char * dom2_cred_string;
678 NTSTATUS status;
679 struct dom_sid *domsid;
680 DATA_BLOB auth_blob;
681 struct dcerpc_binding *dom2_binding;
682 struct dcerpc_pipe *dom2_p;
683 struct cli_credentials *dom2_credentials;
684 union lsa_PolicyInformation *dom1_info_dns = NULL;
685 union lsa_PolicyInformation *dom2_info_dns = NULL;
687 torture_comment(tctx, "Testing Forest Trusts\n");
689 if (!get_trust_domain_passwords_auth_blob(tctx, TPASS, &auth_blob)) {
690 torture_comment(tctx,
691 "get_trust_domain_passwords_auth_blob failed\n");
692 return false;
695 #if 0
696 /* Use the following if get_trust_domain_passwords_auth_blob() cannot
697 * generate a usable blob due to errors in the IDL */
698 auth_blob.data = talloc_memdup(tctx, my_blob, sizeof(my_blob));
699 auth_blob.length = sizeof(my_blob);
700 #endif
702 domsid = dom_sid_parse_talloc(tctx, TEST_DOM_SID);
703 if (domsid == NULL) {
704 return false;
707 if (!test_setup_trust(tctx, p, TEST_DOM, TEST_DOM_DNS, domsid,
708 &auth_blob)) {
709 ret = false;
712 if (!get_lsa_policy_info_dns(p, tctx, &dom1_info_dns)) {
713 return false;
716 if (!test_validate_trust(tctx, p->binding,
717 dom1_info_dns->dns.name.string,
718 dom1_info_dns->dns.dns_domain.string,
719 TEST_DOM, TEST_DOM_DNS)) {
720 ret = false;
723 if (!delete_trusted_domain_by_sid(p, tctx, domsid)) {
724 ret = false;
727 dom2_binding_string = torture_setting_string(tctx,
728 "Forest_Trust_Dom2_Binding",
729 NULL);
730 if (dom2_binding_string == NULL) {
731 return ret;
734 status = dcerpc_parse_binding(tctx, dom2_binding_string, &dom2_binding);
735 if (NT_STATUS_IS_ERR(status)) {
736 DEBUG(0,("Failed to parse dcerpc binding '%s'\n",
737 dom2_binding_string));
738 return false;
741 dom2_cred_string = torture_setting_string(tctx,
742 "Forest_Trust_Dom2_Creds",
743 NULL);
744 if (dom2_cred_string == NULL) {
745 return false;
748 dom2_credentials = cli_credentials_init(tctx);
749 if (dom2_credentials == NULL) {
750 return false;
753 cli_credentials_parse_string(dom2_credentials, dom2_cred_string,
754 CRED_SPECIFIED);
755 cli_credentials_set_workstation(dom2_credentials,
756 TEST_MACHINE_NAME, CRED_SPECIFIED);
758 status = dcerpc_pipe_connect_b(tctx, &dom2_p, dom2_binding,
759 &ndr_table_lsarpc, dom2_credentials,
760 tctx->ev, tctx->lp_ctx);
762 if (NT_STATUS_IS_ERR(status)) {
763 torture_comment(tctx, "Failed to connect to remote server: %s %s\n",
764 dcerpc_binding_string(tctx, dom2_binding),
765 nt_errstr(status));
766 return false;
769 if (!get_lsa_policy_info_dns(dom2_p, tctx, &dom2_info_dns)) {
770 return false;
773 if (strcasecmp(dom1_info_dns->dns.name.string,
774 dom2_info_dns->dns.name.string) == 0 ||
775 strcasecmp(dom1_info_dns->dns.dns_domain.string,
776 dom2_info_dns->dns.dns_domain.string) == 0)
778 torture_comment(tctx, "Trusting and trusted domain have the "
779 "same name.\n");
780 return false;
783 if (!test_setup_trust(tctx, p, dom2_info_dns->dns.name.string,
784 dom2_info_dns->dns.dns_domain.string,
785 dom2_info_dns->dns.sid, &auth_blob)) {
786 ret = false;
788 if (!test_setup_trust(tctx, dom2_p, dom1_info_dns->dns.name.string,
789 dom1_info_dns->dns.dns_domain.string,
790 dom1_info_dns->dns.sid, &auth_blob)) {
791 ret = false;
794 if (!test_validate_trust(tctx, p->binding,
795 dom1_info_dns->dns.name.string,
796 dom1_info_dns->dns.dns_domain.string,
797 dom2_info_dns->dns.name.string,
798 dom2_info_dns->dns.dns_domain.string)) {
799 ret = false;
802 if (!test_validate_trust(tctx, dom2_p->binding,
803 dom2_info_dns->dns.name.string,
804 dom2_info_dns->dns.dns_domain.string,
805 dom1_info_dns->dns.name.string,
806 dom1_info_dns->dns.dns_domain.string)) {
807 ret = false;
810 if (!delete_trusted_domain_by_sid(p, tctx, dom2_info_dns->dns.sid)) {
811 ret = false;
814 if (!delete_trusted_domain_by_sid(dom2_p, tctx, dom1_info_dns->dns.sid)) {
815 ret = false;
818 return ret;
821 /* By default this test creates a trust object in the destination server to a
822 * dummy domain. If a second server from a different domain is specified on the
823 * command line a trust is created between those two domains.
825 * Example:
826 * smbtorture ncacn_np:srv1.dom1.test[print] RPC-LSA-FOREST-TRUST \
827 * -U 'dom1\testadm1%12345678' \
828 * --option=torture:Forest_Trust_Dom2_Binding=ncacn_np:srv2.dom2.test[print] \
829 * --option=torture:Forest_Trust_Dom2_Creds='dom2\testadm2%12345678'
832 struct torture_suite *torture_rpc_lsa_forest_trust(TALLOC_CTX *mem_ctx)
834 struct torture_suite *suite;
835 struct torture_rpc_tcase *tcase;
837 suite = torture_suite_create(mem_ctx, "lsa.forest.trust");
839 tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa-forest-trust",
840 &ndr_table_lsarpc);
841 torture_rpc_tcase_add_test(tcase, "ForestTrust", testcase_ForestTrusts);
843 return suite;