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
[0].version
, 3,
52 "Not expected version for referral entry 0 got %d expected 3",
53 resp
.referral_entries
[0].version
));
54 torture_assert_int_equal(tctx
, resp
.referral_entries
[0].referral
.v3
.data
.server_type
,
57 "Wrong server type, expected non root server and got %d",
58 resp
.referral_entries
[0].referral
.v3
.data
.server_type
));
59 torture_assert_int_equal(tctx
, resp
.referral_entries
[0].referral
.v3
.data
.entry_flags
,
60 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
62 "Wrong entry flag expected to have a domain response and got %d",
63 resp
.referral_entries
[0].referral
.v3
.data
.entry_flags
));
64 torture_assert_int_equal(tctx
, strlen(
65 resp
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
) > 0,
67 "Length of domain is 0 or less");
71 static bool test_getdcreferral(struct torture_context
*tctx
,
72 struct smbcli_state
*cli
)
74 struct dfs_GetDFSReferral r
, r2
, r3
;
75 struct dfs_referral_resp resp
, resp2
, resp3
;
78 r
.in
.req
.max_referral_level
= 3;
79 r
.in
.req
.servername
= "";
82 torture_assert_ntstatus_ok(tctx
,
83 dfs_cli_do_call(cli
->tree
, &r
),
84 "Get Domain referral failed");
86 str
= resp
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
;
87 if( strchr(str
, '.') == NULL
) {
88 str
= resp
.referral_entries
[1].referral
.v3
.data
.referrals
.r2
.special_name
;
91 r2
.in
.req
.max_referral_level
= 3;
92 r2
.in
.req
.servername
= str
;
95 torture_assert_ntstatus_ok(tctx
,
96 dfs_cli_do_call(cli
->tree
, &r2
),
97 "Get DC Domain referral failed");
100 torture_assert_int_equal(tctx
, resp2
.path_consumed
, 0,
101 "Path consumed not equal to 0");
102 torture_assert_int_equal(tctx
, resp2
.nb_referrals
, 1,
103 "We do not received only 1 referral");
104 torture_assert_int_equal(tctx
, resp2
.header_flags
, 0,
105 "Header flag different it's not a referral server");
106 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].version
, 3,
107 talloc_asprintf(tctx
,
108 "Not expected version for referral entry 0 got %d expected 3",
109 resp2
.referral_entries
[0].version
));
110 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.data
.server_type
,
112 talloc_asprintf(tctx
,
113 "Wrong server type, expected non root server and got %d",
114 resp2
.referral_entries
[0].referral
.v3
.data
.server_type
));
115 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.data
.entry_flags
,
116 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
117 talloc_asprintf(tctx
,
118 "Wrong entry flag expected to have a domain response and got %d",
119 resp2
.referral_entries
[0].referral
.v3
.data
.entry_flags
));
120 torture_assert_int_equal(tctx
, strlen(
121 resp2
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
) > 0,
123 "Length of domain is 0 or less");
124 torture_assert_int_equal(tctx
, strlen(
125 resp2
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.expanded_names
[0]) > 0,
127 "Length of first dc is less than 0");
129 r3
.in
.req
.max_referral_level
= 3;
131 * Windows 7 and at least windows 2008 server sends domain.fqdn instead of \domain.fqdn
132 * (as it is specified in the spec)
133 * Let's check that we are able to support it too
135 r3
.in
.req
.servername
= str
;
136 r3
.out
.resp
= &resp3
;
138 torture_assert_ntstatus_ok(tctx
,
139 dfs_cli_do_call(cli
->tree
, &r3
),
140 "Get DC Domain referral failed");
142 torture_assert_int_equal(tctx
, resp3
.path_consumed
, 0,
143 "Path consumed not equal to 0");
144 torture_assert_int_equal(tctx
, resp3
.nb_referrals
, 1,
145 "We do not received only 1 referral");
146 torture_assert_int_equal(tctx
, resp3
.header_flags
, 0,
147 "Header flag different it's not a referral server");
148 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
149 talloc_asprintf(tctx
,
150 "Not expected version for referral entry 0 got %d expected 3",
151 resp3
.referral_entries
[0].version
));
152 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.data
.server_type
,
154 talloc_asprintf(tctx
,
155 "Wrong server type, expected non root server and got %d",
156 resp3
.referral_entries
[0].referral
.v3
.data
.server_type
));
157 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.data
.entry_flags
,
158 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
159 talloc_asprintf(tctx
,
160 "Wrong entry flag expected to have a domain response and got %d",
161 resp3
.referral_entries
[0].referral
.v3
.data
.entry_flags
));
162 torture_assert_int_equal(tctx
, strlen(
163 resp3
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
) > 0,
165 "Length of domain is 0 or less");
166 torture_assert_int_equal(tctx
, strlen(
167 resp3
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.expanded_names
[0]) > 0,
169 "Length of first dc is less than 0");
173 static bool test_getdcreferral_netbios(struct torture_context
*tctx
,
174 struct smbcli_state
*cli
)
176 struct dfs_GetDFSReferral r
, r2
, r3
;
177 struct dfs_referral_resp resp
, resp2
, resp3
;
180 r
.in
.req
.max_referral_level
= 3;
181 r
.in
.req
.servername
= "";
184 torture_assert_ntstatus_ok(tctx
,
185 dfs_cli_do_call(cli
->tree
, &r
),
186 "Get Domain referral failed");
188 r2
.in
.req
.max_referral_level
= 3;
190 str
= resp
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
;
191 if( strchr(str
, '.') != NULL
) {
192 str
= resp
.referral_entries
[1].referral
.v3
.data
.referrals
.r2
.special_name
;
195 r2
.in
.req
.servername
= str
;
196 r2
.out
.resp
= &resp2
;
198 torture_assert_ntstatus_ok(tctx
,
199 dfs_cli_do_call(cli
->tree
, &r2
),
200 "Get DC Domain referral failed");
202 torture_assert_int_equal(tctx
, resp2
.path_consumed
, 0,
203 "Path consumed not equal to 0");
204 torture_assert_int_equal(tctx
, resp2
.nb_referrals
, 1,
205 "We do not received only 1 referral");
206 torture_assert_int_equal(tctx
, resp2
.header_flags
, 0,
207 "Header flag different it's not a referral server");
208 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].version
, 3,
209 talloc_asprintf(tctx
,
210 "Not expected version for referral entry 0 got %d expected 3",
211 resp2
.referral_entries
[0].version
));
212 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.data
.server_type
,
214 talloc_asprintf(tctx
,
215 "Wrong server type, expected non root server and got %d",
216 resp2
.referral_entries
[0].referral
.v3
.data
.server_type
));
217 torture_assert_int_equal(tctx
, resp2
.referral_entries
[0].referral
.v3
.data
.entry_flags
,
218 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
219 talloc_asprintf(tctx
,
220 "Wrong entry flag expected to have a domain response and got %d",
221 resp2
.referral_entries
[0].referral
.v3
.data
.entry_flags
));
222 torture_assert_int_equal(tctx
, strlen(
223 resp2
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
) > 0,
225 "Length of domain is 0 or less");
226 torture_assert_int_equal(tctx
, strlen(
227 resp2
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.expanded_names
[0]) > 0,
229 "Length of first dc is less than 0");
230 torture_assert(tctx
, strchr(
231 resp2
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.expanded_names
[0],'.') == NULL
,
232 "referral contains dots it's not a netbios name");
234 r3
.in
.req
.max_referral_level
= 3;
236 * Windows 7 and at least windows 2008 server sends domain.fqdn instead of \domain.fqdn
237 * (as it is specified in the spec)
238 * Let's check that we are able to support it too
240 r3
.in
.req
.servername
= str
+ 1;
241 r3
.out
.resp
= &resp3
;
243 torture_assert_ntstatus_ok(tctx
,
244 dfs_cli_do_call(cli
->tree
, &r3
),
245 "Get DC Domain referral failed");
247 torture_assert_int_equal(tctx
, resp3
.path_consumed
, 0,
248 "Path consumed not equal to 0");
249 torture_assert_int_equal(tctx
, resp3
.nb_referrals
, 1,
250 "We do not received only 1 referral");
251 torture_assert_int_equal(tctx
, resp3
.header_flags
, 0,
252 "Header flag different it's not a referral server");
253 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
254 talloc_asprintf(tctx
,
255 "Not expected version for referral entry 0 got %d expected 3",
256 resp3
.referral_entries
[0].version
));
257 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.data
.server_type
,
259 talloc_asprintf(tctx
,
260 "Wrong server type, expected non root server and got %d",
261 resp3
.referral_entries
[0].referral
.v3
.data
.server_type
));
262 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.data
.entry_flags
,
263 DFS_FLAG_REFERRAL_DOMAIN_RESP
,
264 talloc_asprintf(tctx
,
265 "Wrong entry flag expected to have a domain response and got %d",
266 resp3
.referral_entries
[0].referral
.v3
.data
.entry_flags
));
267 torture_assert_int_equal(tctx
, strlen(
268 resp3
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
) > 0,
270 "Length of domain is 0 or less");
271 torture_assert_int_equal(tctx
, strlen(
272 resp3
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.expanded_names
[0]) > 0,
274 "Length of first dc is less than 0");
275 torture_assert(tctx
, strchr(
276 resp3
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.expanded_names
[0],'.') == NULL
,
277 "referral contains dots it's not a netbios name");
281 static bool test_getsysvolreferral(struct torture_context
*tctx
,
282 struct smbcli_state
*cli
)
285 struct dfs_GetDFSReferral r
, r2
, r3
;
286 struct dfs_referral_resp resp
, resp2
, resp3
;
288 r
.in
.req
.max_referral_level
= 3;
289 r
.in
.req
.servername
= "";
292 torture_assert_ntstatus_ok(tctx
,
293 dfs_cli_do_call(cli
->tree
, &r
),
294 "Get Domain referral failed");
296 str
= resp
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
;
297 if( strchr(str
, '.') == NULL
) {
298 str
= resp
.referral_entries
[1].referral
.v3
.data
.referrals
.r2
.special_name
;
301 r2
.in
.req
.max_referral_level
= 3;
302 r2
.in
.req
.servername
= str
;
303 r2
.out
.resp
= &resp2
;
305 torture_assert_ntstatus_ok(tctx
,
306 dfs_cli_do_call(cli
->tree
, &r2
),
307 "Get DC Domain referral failed");
309 r3
.in
.req
.max_referral_level
= 3;
310 r3
.in
.req
.servername
= talloc_asprintf(tctx
, "%s\\sysvol", str
);
311 r3
.out
.resp
= &resp3
;
313 torture_assert_ntstatus_ok(tctx
,
314 dfs_cli_do_call(cli
->tree
, &r3
),
315 "Get sysvol Domain referral failed");
317 torture_assert_int_equal(tctx
, resp3
.path_consumed
, 2*strlen(r3
.in
.req
.servername
),
318 "Path consumed not equal to length of the request");
319 torture_assert_int_equal(tctx
, resp3
.nb_referrals
!= 0, 1,
320 "We do not receive at least 1 referral");
321 torture_assert_int_equal(tctx
, resp3
.header_flags
, DFS_HEADER_FLAG_STORAGE_SVR
,
322 "Header flag different it's not a referral for a storage");
323 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 3,
324 talloc_asprintf(tctx
,
325 "Not expected version for referral entry 0 got %d expected 3",
326 resp3
.referral_entries
[0].version
));
327 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.data
.server_type
,
329 talloc_asprintf(tctx
,
330 "Wrong server type, expected non root server and got %d",
331 resp3
.referral_entries
[0].referral
.v3
.data
.server_type
));
332 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v3
.data
.entry_flags
,
334 talloc_asprintf(tctx
,
335 "Wrong entry flag expected to have a non domain response and got %d",
336 resp3
.referral_entries
[0].referral
.v3
.data
.entry_flags
));
337 torture_assert_int_equal(tctx
, strlen(
338 resp3
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
) > 0,
340 "Length of domain is 0 or less");
341 torture_assert_int_equal(tctx
, strlen(
342 resp2
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.expanded_names
[0]) > 0,
344 "Length of first referral is less than 0");
346 r3
.in
.req
.max_referral_level
= 4;
348 torture_assert_ntstatus_ok(tctx
,
349 dfs_cli_do_call(cli
->tree
, &r3
),
350 "Get sysvol Domain referral failed");
352 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].version
, 4,
353 talloc_asprintf(tctx
,
354 "Not expected version for referral entry 0 got %d expected 4",
355 resp3
.referral_entries
[0].version
));
358 * We do not support fallback indication for the moment
360 torture_assert_int_equal(tctx
, resp3
.header_flags
,
361 DFS_HEADER_FLAG_STORAGE_SVR
| DFS_HEADER_FLAG_TARGET_BCK
,
362 "Header flag different it's not a referral for a storage with fallback");
364 torture_assert_int_equal(tctx
, resp3
.referral_entries
[0].referral
.v4
.entry_flags
,
365 DFS_FLAG_REFERRAL_FIRST_TARGET_SET
,
366 talloc_asprintf(tctx
,
367 "Wrong entry flag expected to have a non domain response and got %d",
368 resp3
.referral_entries
[0].referral
.v4
.entry_flags
));
372 static bool test_unknowndomain(struct torture_context
*tctx
,
373 struct smbcli_state
*cli
)
375 struct dfs_GetDFSReferral r
, r2
;
376 struct dfs_referral_resp resp
, resp2
;
378 r
.in
.req
.max_referral_level
= 3;
379 r
.in
.req
.servername
= "";
382 torture_assert_ntstatus_ok(tctx
,
383 dfs_cli_do_call(cli
->tree
, &r
),
384 "Get Domain referral failed");
386 r2
.in
.req
.max_referral_level
= 3;
387 r2
.in
.req
.servername
= "foobar.none.net";
388 r2
.out
.resp
= &resp2
;
390 torture_assert_ntstatus_equal(tctx
,
391 dfs_cli_do_call(cli
->tree
, &r2
),
392 NT_STATUS_INVALID_PARAMETER
,
393 "Get DC Domain didn't return exptected error code");
398 static bool test_getsysvolplusreferral(struct torture_context
*tctx
,
399 struct smbcli_state
*cli
)
402 struct dfs_GetDFSReferral r
, r2
, r3
;
403 struct dfs_referral_resp resp
, resp2
, resp3
;
405 r
.in
.req
.max_referral_level
= 3;
406 r
.in
.req
.servername
= "";
409 torture_assert_ntstatus_ok(tctx
,
410 dfs_cli_do_call(cli
->tree
, &r
),
411 "Get Domain referral failed");
413 r2
.in
.req
.max_referral_level
= 3;
414 r2
.in
.req
.servername
= resp
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
;
415 r2
.out
.resp
= &resp2
;
417 torture_assert_ntstatus_ok(tctx
,
418 dfs_cli_do_call(cli
->tree
, &r2
),
419 "Get DC Domain referral failed");
421 str
= resp2
.referral_entries
[0].referral
.v3
.data
.referrals
.r2
.special_name
;
422 r3
.in
.req
.max_referral_level
= 3;
423 r3
.in
.req
.servername
= talloc_asprintf(tctx
, "%s\\sysvol\\foo", str
);
424 r3
.out
.resp
= &resp3
;
426 torture_assert_ntstatus_equal(tctx
,
427 dfs_cli_do_call(cli
->tree
, &r3
),
429 "Bad behavior with subtree sysvol referral");
434 static bool test_low_referral_level(struct torture_context
*tctx
,
435 struct smbcli_state
*cli
)
437 struct dfs_GetDFSReferral r
;
438 struct dfs_referral_resp resp
;
440 r
.in
.req
.max_referral_level
= 2;
441 r
.in
.req
.servername
= "";
444 torture_assert_ntstatus_equal(tctx
,
445 dfs_cli_do_call(cli
->tree
, &r
),
446 NT_STATUS_UNSUCCESSFUL
,
447 "Unexpected STATUS for invalid deferral retquest");
452 NTSTATUS
torture_dfs_init(void)
454 struct torture_suite
*suite
= torture_suite_create(talloc_autofree_context(), "DFS");
455 struct torture_suite
*suite_basic
= torture_suite_create(suite
, "DOMAIN");
457 torture_suite_add_suite(suite
, suite_basic
);
459 torture_suite_add_1smb_test(suite_basic
, "domain referral",
460 test_getdomainreferral
);
461 torture_suite_add_1smb_test(suite_basic
, "dc referral",
463 torture_suite_add_1smb_test(suite_basic
, "dc referral netbios",
464 test_getdcreferral_netbios
);
466 torture_suite_add_1smb_test(suite_basic
, "sysvol referral",
467 test_getsysvolreferral
);
469 /* Non standard case */
471 torture_suite_add_1smb_test(suite_basic
, "dc referral on unknown domain",
473 torture_suite_add_1smb_test(suite_basic
, "sysvol with subtree referral",
474 test_getsysvolplusreferral
);
475 torture_suite_add_1smb_test(suite_basic
, "referral with a level 2",
476 test_low_referral_level
);
479 * test with invalid level
483 suite
->description
= talloc_strdup(suite
, "DFS referrals calls");
485 torture_register_suite(suite
);