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 resp3
.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 * Due to strange behavior with XP and level 4
385 * we are obliged to degrade to level 3 ...
387 r3
.in
.req
.max_referral_level
= 4;
389 torture_assert_ntstatus_ok(tctx
,
390 dfs_cli_do_call(cli
->tree
, &r3
),
391 "Get sysvol Domain referral failed");
393 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 4,
394 talloc_asprintf(tctx
,
395 "Not expected version for referral entry 0 got %d expected 4",
396 resp3
.referral_entries
[0].version
));
397 torture_assert_int_equal(tctx
, memcmp(resp3
.referral_entries
[0].referral
.v3
.service_site_guid
.value
, zeros
, 16), 0,
398 talloc_asprintf(tctx
,
399 "Service_site_guid is not NULL as expected"));
401 /* Shouldn't be needed anymore*/
402 r3
.in
.req
.max_referral_level
= 4;
404 torture_assert_ntstatus_ok(tctx
,
405 dfs_cli_do_call(cli
->tree
, &r3
),
406 "Get sysvol Domain referral failed");
408 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
409 talloc_asprintf(tctx
,
410 "Not expected version for referral entry 0 got %d expected 3 in degraded mode",
411 resp3
.referral_entries
[0].version
));
413 * We do not support fallback indication for the moment
415 torture_assert_int_equal(tctx
, resp3
.header_flags
,
416 DFS_HEADER_FLAG_STORAGE_SVR
| DFS_HEADER_FLAG_TARGET_BCK
,
417 "Header flag different it's not a referral for a storage with fallback");
418 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v4
.entry_flags
,
419 DFS_FLAG_REFERRAL_FIRST_TARGET_SET
,
420 talloc_asprintf(tctx
,
421 "Wrong entry flag expected to have a non domain response and got %d",
422 resp3
.referral_entries
[0].referral
.v4
.entry_flags
));
427 static bool test_unknowndomain(struct torture_context
*tctx
,
428 struct smbcli_state
*cli
)
430 struct dfs_GetDFSReferral r
, r2
;
431 struct dfs_referral_resp resp
, resp2
;
433 r
.in
.req
.max_referral_level
= 3;
434 r
.in
.req
.servername
= "";
437 torture_assert_ntstatus_ok(tctx
,
438 dfs_cli_do_call(cli
->tree
, &r
),
439 "Get Domain referral failed");
441 r2
.in
.req
.max_referral_level
= 3;
442 r2
.in
.req
.servername
= "foobar.none.net";
443 r2
.out
.resp
= &resp2
;
445 torture_assert_ntstatus_equal(tctx
,
446 dfs_cli_do_call(cli
->tree
, &r2
),
447 NT_STATUS_INVALID_PARAMETER
,
448 "Get DC Domain didn't return exptected error code");
453 static bool test_getsysvolplusreferral(struct torture_context
*tctx
,
454 struct smbcli_state
*cli
)
457 struct dfs_GetDFSReferral r
, r2
, r3
;
458 struct dfs_referral_resp resp
, resp2
, resp3
;
460 r
.in
.req
.max_referral_level
= 3;
461 r
.in
.req
.servername
= "";
464 torture_assert_ntstatus_ok(tctx
,
465 dfs_cli_do_call(cli
->tree
, &r
),
466 "Get Domain referral failed");
468 r2
.in
.req
.max_referral_level
= 3;
469 r2
.in
.req
.servername
= resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
470 r2
.out
.resp
= &resp2
;
472 torture_assert_ntstatus_ok(tctx
,
473 dfs_cli_do_call(cli
->tree
, &r2
),
474 "Get DC Domain referral failed");
476 str
= resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
477 r3
.in
.req
.max_referral_level
= 3;
478 r3
.in
.req
.servername
= talloc_asprintf(tctx
, "%s\\sysvol\\foo", str
);
479 r3
.out
.resp
= &resp3
;
481 torture_assert_ntstatus_equal(tctx
,
482 dfs_cli_do_call(cli
->tree
, &r3
),
484 "Bad behavior with subtree sysvol referral");
489 static bool test_low_referral_level(struct torture_context
*tctx
,
490 struct smbcli_state
*cli
)
492 struct dfs_GetDFSReferral r
;
493 struct dfs_referral_resp resp
;
495 r
.in
.req
.max_referral_level
= 2;
496 r
.in
.req
.servername
= "";
499 torture_assert_ntstatus_equal(tctx
,
500 dfs_cli_do_call(cli
->tree
, &r
),
501 NT_STATUS_UNSUCCESSFUL
,
502 "Unexpected STATUS for invalid deferral retquest");
507 NTSTATUS
torture_dfs_init(void)
509 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "dfs");
510 struct torture_suite
*suite_basic
= torture_suite_create(suite
, "domain");
512 torture_suite_add_suite(suite
, suite_basic
);
514 torture_suite_add_1smb_test(suite_basic
, "domain referral",
515 test_getdomainreferral
);
516 torture_suite_add_1smb_test(suite_basic
, "dc referral",
518 torture_suite_add_1smb_test(suite_basic
, "dc referral netbios",
519 test_getdcreferral_netbios
);
521 torture_suite_add_1smb_test(suite_basic
, "sysvol referral",
522 test_getsysvolreferral
);
524 /* Non standard case */
526 torture_suite_add_1smb_test(suite_basic
, "dc referral on unknown domain",
528 torture_suite_add_1smb_test(suite_basic
, "sysvol with subtree referral",
529 test_getsysvolplusreferral
);
530 torture_suite_add_1smb_test(suite_basic
, "referral with a level 2",
531 test_low_referral_level
);
534 * test with invalid level
538 suite
->description
= talloc_strdup(suite
, "DFS referrals calls");
540 torture_register_suite(suite
);