Add the ability to parse out the port to SMBC_parse_path().
[Samba/vl.git] / source4 / torture / dfs / domaindfs.c
blob4981d0f11ee17f3265226a4a6a715e9a04a3ca65
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[1].version, 3,
51 talloc_asprintf(tctx,
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,
55 talloc_asprintf(tctx,
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,
59 DFS_SERVER_NON_ROOT,
60 talloc_asprintf(tctx,
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,
65 talloc_asprintf(tctx,
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 \\");
76 return true;
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;
84 const char* str;
85 const char* str2;
87 r.in.req.max_referral_level = 3;
88 r.in.req.servername = "";
89 r.out.resp = &resp;
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,
120 DFS_SERVER_NON_ROOT,
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] == '\\') {
140 str2++;
142 torture_assert_int_equal(tctx, strlen(str) >0, 1 ,"Length of domain too short");
143 str++;
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,
176 DFS_SERVER_NON_ROOT,
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");
193 return true;
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;
201 const char* str;
203 r.in.req.max_referral_level = 3;
204 r.in.req.servername = "";
205 r.out.resp = &resp;
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,
236 DFS_SERVER_NON_ROOT,
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,
281 DFS_SERVER_NON_ROOT,
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");
301 return true;
304 static bool test_getsysvolreferral(struct torture_context *tctx,
305 struct smbcli_state *cli)
307 const char* str;
308 struct dfs_GetDFSReferral r, r2, r3;
309 struct dfs_referral_resp resp, resp2, resp3;
310 uint8_t zeros[16];
312 memset(zeros, 0, sizeof(zeros));
314 r.in.req.max_referral_level = 3;
315 r.in.req.servername = "";
316 r.out.resp = &resp;
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,
354 DFS_SERVER_NON_ROOT,
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,
368 str+1) != NULL, 1,
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,
372 str+1));
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,
378 str+1) != NULL, 1,
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,
382 str+1));
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"));
400 #if 0
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));
423 #endif
424 return true;
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 = "";
435 r.out.resp = &resp;
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");
450 return true;
453 static bool test_getsysvolplusreferral(struct torture_context *tctx,
454 struct smbcli_state *cli)
456 const char* str;
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 = "";
462 r.out.resp = &resp;
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),
483 NT_STATUS_NOT_FOUND,
484 "Bad behavior with subtree sysvol referral");
486 return true;
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 = "";
497 r.out.resp = &resp;
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");
504 return true;
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",
517 test_getdcreferral);
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",
527 test_unknowndomain);
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
535 * test with netbios
538 suite->description = talloc_strdup(suite, "DFS referrals calls");
540 torture_register_suite(suite);
542 return NT_STATUS_OK;