2 Unix SMB/CIFS implementation.
3 chkpath individual test suite
4 Copyright (C) Andrew Tridgell 2003
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 "system/locale.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
26 #define BASEDIR "\\rawchkpath"
28 #define CHECK_STATUS(status, correct, dos_correct) do { \
29 if (!NT_STATUS_EQUAL(status, correct) && !NT_STATUS_EQUAL(status, dos_correct)) { \
30 printf("(%d) Incorrect status %s - should be %s\n", \
31 __LINE__, nt_errstr(status), nt_errstr(correct)); \
37 static NTSTATUS
single_search(struct smbcli_state
*cli
,
38 TALLOC_CTX
*mem_ctx
, const char *pattern
)
40 union smb_search_first io
;
43 io
.t2ffirst
.level
= RAW_SEARCH_TRANS2
;
44 io
.t2ffirst
.data_level
= RAW_SEARCH_DATA_STANDARD
;
45 io
.t2ffirst
.in
.search_attrib
= 0;
46 io
.t2ffirst
.in
.max_count
= 1;
47 io
.t2ffirst
.in
.flags
= FLAG_TRANS2_FIND_CLOSE
;
48 io
.t2ffirst
.in
.storage_type
= 0;
49 io
.t2ffirst
.in
.pattern
= pattern
;
51 status
= smb_raw_search_first(cli
->tree
, mem_ctx
,
57 static bool test_path_ex(struct smbcli_state
*cli
, struct torture_context
*tctx
,
58 const char *path
, const char *path_expected
,
59 NTSTATUS expected
, NTSTATUS dos_expected
)
62 union smb_fileinfo finfo
;
65 io
.chkpath
.in
.path
= path
;
66 status
= smb_raw_chkpath(cli
->tree
, &io
);
67 if (!NT_STATUS_EQUAL(status
, expected
) && !NT_STATUS_EQUAL(status
, dos_expected
)) {
68 printf("FAILED %-30s chkpath %s should be %s or %s\n",
69 path
, nt_errstr(status
), nt_errstr(expected
), nt_errstr(dos_expected
));
72 printf("%-30s chkpath correct (%s)\n", path
, nt_errstr(status
));
75 if (NT_STATUS_EQUAL(expected
, NT_STATUS_NOT_A_DIRECTORY
)) {
76 expected
= NT_STATUS_OK
;
80 finfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
81 finfo
.generic
.in
.file
.path
= path
;
82 status
= smb_raw_pathinfo(cli
->tree
, cli
, &finfo
);
83 if (!NT_STATUS_EQUAL(status
, expected
) && !NT_STATUS_EQUAL(status
, dos_expected
)) {
84 printf("FAILED: %-30s pathinfo %s should be %s or %s\n",
85 path
, nt_errstr(status
), nt_errstr(expected
), nt_errstr(dos_expected
));
89 if (!NT_STATUS_IS_OK(status
)) {
90 printf("%-30s chkpath correct (%s)\n", path
, nt_errstr(status
));
95 (!finfo
.name_info
.out
.fname
.s
||
96 strcmp(finfo
.name_info
.out
.fname
.s
, path_expected
) != 0)) {
97 if (tctx
&& torture_setting_bool(tctx
, "samba4", false)) {
98 printf("IGNORE: %-30s => %-20s should be %s\n",
99 path
, finfo
.name_info
.out
.fname
.s
, path_expected
);
102 printf("FAILED: %-30s => %-20s should be %s\n",
103 path
, finfo
.name_info
.out
.fname
.s
, path_expected
);
106 printf("%-30s => %-20s correct\n",
107 path
, finfo
.name_info
.out
.fname
.s
);
112 static bool test_path(struct smbcli_state
*cli
, const char *path
,
113 NTSTATUS expected
, NTSTATUS dos_expected
)
115 return test_path_ex(cli
, NULL
, path
, path
, expected
, dos_expected
);
118 static bool test_chkpath(struct smbcli_state
*cli
, struct torture_context
*tctx
)
120 union smb_chkpath io
;
126 io
.chkpath
.in
.path
= BASEDIR
;
128 status
= smb_raw_chkpath(cli
->tree
, &io
);
129 CHECK_STATUS(status
, NT_STATUS_OK
, NT_STATUS_OK
);
131 ret
&= test_path(cli
, BASEDIR
"\\nodir", NT_STATUS_OBJECT_NAME_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
133 fnum
= create_complex_file(cli
, tctx
, BASEDIR
"\\test.txt..");
135 printf("failed to open test.txt - %s\n", smbcli_errstr(cli
->tree
));
140 ret
&= test_path(cli
, BASEDIR
"\\test.txt..", NT_STATUS_NOT_A_DIRECTORY
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
142 if (!torture_set_file_attribute(cli
->tree
, BASEDIR
, FILE_ATTRIBUTE_HIDDEN
)) {
143 printf("failed to set basedir hidden\n");
148 ret
&= test_path_ex(cli
, tctx
, BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
149 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
) + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
150 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\\\") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
151 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\foo\\..") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
152 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\f\\o\\o\\..\\..\\..") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
153 ret
&= test_path_ex(cli
, tctx
, ((const char *)BASEDIR
"\\foo\\\\..\\\\") + 1, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
154 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\", BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
155 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\\\..\\"BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
156 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\\\\\", BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
157 ret
&= test_path_ex(cli
, tctx
, "\\\\\\\\"BASEDIR
"\\\\\\\\", BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
158 ret
&= test_path_ex(cli
, tctx
, "\\\\\\\\"BASEDIR
, BASEDIR
, NT_STATUS_OK
, NT_STATUS_OK
);
159 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\foo\\..\\test.txt..", BASEDIR
"\\test.txt..",
160 NT_STATUS_NOT_A_DIRECTORY
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
161 ret
&= test_path_ex(cli
, tctx
, "", "\\", NT_STATUS_OK
, NT_STATUS_OK
);
162 ret
&= test_path(cli
, ".", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
163 ret
&= test_path(cli
, ".\\", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
164 ret
&= test_path(cli
, "\\\\\\.\\", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
165 ret
&= test_path(cli
, ".\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
166 ret
&= test_path(cli
, "." BASEDIR
, NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
167 ret
&= test_path(cli
, BASEDIR
"\\.", NT_STATUS_OBJECT_NAME_INVALID
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
168 ret
&= test_path(cli
, BASEDIR
"\\.\\test.txt..", NT_STATUS_OBJECT_PATH_NOT_FOUND
, NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
169 ret
&= test_path(cli
, ".\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
170 ret
&= test_path(cli
, ".\\.\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
171 ret
&= test_path(cli
, ".\\.\\.aaaaa", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
172 ret
&= test_path(cli
, "\\.\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
173 ret
&= test_path(cli
, "\\.\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
174 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
176 /* Note that the two following paths are identical but
177 give different NT status returns for chkpth and findfirst. */
179 printf("Testing findfirst on %s\n", "\\.\\\\\\\\\\\\.");
180 status
= single_search(cli
, tctx
, "\\.\\\\\\\\\\\\.");
181 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRinvalidname
));
183 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
185 /* We expect this open to fail with the same error code as the chkpath below. */
186 printf("Testing Open on %s\n", "\\.\\\\\\\\\\\\.");
187 /* findfirst seems to fail with a different error. */
188 fnum1
= smbcli_nt_create_full(cli
->tree
, "\\.\\\\\\\\\\\\.",
189 0, SEC_RIGHTS_FILE_ALL
,
190 FILE_ATTRIBUTE_NORMAL
,
191 NTCREATEX_SHARE_ACCESS_DELETE
|
192 NTCREATEX_SHARE_ACCESS_READ
|
193 NTCREATEX_SHARE_ACCESS_WRITE
,
194 NTCREATEX_DISP_OVERWRITE_IF
,
196 status
= smbcli_nt_error(cli
->tree
);
197 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
200 ret
&= test_path(cli
, "\\.\\\\xxx", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
201 ret
&= test_path(cli
, "..\\..\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
202 ret
&= test_path(cli
, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
203 ret
&= test_path(cli
, "\\.\\\\\\\\\\\\xxx", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
204 ret
&= test_path(cli
, BASEDIR
"\\.\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
205 ret
&= test_path(cli
, BASEDIR
"\\.\\\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
206 ret
&= test_path(cli
, BASEDIR
"\\.\\nt", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
207 ret
&= test_path(cli
, BASEDIR
"\\.\\.\\nt", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
208 ret
&= test_path(cli
, BASEDIR
"\\nt", NT_STATUS_OK
, NT_STATUS_OK
);
209 ret
&= test_path(cli
, BASEDIR
".\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
210 ret
&= test_path(cli
, BASEDIR
"xx\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
211 ret
&= test_path(cli
, ".\\", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
212 ret
&= test_path(cli
, ".\\.", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
213 ret
&= test_path(cli
, ".\\.\\.\\.\\foo\\.\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
214 ret
&= test_path(cli
, BASEDIR
".\\.\\.\\.\\foo\\.\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
215 ret
&= test_path(cli
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
216 ret
&= test_path(cli
, BASEDIR
".", NT_STATUS_OBJECT_NAME_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
217 ret
&= test_path(cli
, "\\", NT_STATUS_OK
,NT_STATUS_OK
);
218 ret
&= test_path(cli
, "\\.", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
219 ret
&= test_path(cli
, "\\..\\", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
220 ret
&= test_path(cli
, "\\..", NT_STATUS_OBJECT_PATH_SYNTAX_BAD
,NT_STATUS_DOS(ERRDOS
,ERRinvalidpath
));
221 ret
&= test_path(cli
, BASEDIR
"\\.", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
222 ret
&= test_path_ex(cli
, tctx
, BASEDIR
"\\..", "\\", NT_STATUS_OK
,NT_STATUS_OK
);
223 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb600", NT_STATUS_OBJECT_NAME_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
224 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe", NT_STATUS_NOT_A_DIRECTORY
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
226 /* We expect this open to fail with the same error code as the chkpath below. */
227 printf("Testing Open on %s\n", BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
228 /* findfirst seems to fail with a different error. */
229 fnum1
= smbcli_nt_create_full(cli
->tree
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\",
230 0, SEC_RIGHTS_FILE_ALL
,
231 FILE_ATTRIBUTE_NORMAL
,
232 NTCREATEX_SHARE_ACCESS_DELETE
|
233 NTCREATEX_SHARE_ACCESS_READ
|
234 NTCREATEX_SHARE_ACCESS_WRITE
,
235 NTCREATEX_DISP_OVERWRITE_IF
,
237 status
= smbcli_nt_error(cli
->tree
);
238 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
240 printf("Testing findfirst on %s\n", BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
241 status
= single_search(cli
, tctx
, BASEDIR
".\\.\\.\\.\\foo\\..\\.\\");
242 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
244 /* We expect this open to fail with the same error code as the chkpath below. */
245 /* findfirst seems to fail with a different error. */
246 printf("Testing Open on %s\n", BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3");
247 fnum1
= smbcli_nt_create_full(cli
->tree
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3",
248 0, SEC_RIGHTS_FILE_ALL
,
249 FILE_ATTRIBUTE_NORMAL
,
250 NTCREATEX_SHARE_ACCESS_DELETE
|
251 NTCREATEX_SHARE_ACCESS_READ
|
252 NTCREATEX_SHARE_ACCESS_WRITE
,
253 NTCREATEX_DISP_OVERWRITE_IF
,
255 status
= smbcli_nt_error(cli
->tree
);
256 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
258 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
259 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe\\3\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
260 ret
&= test_path(cli
, BASEDIR
"\\nt\\3\\foo", NT_STATUS_OBJECT_PATH_NOT_FOUND
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
261 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\*\\vb6.exe\\3", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
262 ret
&= test_path(cli
, BASEDIR
"\\nt\\V S\\*\\*\\vb6.exe\\3", NT_STATUS_OBJECT_NAME_INVALID
,NT_STATUS_DOS(ERRDOS
,ERRbadpath
));
265 smbcli_close(cli
->tree
, fnum
);
269 static bool test_chkpath_names(struct smbcli_state
*cli
, struct torture_context
*tctx
)
271 union smb_chkpath io
;
272 union smb_fileinfo finfo
;
278 * we don't test characters >= 0x80 yet,
279 * as somehow our client libraries can't do that
281 for (i
=0x01; i
<= 0x7F; i
++) {
283 * it's important that we test the last character
284 * because of the error code with ':' 0x3A
285 * and servers without stream support
287 char *path
= talloc_asprintf(tctx
, "%s\\File0x%02X%c",
290 NTSTATUS expected_dos1
;
291 NTSTATUS expected_dos2
;
293 expected
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
294 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
295 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRbadfile
);
307 torture_setting_bool(tctx
, "samba3", false)) {
308 /* samba 3 handles '/' as '\\' */
311 expected
= NT_STATUS_OBJECT_NAME_INVALID
;
312 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
313 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRinvalidname
);
317 expected
= NT_STATUS_OBJECT_NAME_INVALID
;
318 expected_dos1
= NT_STATUS_DOS(ERRDOS
,ERRbadpath
);
319 expected_dos2
= NT_STATUS_DOS(ERRDOS
,ERRinvalidname
);
324 printf("Checking File0x%02X%c%s expected[%s|%s|%s]\n",
325 i
, isprint(i
)?(char)i
:' ',
326 isprint(i
)?"":"(not printable)",
328 nt_errstr(expected_dos1
),
329 nt_errstr(expected_dos2
));
331 io
.chkpath
.in
.path
= path
;
332 status
= smb_raw_chkpath(cli
->tree
, &io
);
333 CHECK_STATUS(status
, expected
, expected_dos1
);
336 finfo
.generic
.level
= RAW_FILEINFO_NAME_INFO
;
337 finfo
.generic
.in
.file
.path
= path
;
338 status
= smb_raw_pathinfo(cli
->tree
, cli
, &finfo
);
339 CHECK_STATUS(status
, expected
, expected_dos2
);
349 basic testing of chkpath calls
351 bool torture_raw_chkpath(struct torture_context
*torture
,
352 struct smbcli_state
*cli
)
357 if (!torture_setup_dir(cli
, BASEDIR
)) {
361 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt"))) {
362 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
366 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt\\V S"))) {
367 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
371 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli
->tree
, BASEDIR
"\\nt\\V S\\VB98"))) {
372 printf("Failed to create " BASEDIR
" - %s\n", smbcli_errstr(cli
->tree
));
376 fnum
= create_complex_file(cli
, torture
, BASEDIR
"\\nt\\V S\\VB98\\vb6.exe");
378 printf("failed to open \\nt\\V S\\VB98\\vb6.exe - %s\n", smbcli_errstr(cli
->tree
));
383 ret
&= test_chkpath(cli
, torture
);
384 ret
&= test_chkpath_names(cli
, torture
);
388 smb_raw_exit(cli
->session
);
389 smbcli_deltree(cli
->tree
, BASEDIR
);