s4 torture: Add tests for dfs referrals handling in SMB/trans2 requests
[Samba.git] / source4 / torture / dfs / domaindfs.c
blob18c84396d389a2dcefd15acd015e70f7d0dda4a5
1 /*
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/>.
20 #include "includes.h"
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 = "";
38 r.out.resp = &resp;
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,
51 talloc_asprintf(tctx,
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,
55 DFS_SERVER_NON_ROOT,
56 talloc_asprintf(tctx,
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,
61 talloc_asprintf(tctx,
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");
68 return true;
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;
76 const char* str;
78 r.in.req.max_referral_level = 3;
79 r.in.req.servername = "";
80 r.out.resp = &resp;
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;
93 r2.out.resp = &resp2;
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,
111 DFS_SERVER_NON_ROOT,
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,
153 DFS_SERVER_NON_ROOT,
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");
170 return true;
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;
178 const char* str;
180 r.in.req.max_referral_level = 3;
181 r.in.req.servername = "";
182 r.out.resp = &resp;
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,
213 DFS_SERVER_NON_ROOT,
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,
258 DFS_SERVER_NON_ROOT,
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");
278 return true;
281 static bool test_getsysvolreferral(struct torture_context *tctx,
282 struct smbcli_state *cli)
284 const char* str;
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 = "";
290 r.out.resp = &resp;
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,
328 DFS_SERVER_NON_ROOT,
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));
356 #if 0
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");
363 #endif
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));
369 return true;
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 = "";
380 r.out.resp = &resp;
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");
395 return true;
398 static bool test_getsysvolplusreferral(struct torture_context *tctx,
399 struct smbcli_state *cli)
401 const char* str;
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 = "";
407 r.out.resp = &resp;
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),
428 NT_STATUS_NOT_FOUND,
429 "Bad behavior with subtree sysvol referral");
431 return true;
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 = "";
442 r.out.resp = &resp;
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");
449 return true;
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",
462 test_getdcreferral);
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",
472 test_unknowndomain);
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
480 * test with netbios
483 suite->description = talloc_strdup(suite, "DFS referrals calls");
485 torture_register_suite(suite);
487 return NT_STATUS_OK;