2 Unix SMB/CIFS implementation.
3 test suite for various Domain DFS
4 Copyright (C) Matthieu Patou 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libcli/libcli.h"
22 #include "torture/smbtorture.h"
23 #include "torture/util.h"
24 #include "../librpc/gen_ndr/ndr_dfsblobs.h"
25 #include "librpc/ndr/libndr.h"
26 #include "param/param.h"
27 #include "torture/torture.h"
28 #include "torture/dfs/proto.h"
30 static bool test_getdomainreferral(struct torture_context
*tctx
,
31 struct smbcli_state
*cli
)
33 struct dfs_GetDFSReferral r
;
34 struct dfs_referral_resp resp
;
36 r
.in
.req
.max_referral_level
= 3;
37 r
.in
.req
.servername
= "";
40 torture_assert_ntstatus_ok(tctx
,
41 dfs_cli_do_call(cli
->tree
, &r
),
42 "Get Domain referral failed");
44 torture_assert_int_equal(tctx
, resp
.path_consumed
, 0,
45 "Path consumed not equal to 0");
46 torture_assert_int_equal(tctx
, resp
.nb_referrals
!= 0, 1,
47 "0 domains referrals returned");
48 torture_assert_int_equal(tctx
, resp
.header_flags
, 0,
49 "Header flag different it's not a referral server");
50 torture_assert_int_equal(tctx
, resp
.referral_entries
[1].version
, 3,
52 "Not expected version for referral entry 1 got %d expected 3",
53 resp
.referral_entries
[1].version
));
54 torture_assert_int_equal(tctx
, resp
.referral_entries
[0].version
, 3,
56 "Not expected version for referral entry 0 got %d expected 3",
57 resp
.referral_entries
[0].version
));
58 torture_assert_int_equal(tctx
, resp
.referral_entries
[0].referral
.v3
.server_type
,
61 "Wrong server type, expected non root server and got %d",
62 resp
.referral_entries
[0].referral
.v3
.server_type
));
63 torture_assert_int_equal(tctx
, resp
.referral_entries
[0].referral
.v3
.entry_flags
,
64 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
66 "Wrong entry flag expected to have a domain response and got %d",
67 resp
.referral_entries
[0].referral
.v3
.entry_flags
));
68 torture_assert_int_equal(tctx
, strlen(
69 resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
) > 0,
71 "Length of domain is 0 or less");
72 torture_assert_int_equal(tctx
,
73 resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
[0] == '\\',
75 "domain didn't start with a \\");
79 static bool test_getdcreferral(struct torture_context
*tctx
,
80 struct smbcli_state
*cli
)
82 struct dfs_GetDFSReferral r
, r2
, r3
;
83 struct dfs_referral_resp resp
, resp2
, resp3
;
87 r
.in
.req
.max_referral_level
= 3;
88 r
.in
.req
.servername
= "";
91 torture_assert_ntstatus_ok(tctx
,
92 dfs_cli_do_call(cli
->tree
, &r
),
93 "Get Domain referral failed");
95 str
= resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
96 if( strchr(str
, '.') == NULL
) {
97 str
= resp
.referral_entries
[1].referral
.v3
.referrals
.r2
.special_name
;
100 r2
.in
.req
.max_referral_level
= 3;
101 r2
.in
.req
.servername
= str
;
102 r2
.out
.resp
= &resp2
;
104 torture_assert_ntstatus_ok(tctx
,
105 dfs_cli_do_call(cli
->tree
, &r2
),
106 "Get DC Domain referral failed");
109 torture_assert_int_equal(tctx
, resp2
.path_consumed
, 0,
110 "Path consumed not equal to 0");
111 torture_assert_int_equal(tctx
, resp2
.nb_referrals
, 1,
112 "We do not received only 1 referral");
113 torture_assert_int_equal(tctx
, resp2
.header_flags
, 0,
114 "Header flag different it's not a referral server");
115 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].version
, 3,
116 talloc_asprintf(tctx
,
117 "Not expected version for referral entry 0 got %d expected 3",
118 resp2
.referral_entries
[0].version
));
119 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.server_type
,
121 talloc_asprintf(tctx
,
122 "Wrong server type, expected non root server and got %d",
123 resp2
.referral_entries
[0].referral
.v3
.server_type
));
124 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.entry_flags
,
125 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
126 talloc_asprintf(tctx
,
127 "Wrong entry flag expected to have a domain response and got %d",
128 resp2
.referral_entries
[0].referral
.v3
.entry_flags
));
129 torture_assert_int_equal(tctx
, strlen(
130 resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
) > 0,
132 "Length of domain is 0 or less");
133 torture_assert_int_equal(tctx
, strlen(
134 resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.expanded_names
[0]) > 0,
136 "Length of first dc is less than 0");
137 str
= strchr(resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.expanded_names
[0], '.');
138 str2
= resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
139 if (str2
[0] == '\\') {
142 torture_assert_int_equal(tctx
, strlen(str
) >0, 1 ,"Length of domain too short");
144 torture_assert_int_equal(tctx
, strcmp(str
,str2
), 0,
145 talloc_asprintf(tctx
, "Pb domain of the dc is not "\
146 "the same as the requested: domain was = %s got =%s",str2
,str
));
147 torture_assert_int_equal(tctx
,
148 resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
[0] == '\\',
150 "dc name didn't start with a \\");
152 r3
.in
.req
.max_referral_level
= 3;
154 * Windows 7 and at least windows 2008 server sends domain.fqdn instead of \domain.fqdn
155 * (as it is specified in the spec)
156 * Let's check that we are able to support it too
158 r3
.in
.req
.servername
= str
;
159 r3
.out
.resp
= &resp3
;
161 torture_assert_ntstatus_ok(tctx
,
162 dfs_cli_do_call(cli
->tree
, &r3
),
163 "Get DC Domain referral failed");
165 torture_assert_int_equal(tctx
, resp3
.path_consumed
, 0,
166 "Path consumed not equal to 0");
167 torture_assert_int_equal(tctx
, resp3
.nb_referrals
, 1,
168 "We do not received only 1 referral");
169 torture_assert_int_equal(tctx
, resp3
.header_flags
, 0,
170 "Header flag different it's not a referral server");
171 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
172 talloc_asprintf(tctx
,
173 "Not expected version for referral entry 0 got %d expected 3",
174 resp3
.referral_entries
[0].version
));
175 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.server_type
,
177 talloc_asprintf(tctx
,
178 "Wrong server type, expected non root server and got %d",
179 resp3
.referral_entries
[0].referral
.v3
.server_type
));
180 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.entry_flags
,
181 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
182 talloc_asprintf(tctx
,
183 "Wrong entry flag expected to have a domain response and got %d",
184 resp3
.referral_entries
[0].referral
.v3
.entry_flags
));
185 torture_assert_int_equal(tctx
, strlen(
186 resp3
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
) > 0,
188 "Length of domain is 0 or less");
189 torture_assert_int_equal(tctx
, strlen(
190 resp3
.referral_entries
[0].referral
.v3
.referrals
.r2
.expanded_names
[0]) > 0,
192 "Length of first dc is less than 0");
196 static bool test_getdcreferral_netbios(struct torture_context
*tctx
,
197 struct smbcli_state
*cli
)
199 struct dfs_GetDFSReferral r
, r2
, r3
;
200 struct dfs_referral_resp resp
, resp2
, resp3
;
203 r
.in
.req
.max_referral_level
= 3;
204 r
.in
.req
.servername
= "";
207 torture_assert_ntstatus_ok(tctx
,
208 dfs_cli_do_call(cli
->tree
, &r
),
209 "Get Domain referral failed");
211 r2
.in
.req
.max_referral_level
= 3;
213 str
= resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
214 if( strchr(str
, '.') != NULL
) {
215 str
= resp
.referral_entries
[1].referral
.v3
.referrals
.r2
.special_name
;
218 r2
.in
.req
.servername
= str
;
219 r2
.out
.resp
= &resp2
;
221 torture_assert_ntstatus_ok(tctx
,
222 dfs_cli_do_call(cli
->tree
, &r2
),
223 "Get DC Domain referral failed");
225 torture_assert_int_equal(tctx
, resp2
.path_consumed
, 0,
226 "Path consumed not equal to 0");
227 torture_assert_int_equal(tctx
, resp2
.nb_referrals
, 1,
228 "We do not received only 1 referral");
229 torture_assert_int_equal(tctx
, resp2
.header_flags
, 0,
230 "Header flag different it's not a referral server");
231 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].version
, 3,
232 talloc_asprintf(tctx
,
233 "Not expected version for referral entry 0 got %d expected 3",
234 resp2
.referral_entries
[0].version
));
235 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.server_type
,
237 talloc_asprintf(tctx
,
238 "Wrong server type, expected non root server and got %d",
239 resp2
.referral_entries
[0].referral
.v3
.server_type
));
240 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.entry_flags
,
241 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
242 talloc_asprintf(tctx
,
243 "Wrong entry flag expected to have a domain response and got %d",
244 resp2
.referral_entries
[0].referral
.v3
.entry_flags
));
245 torture_assert_int_equal(tctx
, strlen(
246 resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
) > 0,
248 "Length of domain is 0 or less");
249 torture_assert_int_equal(tctx
, strlen(
250 resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.expanded_names
[0]) > 0,
252 "Length of first dc is less than 0");
253 torture_assert(tctx
, strchr(
254 resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.expanded_names
[0],'.') == NULL
,
255 "referral contains dots it's not a netbios name");
257 r3
.in
.req
.max_referral_level
= 3;
259 * Windows 7 and at least windows 2008 server sends domain.fqdn instead of \domain.fqdn
260 * (as it is specified in the spec)
261 * Let's check that we are able to support it too
263 r3
.in
.req
.servername
= str
+ 1;
264 r3
.out
.resp
= &resp3
;
266 torture_assert_ntstatus_ok(tctx
,
267 dfs_cli_do_call(cli
->tree
, &r3
),
268 "Get DC Domain referral failed");
270 torture_assert_int_equal(tctx
, resp3
.path_consumed
, 0,
271 "Path consumed not equal to 0");
272 torture_assert_int_equal(tctx
, resp3
.nb_referrals
, 1,
273 "We do not received only 1 referral");
274 torture_assert_int_equal(tctx
, resp3
.header_flags
, 0,
275 "Header flag different it's not a referral server");
276 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
277 talloc_asprintf(tctx
,
278 "Not expected version for referral entry 0 got %d expected 3",
279 resp3
.referral_entries
[0].version
));
280 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.server_type
,
282 talloc_asprintf(tctx
,
283 "Wrong server type, expected non root server and got %d",
284 resp3
.referral_entries
[0].referral
.v3
.server_type
));
285 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.entry_flags
,
286 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
287 talloc_asprintf(tctx
,
288 "Wrong entry flag expected to have a domain response and got %d",
289 resp3
.referral_entries
[0].referral
.v3
.entry_flags
));
290 torture_assert_int_equal(tctx
, strlen(
291 resp3
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
) > 0,
293 "Length of domain is 0 or less");
294 torture_assert_int_equal(tctx
, strlen(
295 resp3
.referral_entries
[0].referral
.v3
.referrals
.r2
.expanded_names
[0]) > 0,
297 "Length of first dc is less than 0");
298 torture_assert(tctx
, strchr(
299 resp3
.referral_entries
[0].referral
.v3
.referrals
.r2
.expanded_names
[0],'.') == NULL
,
300 "referral contains dots it's not a netbios name");
304 static bool test_getsysvolreferral(struct torture_context
*tctx
,
305 struct smbcli_state
*cli
)
308 struct dfs_GetDFSReferral r
, r2
, r3
;
309 struct dfs_referral_resp resp
, resp2
, resp3
;
312 memset(zeros
, 0, sizeof(zeros
));
314 r
.in
.req
.max_referral_level
= 3;
315 r
.in
.req
.servername
= "";
318 torture_assert_ntstatus_ok(tctx
,
319 dfs_cli_do_call(cli
->tree
, &r
),
320 "Get Domain referral failed");
322 str
= resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
323 if( strchr(str
, '.') == NULL
) {
324 str
= resp
.referral_entries
[1].referral
.v3
.referrals
.r2
.special_name
;
327 r2
.in
.req
.max_referral_level
= 3;
328 r2
.in
.req
.servername
= str
;
329 r2
.out
.resp
= &resp2
;
331 torture_assert_ntstatus_ok(tctx
,
332 dfs_cli_do_call(cli
->tree
, &r2
),
333 "Get DC Domain referral failed");
335 r3
.in
.req
.max_referral_level
= 3;
336 r3
.in
.req
.servername
= talloc_asprintf(tctx
, "%s\\sysvol", str
);
337 r3
.out
.resp
= &resp3
;
339 torture_assert_ntstatus_ok(tctx
,
340 dfs_cli_do_call(cli
->tree
, &r3
),
341 "Get sysvol Domain referral failed");
343 torture_assert_int_equal(tctx
, resp3
.path_consumed
, 2*strlen(r3
.in
.req
.servername
),
344 "Path consumed not equal to length of the request");
345 torture_assert_int_equal(tctx
, resp3
.nb_referrals
!= 0, 1,
346 "We do not receive at least 1 referral");
347 torture_assert_int_equal(tctx
, resp3
.header_flags
, DFS_HEADER_FLAG_STORAGE_SVR
,
348 "Header flag different it's not a referral for a storage");
349 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
350 talloc_asprintf(tctx
,
351 "Not expected version for referral entry 0 got %d expected 3",
352 resp3
.referral_entries
[0].version
));
353 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.server_type
,
355 talloc_asprintf(tctx
,
356 "Wrong server type, expected non root server and got %d",
357 resp3
.referral_entries
[0].referral
.v3
.server_type
));
358 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.entry_flags
,
360 talloc_asprintf(tctx
,
361 "Wrong entry flag expected to have a non domain response and got %d",
362 resp3
.referral_entries
[0].referral
.v3
.entry_flags
));
363 torture_assert_int_equal(tctx
, strlen(
364 resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.DFS_path
) > 0,
366 "Length of domain is 0 or less");
367 torture_assert_int_equal(tctx
, strstr(resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.DFS_path
,
369 talloc_asprintf(tctx
,
370 "Wrong DFS_path %s unable to find substring %s in it",
371 resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.DFS_path
,
373 torture_assert_int_equal(tctx
, strlen(
374 resp2
.referral_entries
[0].referral
.v3
.referrals
.r1
.netw_address
) > 0,
376 "Length of first referral is less than 0");
377 torture_assert_int_equal(tctx
, strstr(resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.netw_address
,
379 talloc_asprintf(tctx
,
380 "Wrong DFS_path %s unable to find substring %s in it",
381 resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.netw_address
,
384 r3
.in
.req
.max_referral_level
= 4;
386 torture_assert_ntstatus_ok(tctx
,
387 dfs_cli_do_call(cli
->tree
, &r3
),
388 "Get sysvol Domain referral failed");
390 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 4,
391 talloc_asprintf(tctx
,
392 "Not expected version for referral entry 0 got %d expected 4",
393 resp3
.referral_entries
[0].version
));
394 torture_assert_int_equal(tctx
, memcmp(resp3
.referral_entries
[0].referral
.v3
.service_site_guid
.value
, zeros
, 16), 0,
395 talloc_asprintf(tctx
,
396 "Service_site_guid is not NULL as expected"));
399 * We do not support fallback indication for the moment
401 torture_assert_int_equal(tctx
, resp3
.header_flags
,
402 DFS_HEADER_FLAG_STORAGE_SVR
| DFS_HEADER_FLAG_TARGET_BCK
,
403 "Header flag different it's not a referral for a storage with fallback");
405 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v4
.entry_flags
,
406 DFS_FLAG_REFERRAL_FIRST_TARGET_SET
,
407 talloc_asprintf(tctx
,
408 "Wrong entry flag expected to have a non domain response and got %d",
409 resp3
.referral_entries
[0].referral
.v4
.entry_flags
));
413 static bool test_unknowndomain(struct torture_context
*tctx
,
414 struct smbcli_state
*cli
)
416 struct dfs_GetDFSReferral r
, r2
;
417 struct dfs_referral_resp resp
, resp2
;
419 r
.in
.req
.max_referral_level
= 3;
420 r
.in
.req
.servername
= "";
423 torture_assert_ntstatus_ok(tctx
,
424 dfs_cli_do_call(cli
->tree
, &r
),
425 "Get Domain referral failed");
427 r2
.in
.req
.max_referral_level
= 3;
428 r2
.in
.req
.servername
= "foobar.none.net";
429 r2
.out
.resp
= &resp2
;
431 torture_assert_ntstatus_equal(tctx
,
432 dfs_cli_do_call(cli
->tree
, &r2
),
433 NT_STATUS_INVALID_PARAMETER
,
434 "Get DC Domain didn't return exptected error code");
439 static bool test_getsysvolplusreferral(struct torture_context
*tctx
,
440 struct smbcli_state
*cli
)
443 struct dfs_GetDFSReferral r
, r2
, r3
;
444 struct dfs_referral_resp resp
, resp2
, resp3
;
446 r
.in
.req
.max_referral_level
= 3;
447 r
.in
.req
.servername
= "";
450 torture_assert_ntstatus_ok(tctx
,
451 dfs_cli_do_call(cli
->tree
, &r
),
452 "Get Domain referral failed");
454 r2
.in
.req
.max_referral_level
= 3;
455 r2
.in
.req
.servername
= resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
456 r2
.out
.resp
= &resp2
;
458 torture_assert_ntstatus_ok(tctx
,
459 dfs_cli_do_call(cli
->tree
, &r2
),
460 "Get DC Domain referral failed");
462 str
= resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
463 r3
.in
.req
.max_referral_level
= 3;
464 r3
.in
.req
.servername
= talloc_asprintf(tctx
, "%s\\sysvol\\foo", str
);
465 r3
.out
.resp
= &resp3
;
467 torture_assert_ntstatus_equal(tctx
,
468 dfs_cli_do_call(cli
->tree
, &r3
),
470 "Bad behavior with subtree sysvol referral");
475 static bool test_low_referral_level(struct torture_context
*tctx
,
476 struct smbcli_state
*cli
)
478 struct dfs_GetDFSReferral r
;
479 struct dfs_referral_resp resp
;
481 r
.in
.req
.max_referral_level
= 2;
482 r
.in
.req
.servername
= "";
485 torture_assert_ntstatus_equal(tctx
,
486 dfs_cli_do_call(cli
->tree
, &r
),
487 NT_STATUS_UNSUCCESSFUL
,
488 "Unexpected STATUS for invalid deferral retquest");
493 NTSTATUS
torture_dfs_init(void)
495 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "dfs");
496 struct torture_suite
*suite_basic
= torture_suite_create(suite
, "domain");
498 torture_suite_add_suite(suite
, suite_basic
);
500 torture_suite_add_1smb_test(suite_basic
, "domain referral",
501 test_getdomainreferral
);
502 torture_suite_add_1smb_test(suite_basic
, "dc referral",
504 torture_suite_add_1smb_test(suite_basic
, "dc referral netbios",
505 test_getdcreferral_netbios
);
507 torture_suite_add_1smb_test(suite_basic
, "sysvol referral",
508 test_getsysvolreferral
);
510 /* Non standard case */
512 torture_suite_add_1smb_test(suite_basic
, "dc referral on unknown domain",
514 torture_suite_add_1smb_test(suite_basic
, "sysvol with subtree referral",
515 test_getsysvolplusreferral
);
516 torture_suite_add_1smb_test(suite_basic
, "referral with a level 2",
517 test_low_referral_level
);
520 * test with invalid level
524 suite
->description
= talloc_strdup(suite
, "DFS referrals calls");
526 torture_register_suite(suite
);