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
;
311 r
.in
.req
.max_referral_level
= 3;
312 r
.in
.req
.servername
= "";
315 torture_assert_ntstatus_ok(tctx
,
316 dfs_cli_do_call(cli
->tree
, &r
),
317 "Get Domain referral failed");
319 str
= resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
320 if( strchr(str
, '.') == NULL
) {
321 str
= resp
.referral_entries
[1].referral
.v3
.referrals
.r2
.special_name
;
324 r2
.in
.req
.max_referral_level
= 3;
325 r2
.in
.req
.servername
= str
;
326 r2
.out
.resp
= &resp2
;
328 torture_assert_ntstatus_ok(tctx
,
329 dfs_cli_do_call(cli
->tree
, &r2
),
330 "Get DC Domain referral failed");
332 r3
.in
.req
.max_referral_level
= 3;
333 r3
.in
.req
.servername
= talloc_asprintf(tctx
, "%s\\sysvol", str
);
334 r3
.out
.resp
= &resp3
;
336 torture_assert_ntstatus_ok(tctx
,
337 dfs_cli_do_call(cli
->tree
, &r3
),
338 "Get sysvol Domain referral failed");
340 torture_assert_int_equal(tctx
, resp3
.path_consumed
, 2*strlen(r3
.in
.req
.servername
),
341 "Path consumed not equal to length of the request");
342 torture_assert_int_equal(tctx
, resp3
.nb_referrals
!= 0, 1,
343 "We do not receive at least 1 referral");
344 torture_assert_int_equal(tctx
, resp3
.header_flags
, DFS_HEADER_FLAG_STORAGE_SVR
,
345 "Header flag different it's not a referral for a storage");
346 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
347 talloc_asprintf(tctx
,
348 "Not expected version for referral entry 0 got %d expected 3",
349 resp3
.referral_entries
[0].version
));
350 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.server_type
,
352 talloc_asprintf(tctx
,
353 "Wrong server type, expected non root server and got %d",
354 resp3
.referral_entries
[0].referral
.v3
.server_type
));
355 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.entry_flags
,
357 talloc_asprintf(tctx
,
358 "Wrong entry flag expected to have a non domain response and got %d",
359 resp3
.referral_entries
[0].referral
.v3
.entry_flags
));
360 torture_assert_int_equal(tctx
, strlen(
361 resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.DFS_path
) > 0,
363 "Length of domain is 0 or less");
364 torture_assert_int_equal(tctx
, strstr(resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.DFS_path
,
366 talloc_asprintf(tctx
,
367 "Wrong DFS_path %s unable to find substring %s in it",
368 resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.DFS_path
,
370 torture_assert_int_equal(tctx
, strlen(
371 resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.netw_address
) > 0,
373 "Length of first referral is less than 0");
374 torture_assert_int_equal(tctx
, strstr(resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.netw_address
,
376 talloc_asprintf(tctx
,
377 "Wrong DFS_path %s unable to find substring %s in it",
378 resp3
.referral_entries
[0].referral
.v3
.referrals
.r1
.netw_address
,
381 * Due to strange behavior with XP and level 4
382 * we are obliged to degrade to level 3 ...
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(tctx
, all_zero(resp3
.referral_entries
[0].referral
.v3
.service_site_guid
.value
, 16),
395 talloc_asprintf(tctx
,
396 "Service_site_guid is not NULL as expected"));
398 /* Shouldn't be needed anymore*/
399 r3
.in
.req
.max_referral_level
= 4;
401 torture_assert_ntstatus_ok(tctx
,
402 dfs_cli_do_call(cli
->tree
, &r3
),
403 "Get sysvol Domain referral failed");
405 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
406 talloc_asprintf(tctx
,
407 "Not expected version for referral entry 0 got %d expected 3 in degraded mode",
408 resp3
.referral_entries
[0].version
));
410 * We do not support fallback indication for the moment
412 torture_assert_int_equal(tctx
, resp3
.header_flags
,
413 DFS_HEADER_FLAG_STORAGE_SVR
| DFS_HEADER_FLAG_TARGET_BCK
,
414 "Header flag different it's not a referral for a storage with fallback");
415 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v4
.entry_flags
,
416 DFS_FLAG_REFERRAL_FIRST_TARGET_SET
,
417 talloc_asprintf(tctx
,
418 "Wrong entry flag expected to have a non domain response and got %d",
419 resp3
.referral_entries
[0].referral
.v4
.entry_flags
));
424 static bool test_unknowndomain(struct torture_context
*tctx
,
425 struct smbcli_state
*cli
)
427 struct dfs_GetDFSReferral r
, r2
;
428 struct dfs_referral_resp resp
, resp2
;
430 r
.in
.req
.max_referral_level
= 3;
431 r
.in
.req
.servername
= "";
434 torture_assert_ntstatus_ok(tctx
,
435 dfs_cli_do_call(cli
->tree
, &r
),
436 "Get Domain referral failed");
438 r2
.in
.req
.max_referral_level
= 3;
439 r2
.in
.req
.servername
= "foobar.none.net";
440 r2
.out
.resp
= &resp2
;
442 torture_assert_ntstatus_equal(tctx
,
443 dfs_cli_do_call(cli
->tree
, &r2
),
444 NT_STATUS_INVALID_PARAMETER
,
445 "Get DC Domain didn't return expected error code");
450 static bool test_getsysvolplusreferral(struct torture_context
*tctx
,
451 struct smbcli_state
*cli
)
454 struct dfs_GetDFSReferral r
, r2
, r3
;
455 struct dfs_referral_resp resp
, resp2
, resp3
;
457 r
.in
.req
.max_referral_level
= 3;
458 r
.in
.req
.servername
= "";
461 torture_assert_ntstatus_ok(tctx
,
462 dfs_cli_do_call(cli
->tree
, &r
),
463 "Get Domain referral failed");
465 r2
.in
.req
.max_referral_level
= 3;
466 r2
.in
.req
.servername
= resp
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
467 r2
.out
.resp
= &resp2
;
469 torture_assert_ntstatus_ok(tctx
,
470 dfs_cli_do_call(cli
->tree
, &r2
),
471 "Get DC Domain referral failed");
473 str
= resp2
.referral_entries
[0].referral
.v3
.referrals
.r2
.special_name
;
474 r3
.in
.req
.max_referral_level
= 3;
475 r3
.in
.req
.servername
= talloc_asprintf(tctx
, "%s\\sysvol\\foo", str
);
476 r3
.out
.resp
= &resp3
;
478 torture_assert_ntstatus_equal(tctx
,
479 dfs_cli_do_call(cli
->tree
, &r3
),
481 "Bad behavior with subtree sysvol referral");
486 static bool test_low_referral_level(struct torture_context
*tctx
,
487 struct smbcli_state
*cli
)
489 struct dfs_GetDFSReferral r
;
490 struct dfs_referral_resp resp
;
492 r
.in
.req
.max_referral_level
= 2;
493 r
.in
.req
.servername
= "";
496 torture_assert_ntstatus_equal(tctx
,
497 dfs_cli_do_call(cli
->tree
, &r
),
498 NT_STATUS_UNSUCCESSFUL
,
499 "Unexpected STATUS for invalid referral request");
504 NTSTATUS
torture_dfs_init(TALLOC_CTX
*ctx
)
506 struct torture_suite
*suite
= torture_suite_create(ctx
, "dfs");
507 struct torture_suite
*suite_basic
= torture_suite_create(suite
, "domain");
509 torture_suite_add_suite(suite
, suite_basic
);
511 torture_suite_add_1smb_test(suite_basic
, "domain referral",
512 test_getdomainreferral
);
513 torture_suite_add_1smb_test(suite_basic
, "dc referral",
515 torture_suite_add_1smb_test(suite_basic
, "dc referral netbios",
516 test_getdcreferral_netbios
);
518 torture_suite_add_1smb_test(suite_basic
, "sysvol referral",
519 test_getsysvolreferral
);
521 /* Non standard case */
523 torture_suite_add_1smb_test(suite_basic
, "dc referral on unknown domain",
525 torture_suite_add_1smb_test(suite_basic
, "sysvol with subtree referral",
526 test_getsysvolplusreferral
);
527 torture_suite_add_1smb_test(suite_basic
, "referral with a level 2",
528 test_low_referral_level
);
531 * test with invalid level
535 suite
->description
= talloc_strdup(suite
, "DFS referrals calls");
537 torture_register_suite(ctx
, suite
);