Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB torture tester
4 : Copyright (C) Guenther Deschner 2010
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "system/dir.h"
22 : #include "torture/smbtorture.h"
23 : #include "auth/credentials/credentials.h"
24 : #include "lib/cmdline/cmdline.h"
25 : #include <libsmbclient.h>
26 : #include "torture/libsmbclient/proto.h"
27 : #include "lib/param/loadparm.h"
28 : #include "lib/param/param_global.h"
29 : #include "libcli/smb/smb_constants.h"
30 : #include "dynconfig.h"
31 : #include "lib/util/time.h"
32 :
33 : /* test string to compare with when debug_callback is called */
34 : #define TEST_STRING "smbc_setLogCallback test"
35 :
36 : /* Dummy log callback function */
37 4 : static void debug_callback(void *private_ptr, int level, const char *msg)
38 : {
39 4 : bool *found = private_ptr;
40 4 : if (strstr(msg, TEST_STRING) != NULL) {
41 4 : *found = true;
42 : }
43 4 : return;
44 : }
45 :
46 14 : static void auth_callback(const char *srv,
47 : const char *shr,
48 : char *wg, int wglen,
49 : char *un, int unlen,
50 : char *pw, int pwlen)
51 : {
52 0 : const char *workgroup =
53 14 : cli_credentials_get_domain(samba_cmdline_get_creds());
54 0 : const char *username =
55 14 : cli_credentials_get_username(samba_cmdline_get_creds());
56 0 : const char *password =
57 14 : cli_credentials_get_password(samba_cmdline_get_creds());
58 0 : ssize_t ret;
59 :
60 14 : if (workgroup != NULL) {
61 14 : ret = strlcpy(wg, workgroup, wglen);
62 14 : if (ret >= wglen) {
63 0 : abort();
64 : }
65 : }
66 :
67 14 : if (username != NULL) {
68 14 : ret = strlcpy(un, username, unlen);
69 14 : if (ret >= unlen) {
70 0 : abort();
71 : }
72 : }
73 :
74 14 : if (password != NULL) {
75 14 : ret = strlcpy(pw, password, pwlen);
76 14 : if (ret >= pwlen) {
77 0 : abort();
78 : }
79 : }
80 14 : };
81 :
82 42 : bool torture_libsmbclient_init_context(struct torture_context *tctx,
83 : SMBCCTX **ctx_p)
84 : {
85 0 : const char *workgroup =
86 42 : cli_credentials_get_domain(samba_cmdline_get_creds());
87 0 : const char *username =
88 42 : cli_credentials_get_username(samba_cmdline_get_creds());
89 0 : const char *client_proto =
90 42 : torture_setting_string(tctx, "clientprotocol", NULL);
91 42 : SMBCCTX *ctx = NULL;
92 42 : SMBCCTX *p = NULL;
93 42 : bool ok = true;
94 42 : int dbglevel = DEBUGLEVEL;
95 :
96 42 : ctx = smbc_new_context();
97 42 : torture_assert_not_null_goto(tctx,
98 : ctx,
99 : ok,
100 : out,
101 : "Failed to create new context");
102 :
103 42 : p = smbc_init_context(ctx);
104 42 : torture_assert_not_null_goto(tctx,
105 : p,
106 : ok,
107 : out,
108 : "Failed to initialize context");
109 :
110 42 : smbc_setDebug(ctx, dbglevel);
111 42 : smbc_setOptionDebugToStderr(ctx, 1);
112 :
113 42 : if (workgroup != NULL) {
114 42 : smbc_setWorkgroup(ctx, workgroup);
115 : }
116 42 : if (username != NULL) {
117 42 : smbc_setUser(ctx, username);
118 : }
119 :
120 42 : smbc_setFunctionAuthData(ctx, auth_callback);
121 :
122 42 : if (client_proto != NULL) {
123 42 : smbc_setOptionProtocols(ctx, client_proto, client_proto);
124 : }
125 :
126 42 : *ctx_p = ctx;
127 :
128 42 : out:
129 42 : if (!ok) {
130 0 : smbc_free_context(ctx, 1);
131 : }
132 :
133 42 : return ok;
134 : }
135 :
136 4 : static bool torture_libsmbclient_version(struct torture_context *tctx)
137 : {
138 4 : torture_comment(tctx, "Testing smbc_version\n");
139 :
140 4 : torture_assert(tctx, smbc_version(), "failed to get version");
141 :
142 4 : return true;
143 : }
144 :
145 4 : static bool torture_libsmbclient_initialize(struct torture_context *tctx)
146 : {
147 0 : SMBCCTX *ctx;
148 4 : bool ret = false;
149 :
150 4 : torture_comment(tctx, "Testing smbc_new_context\n");
151 :
152 4 : ctx = smbc_new_context();
153 4 : torture_assert(tctx, ctx, "failed to get new context");
154 :
155 4 : torture_comment(tctx, "Testing smbc_init_context\n");
156 :
157 4 : torture_assert(tctx, smbc_init_context(ctx), "failed to init context");
158 :
159 4 : smbc_setLogCallback(ctx, &ret, debug_callback);
160 4 : DEBUG(0, (TEST_STRING"\n"));
161 4 : torture_assert(tctx, ret, "Failed debug_callback not called");
162 4 : ret = false;
163 4 : smbc_setLogCallback(ctx, NULL, NULL);
164 4 : DEBUG(0, (TEST_STRING"\n"));
165 4 : torture_assert(tctx, !ret, "Failed debug_callback called");
166 :
167 4 : smbc_free_context(ctx, 1);
168 :
169 4 : return true;
170 : }
171 :
172 4 : static bool torture_libsmbclient_setConfiguration(struct torture_context *tctx)
173 : {
174 0 : SMBCCTX *ctx;
175 4 : struct loadparm_global *global_config = NULL;
176 4 : const char *new_smb_conf = torture_setting_string(tctx,
177 : "replace_smbconf",
178 : "");
179 :
180 4 : ctx = smbc_new_context();
181 4 : torture_assert_not_null(tctx, ctx, "failed to get new context");
182 :
183 4 : torture_assert_not_null(
184 : tctx, smbc_init_context(ctx), "failed to init context");
185 :
186 4 : torture_comment(tctx, "Testing smbc_setConfiguration - new file %s\n",
187 : new_smb_conf);
188 :
189 4 : global_config = get_globals();
190 4 : torture_assert(tctx, global_config, "Global Config is NULL");
191 :
192 : /* check configuration before smbc_setConfiguration call */
193 4 : torture_comment(tctx, "'workgroup' before setConfiguration %s\n",
194 : global_config->workgroup);
195 4 : torture_comment(tctx, "'client min protocol' before "
196 : "setConfiguration %d\n",
197 : global_config->client_min_protocol);
198 4 : torture_comment(tctx, "'client max protocol' before "
199 : "setConfiguration %d\n",
200 : global_config->_client_max_protocol);
201 4 : torture_comment(tctx, "'client signing' before setConfiguration %d\n",
202 : global_config->client_signing);
203 4 : torture_comment(tctx, "'deadtime' before setConfiguration %d\n",
204 : global_config->deadtime);
205 :
206 4 : torture_assert_int_equal(tctx, smbc_setConfiguration(ctx, new_smb_conf),
207 : 0, "setConfiguration conf file not found");
208 :
209 : /* verify configuration */
210 4 : torture_assert_str_equal(tctx, global_config->workgroup,
211 : "NEW_WORKGROUP",
212 : "smbc_setConfiguration failed, "
213 : "'workgroup' not updated");
214 4 : torture_assert_int_equal(tctx, global_config->client_min_protocol, PROTOCOL_NT1,
215 : "smbc_setConfiguration failed, 'client min protocol' "
216 : "not updated");
217 4 : torture_assert_int_equal(tctx, global_config->_client_max_protocol, PROTOCOL_SMB3_00,
218 : "smbc_setConfiguration failed, 'client max protocol' "
219 : "not updated");
220 4 : torture_assert_int_equal(tctx, global_config->client_signing, 1,
221 : "smbc_setConfiguration failed, 'client signing' "
222 : "not updated");
223 4 : torture_assert_int_equal(tctx, global_config->deadtime, 5,
224 : "smbc_setConfiguration failed, 'deadtime' not updated");
225 :
226 : /* Restore configuration to default */
227 4 : smbc_setConfiguration(ctx, get_dyn_CONFIGFILE());
228 :
229 4 : smbc_free_context(ctx, 1);
230 :
231 4 : return true;
232 : }
233 :
234 68 : static bool test_opendir(struct torture_context *tctx,
235 : SMBCCTX *ctx,
236 : const char *fname,
237 : bool expect_success)
238 : {
239 0 : int handle, ret;
240 :
241 68 : torture_comment(tctx, "Testing smbc_opendir(%s)\n", fname);
242 :
243 68 : handle = smbc_opendir(fname);
244 68 : if (!expect_success) {
245 56 : return true;
246 : }
247 12 : if (handle < 0) {
248 8 : torture_fail(tctx, talloc_asprintf(tctx, "failed to obain file handle for '%s'", fname));
249 : }
250 :
251 4 : ret = smbc_closedir(handle);
252 4 : torture_assert_int_equal(tctx, ret, 0,
253 : talloc_asprintf(tctx, "failed to close file handle for '%s'", fname));
254 :
255 4 : return true;
256 : }
257 :
258 4 : static bool torture_libsmbclient_opendir(struct torture_context *tctx)
259 : {
260 0 : size_t i;
261 0 : SMBCCTX *ctx;
262 4 : bool ret = true;
263 4 : const char *bad_urls[] = {
264 : "",
265 : NULL,
266 : "smb",
267 : "smb:",
268 : "smb:/",
269 : "smb:///",
270 : "bms://",
271 : ":",
272 : ":/",
273 : "://",
274 : ":///",
275 : "/",
276 : "//",
277 : "///"
278 : };
279 4 : const char *good_urls[] = {
280 : "smb://",
281 : "smb://WORKGROUP",
282 : "smb://WORKGROUP/"
283 : };
284 :
285 4 : torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), "");
286 4 : smbc_set_context(ctx);
287 :
288 60 : for (i=0; i < ARRAY_SIZE(bad_urls); i++) {
289 56 : ret &= test_opendir(tctx, ctx, bad_urls[i], false);
290 : }
291 16 : for (i=0; i < ARRAY_SIZE(good_urls); i++) {
292 12 : ret &= test_opendir(tctx, ctx, good_urls[i], true);
293 : }
294 :
295 4 : smbc_free_context(ctx, 1);
296 :
297 4 : return ret;
298 : }
299 :
300 4 : static bool torture_libsmbclient_readdirplus(struct torture_context *tctx)
301 : {
302 0 : SMBCCTX *ctx;
303 4 : int ret = -1;
304 4 : int dhandle = -1;
305 4 : int fhandle = -1;
306 4 : bool found = false;
307 4 : const char *filename = NULL;
308 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
309 :
310 4 : if (smburl == NULL) {
311 0 : torture_fail(tctx,
312 : "option --option=torture:smburl="
313 : "smb://user:password@server/share missing\n");
314 : }
315 :
316 4 : torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), "");
317 4 : smbc_set_context(ctx);
318 :
319 4 : filename = talloc_asprintf(tctx,
320 : "%s/test_readdirplus.txt",
321 : smburl);
322 4 : if (filename == NULL) {
323 0 : torture_fail(tctx,
324 : "talloc fail\n");
325 : }
326 : /* Ensure the file doesn't exist. */
327 4 : smbc_unlink(filename);
328 :
329 : /* Create it. */
330 4 : fhandle = smbc_creat(filename, 0666);
331 4 : if (fhandle < 0) {
332 0 : torture_fail(tctx,
333 : talloc_asprintf(tctx,
334 : "failed to create file '%s': %s",
335 : filename,
336 : strerror(errno)));
337 : }
338 4 : ret = smbc_close(fhandle);
339 4 : torture_assert_int_equal(tctx,
340 : ret,
341 : 0,
342 : talloc_asprintf(tctx,
343 : "failed to close handle for '%s'",
344 : filename));
345 :
346 4 : dhandle = smbc_opendir(smburl);
347 4 : if (dhandle < 0) {
348 0 : int saved_errno = errno;
349 0 : smbc_unlink(filename);
350 0 : torture_fail(tctx,
351 : talloc_asprintf(tctx,
352 : "failed to obtain "
353 : "directory handle for '%s' : %s",
354 : smburl,
355 : strerror(saved_errno)));
356 : }
357 :
358 : /* Readdirplus to ensure we see the new file. */
359 123 : for (;;) {
360 0 : const struct libsmb_file_info *exstat =
361 127 : smbc_readdirplus(dhandle);
362 127 : if (exstat == NULL) {
363 0 : break;
364 : }
365 127 : if (strcmp(exstat->name, "test_readdirplus.txt") == 0) {
366 4 : found = true;
367 4 : break;
368 : }
369 : }
370 :
371 : /* Remove it again. */
372 4 : smbc_unlink(filename);
373 4 : ret = smbc_closedir(dhandle);
374 4 : torture_assert_int_equal(tctx,
375 : ret,
376 : 0,
377 : talloc_asprintf(tctx,
378 : "failed to close directory handle for '%s'",
379 : smburl));
380 :
381 4 : smbc_free_context(ctx, 1);
382 :
383 4 : if (!found) {
384 0 : torture_fail(tctx,
385 : talloc_asprintf(tctx,
386 : "failed to find file '%s'",
387 : filename));
388 : }
389 :
390 4 : return true;
391 : }
392 :
393 4 : static bool torture_libsmbclient_readdirplus_seek(struct torture_context *tctx)
394 : {
395 0 : SMBCCTX *ctx;
396 4 : int ret = -1;
397 4 : int dhandle = -1;
398 4 : int fhandle = -1;
399 4 : const char *dname = NULL;
400 4 : const char *full_filename[100] = {0};
401 4 : const char *filename[100] = {0};
402 4 : const struct libsmb_file_info *direntries[102] = {0};
403 4 : unsigned int i = 0;
404 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
405 4 : bool success = false;
406 4 : off_t telldir_50 = (off_t)-1;
407 4 : off_t telldir_20 = (off_t)-1;
408 4 : size_t getdentries_size = 0;
409 4 : struct smbc_dirent *getdentries = NULL;
410 4 : struct smbc_dirent *dirent_20 = NULL;
411 4 : const struct libsmb_file_info *direntries_20 = NULL;
412 4 : const struct libsmb_file_info *direntriesplus_20 = NULL;
413 4 : const char *plus2_stat_path = NULL;
414 4 : struct stat st = {0};
415 4 : struct stat st2 = {0};
416 :
417 4 : torture_assert_not_null(
418 : tctx,
419 : smburl,
420 : "option --option=torture:smburl="
421 : "smb://user:password@server/share missing\n");
422 :
423 4 : DEBUG(0,("torture_libsmbclient_readdirplus_seek start\n"));
424 :
425 4 : torture_assert(tctx, torture_libsmbclient_init_context(tctx, &ctx), "");
426 4 : smbc_set_context(ctx);
427 :
428 4 : dname = talloc_asprintf(tctx,
429 : "%s/rd_seek",
430 : smburl);
431 4 : torture_assert_not_null_goto(
432 : tctx, dname, success, done, "talloc fail\n");
433 :
434 : /* Ensure the files don't exist. */
435 404 : for (i = 0; i < 100; i++) {
436 400 : filename[i] = talloc_asprintf(tctx,
437 : "test_readdirplus_%u.txt",
438 : i);
439 400 : torture_assert_not_null_goto(
440 : tctx, filename[i], success, done, "talloc fail");
441 400 : full_filename[i] = talloc_asprintf(tctx,
442 : "%s/%s",
443 : dname,
444 : filename[i]);
445 400 : torture_assert_not_null_goto(
446 : tctx, full_filename[i], success, done, "talloc fail");
447 400 : (void)smbc_unlink(full_filename[i]);
448 : }
449 : /* Ensure the directory doesn't exist. */
450 4 : (void)smbc_rmdir(dname);
451 :
452 : /* Create containing directory. */
453 4 : ret = smbc_mkdir(dname, 0777);
454 4 : torture_assert_goto(
455 : tctx,
456 : ret == 0,
457 : success,
458 : done,
459 : talloc_asprintf(tctx,
460 : "failed to create directory '%s': %s",
461 : dname,
462 : strerror(errno)));
463 :
464 4 : DEBUG(0,("torture_libsmbclient_readdirplus_seek create\n"));
465 :
466 : /* Create them. */
467 404 : for (i = 0; i < 100; i++) {
468 400 : fhandle = smbc_creat(full_filename[i], 0666);
469 400 : if (fhandle < 0) {
470 0 : torture_fail_goto(tctx,
471 : done,
472 : talloc_asprintf(tctx,
473 : "failed to create file '%s': %s",
474 : full_filename[i],
475 : strerror(errno)));
476 : }
477 400 : ret = smbc_close(fhandle);
478 400 : torture_assert_int_equal_goto(tctx,
479 : ret,
480 : 0,
481 : success,
482 : done,
483 : talloc_asprintf(tctx,
484 : "failed to close handle for '%s'",
485 : full_filename[i]));
486 : }
487 :
488 4 : DEBUG(0,("torture_libsmbclient_readdirplus_seek enum\n"));
489 :
490 : /* Now enumerate the directory. */
491 4 : dhandle = smbc_opendir(dname);
492 4 : torture_assert_goto(
493 : tctx,
494 : dhandle >= 0,
495 : success,
496 : done,
497 : talloc_asprintf(tctx,
498 : "failed to obtain "
499 : "directory handle for '%s' : %s",
500 : dname,
501 : strerror(errno)));
502 :
503 : /* Read all the files. 100 we created plus . and .. */
504 412 : for (i = 0; i < 102; i++) {
505 408 : bool found = false;
506 0 : unsigned int j;
507 :
508 408 : direntries[i] = smbc_readdirplus(dhandle);
509 408 : if (direntries[i] == NULL) {
510 0 : break;
511 : }
512 :
513 : /* Store at offset 50. */
514 408 : if (i == 50) {
515 4 : telldir_50 = smbc_telldir(dhandle);
516 4 : torture_assert_goto(
517 : tctx,
518 : telldir_50 != (off_t)-1,
519 : success,
520 : done,
521 : talloc_asprintf(tctx,
522 : "telldir failed file %s\n",
523 : direntries[i]->name));
524 : }
525 :
526 408 : if (ISDOT(direntries[i]->name)) {
527 4 : continue;
528 : }
529 404 : if (ISDOTDOT(direntries[i]->name)) {
530 4 : continue;
531 : }
532 :
533 : /* Ensure all our files exist. */
534 40400 : for (j = 0; j < 100; j++) {
535 40000 : if (strcmp(direntries[i]->name,
536 : filename[j]) == 0) {
537 400 : found = true;
538 : }
539 : }
540 400 : torture_assert_goto(
541 : tctx,
542 : found,
543 : success,
544 : done,
545 : talloc_asprintf(tctx,
546 : "failed to find file %s\n",
547 : direntries[i]->name));
548 : }
549 :
550 : /*
551 : * We're seeking on in-memory lists here, so
552 : * whilst the handle is open we really should
553 : * get the same files back in the same order.
554 : */
555 :
556 4 : ret = smbc_lseekdir(dhandle, telldir_50);
557 4 : torture_assert_int_equal_goto(tctx,
558 : ret,
559 : 0,
560 : success,
561 : done,
562 : talloc_asprintf(tctx,
563 : "failed to seek (50) directory handle for '%s'",
564 : dname));
565 :
566 4 : DEBUG(0,("torture_libsmbclient_readdirplus_seek seek\n"));
567 :
568 208 : for (i = 51; i < 102; i++) {
569 0 : const struct libsmb_file_info *entry =
570 204 : smbc_readdirplus(dhandle);
571 204 : torture_assert_goto(
572 : tctx,
573 : entry == direntries[i],
574 : success,
575 : done,
576 : talloc_asprintf(tctx,
577 : "after seek - failed to find "
578 : "file %s - got %s\n",
579 : direntries[i]->name,
580 : entry->name));
581 : }
582 :
583 : /* Seek back to the start. */
584 4 : ret = smbc_lseekdir(dhandle, 0);
585 4 : torture_assert_int_equal_goto(tctx,
586 : ret,
587 : 0,
588 : success,
589 : done,
590 : talloc_asprintf(tctx,
591 : "failed to seek directory handle to start for '%s'",
592 : dname));
593 :
594 : /*
595 : * Mix getdents/readdir/readdirplus with lseek to ensure
596 : * we get the same result.
597 : */
598 :
599 : /* Allocate the space for 20 entries.
600 : * Tricky as we need to allocate 20 struct smbc_dirent's + space
601 : * for the name lengths.
602 : */
603 4 : getdentries_size = 20 * (sizeof(struct smbc_dirent) +
604 : strlen("test_readdirplus_1000.txt") + 1);
605 :
606 4 : getdentries = (struct smbc_dirent *)talloc_array_size(tctx,
607 : getdentries_size,
608 : 1);
609 4 : torture_assert_not_null_goto(
610 : tctx,
611 : getdentries,
612 : success,
613 : done,
614 : "talloc fail");
615 :
616 4 : ret = smbc_getdents(dhandle, getdentries, getdentries_size);
617 4 : torture_assert_goto(tctx,
618 : (ret != -1),
619 : success,
620 : done,
621 : talloc_asprintf(tctx,
622 : "smbd_getdents(1) for '%s' failed\n",
623 : dname));
624 :
625 4 : telldir_20 = smbc_telldir(dhandle);
626 4 : torture_assert_goto(
627 : tctx,
628 : telldir_20 != (off_t)-1,
629 : success,
630 : done,
631 : "telldir (20) failed\n");
632 :
633 : /* Read another 20. */
634 4 : ret = smbc_getdents(dhandle, getdentries, getdentries_size);
635 4 : torture_assert_goto(tctx,
636 : (ret != -1),
637 : success,
638 : done,
639 : talloc_asprintf(tctx,
640 : "smbd_getdents(2) for '%s' failed\n",
641 : dname));
642 :
643 : /* Seek back to 20. */
644 4 : ret = smbc_lseekdir(dhandle, telldir_20);
645 4 : torture_assert_int_equal_goto(tctx,
646 : ret,
647 : 0,
648 : success,
649 : done,
650 : talloc_asprintf(tctx,
651 : "failed to seek (20) directory handle for '%s'",
652 : dname));
653 :
654 : /* Read with readdir. */
655 4 : dirent_20 = smbc_readdir(dhandle);
656 4 : torture_assert_not_null_goto(
657 : tctx,
658 : dirent_20,
659 : success,
660 : done,
661 : "smbc_readdir (20) failed\n");
662 :
663 : /* Ensure the getdents and readdir names are the same. */
664 4 : ret = strcmp(dirent_20->name, getdentries[0].name);
665 4 : torture_assert_goto(
666 : tctx,
667 : ret == 0,
668 : success,
669 : done,
670 : talloc_asprintf(tctx,
671 : "after seek (20) readdir name mismatch "
672 : "file %s - got %s\n",
673 : dirent_20->name,
674 : getdentries[0].name));
675 :
676 : /* Seek back to 20. */
677 4 : ret = smbc_lseekdir(dhandle, telldir_20);
678 4 : torture_assert_int_equal_goto(tctx,
679 : ret,
680 : 0,
681 : success,
682 : done,
683 : talloc_asprintf(tctx,
684 : "failed to seek (20) directory handle for '%s'",
685 : dname));
686 : /* Read with readdirplus. */
687 4 : direntries_20 = smbc_readdirplus(dhandle);
688 4 : torture_assert_not_null_goto(
689 : tctx,
690 : direntries_20,
691 : success,
692 : done,
693 : "smbc_readdirplus (20) failed\n");
694 :
695 : /* Ensure the readdirplus and readdir names are the same. */
696 4 : ret = strcmp(dirent_20->name, direntries_20->name);
697 4 : torture_assert_goto(
698 : tctx,
699 : ret == 0,
700 : success,
701 : done,
702 : talloc_asprintf(tctx,
703 : "after seek (20) readdirplus name mismatch "
704 : "file %s - got %s\n",
705 : dirent_20->name,
706 : direntries_20->name));
707 :
708 : /* Seek back to 20. */
709 4 : ret = smbc_lseekdir(dhandle, telldir_20);
710 4 : torture_assert_int_equal_goto(tctx,
711 : ret,
712 : 0,
713 : success,
714 : done,
715 : talloc_asprintf(tctx,
716 : "failed to seek (20) directory handle for '%s'",
717 : dname));
718 :
719 : /* Read with readdirplus2. */
720 4 : direntriesplus_20 = smbc_readdirplus2(dhandle, &st2);
721 4 : torture_assert_not_null_goto(
722 : tctx,
723 : direntriesplus_20,
724 : success,
725 : done,
726 : "smbc_readdirplus2 (20) failed\n");
727 :
728 : /* Ensure the readdirplus2 and readdirplus names are the same. */
729 4 : ret = strcmp(direntries_20->name, direntriesplus_20->name);
730 4 : torture_assert_goto(
731 : tctx,
732 : ret == 0,
733 : success,
734 : done,
735 : talloc_asprintf(tctx,
736 : "after seek (20) readdirplus2 name mismatch "
737 : "file %s - got %s\n",
738 : dirent_20->name,
739 : direntries_20->name));
740 :
741 : /* Ensure doing stat gets the same data. */
742 4 : plus2_stat_path = talloc_asprintf(tctx,
743 : "%s/%s",
744 : dname,
745 4 : direntriesplus_20->name);
746 4 : torture_assert_not_null_goto(
747 : tctx,
748 : plus2_stat_path,
749 : success,
750 : done,
751 : "talloc fail\n");
752 :
753 4 : ret = smbc_stat(plus2_stat_path, &st);
754 4 : torture_assert_int_equal_goto(tctx,
755 : ret,
756 : 0,
757 : success,
758 : done,
759 : talloc_asprintf(tctx,
760 : "failed to stat file '%s'",
761 : plus2_stat_path));
762 :
763 4 : torture_assert_int_equal(tctx,
764 : st.st_ino,
765 : st2.st_ino,
766 : talloc_asprintf(tctx,
767 : "file %s mismatched ino value "
768 : "stat got %"PRIx64" readdirplus2 got %"PRIx64"" ,
769 : plus2_stat_path,
770 : (uint64_t)st.st_ino,
771 : (uint64_t)st2.st_ino));
772 :
773 4 : torture_assert_int_equal(tctx,
774 : st.st_dev,
775 : st2.st_dev,
776 : talloc_asprintf(tctx,
777 : "file %s mismatched dev value "
778 : "stat got %"PRIx64" readdirplus2 got %"PRIx64"" ,
779 : plus2_stat_path,
780 : (uint64_t)st.st_dev,
781 : (uint64_t)st2.st_dev));
782 :
783 4 : ret = smbc_closedir(dhandle);
784 4 : torture_assert_int_equal(tctx,
785 : ret,
786 : 0,
787 : talloc_asprintf(tctx,
788 : "failed to close directory handle for '%s'",
789 : dname));
790 :
791 4 : dhandle = -1;
792 4 : success = true;
793 :
794 4 : done:
795 :
796 : /* Clean up. */
797 4 : if (dhandle != -1) {
798 0 : smbc_closedir(dhandle);
799 : }
800 404 : for (i = 0; i < 100; i++) {
801 400 : if (full_filename[i] != NULL) {
802 400 : smbc_unlink(full_filename[i]);
803 : }
804 : }
805 4 : if (dname != NULL) {
806 4 : smbc_rmdir(dname);
807 : }
808 :
809 4 : smbc_free_context(ctx, 1);
810 :
811 4 : return success;
812 : }
813 :
814 : #ifndef SMBC_FILE_MODE
815 : #define SMBC_FILE_MODE (S_IFREG | 0444)
816 : #endif
817 :
818 4 : static bool torture_libsmbclient_readdirplus2(struct torture_context *tctx)
819 : {
820 4 : SMBCCTX *ctx = NULL;
821 4 : int dhandle = -1;
822 4 : int fhandle = -1;
823 4 : bool found = false;
824 4 : bool success = false;
825 4 : const char *filename = NULL;
826 4 : struct stat st2 = {0};
827 4 : struct stat st = {0};
828 0 : int ret;
829 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
830 :
831 4 : if (smburl == NULL) {
832 0 : torture_fail(tctx,
833 : "option --option=torture:smburl="
834 : "smb://user:password@server/share missing\n");
835 : }
836 :
837 4 : torture_assert_goto(tctx, torture_libsmbclient_init_context(tctx, &ctx), success, done, "");
838 4 : smbc_set_context(ctx);
839 :
840 4 : filename = talloc_asprintf(tctx,
841 : "%s/test_readdirplus.txt",
842 : smburl);
843 4 : if (filename == NULL) {
844 0 : torture_fail_goto(tctx, done, "talloc fail\n");
845 : }
846 :
847 : /* Ensure the file doesn't exist. */
848 4 : smbc_unlink(filename);
849 :
850 : /* Create it. */
851 4 : fhandle = smbc_creat(filename, 0666);
852 4 : if (fhandle < 0) {
853 0 : torture_fail_goto(tctx,
854 : done,
855 : talloc_asprintf(tctx,
856 : "failed to create file '%s': %s",
857 : filename,
858 : strerror(errno)));
859 : }
860 4 : ret = smbc_close(fhandle);
861 4 : torture_assert_int_equal_goto(tctx,
862 : ret,
863 : 0,
864 : success,
865 : done,
866 : talloc_asprintf(tctx,
867 : "failed to close handle for '%s'",
868 : filename));
869 :
870 4 : dhandle = smbc_opendir(smburl);
871 4 : if (dhandle < 0) {
872 0 : int saved_errno = errno;
873 0 : smbc_unlink(filename);
874 0 : torture_fail_goto(tctx,
875 : done,
876 : talloc_asprintf(tctx,
877 : "failed to obtain "
878 : "directory handle for '%s' : %s",
879 : smburl,
880 : strerror(saved_errno)));
881 : }
882 :
883 : /* readdirplus2 to ensure we see the new file. */
884 123 : for (;;) {
885 0 : const struct libsmb_file_info *exstat =
886 127 : smbc_readdirplus2(dhandle, &st2);
887 127 : if (exstat == NULL) {
888 0 : break;
889 : }
890 :
891 127 : if (strcmp(exstat->name, "test_readdirplus.txt") == 0) {
892 4 : found = true;
893 4 : break;
894 : }
895 : }
896 :
897 4 : if (!found) {
898 0 : smbc_unlink(filename);
899 0 : torture_fail_goto(tctx,
900 : done,
901 : talloc_asprintf(tctx,
902 : "failed to find file '%s'",
903 : filename));
904 : }
905 :
906 : /* Ensure mode is as expected. */
907 : /*
908 : * New file gets SMBC_FILE_MODE plus
909 : * archive bit -> S_IXUSR
910 : * !READONLY -> S_IWUSR.
911 : */
912 4 : torture_assert_int_equal_goto(tctx,
913 : st2.st_mode,
914 : SMBC_FILE_MODE|S_IXUSR|S_IWUSR,
915 : success,
916 : done,
917 : talloc_asprintf(tctx,
918 : "file %s st_mode should be 0%o, got 0%o'",
919 : filename,
920 : SMBC_FILE_MODE|S_IXUSR|S_IWUSR,
921 : (unsigned int)st2.st_mode));
922 :
923 : /* Ensure smbc_stat() gets the same data. */
924 4 : ret = smbc_stat(filename, &st);
925 4 : torture_assert_int_equal_goto(tctx,
926 : ret,
927 : 0,
928 : success,
929 : done,
930 : talloc_asprintf(tctx,
931 : "failed to stat file '%s'",
932 : filename));
933 :
934 4 : torture_assert_int_equal_goto(tctx,
935 : st2.st_ino,
936 : st.st_ino,
937 : success,
938 : done,
939 : talloc_asprintf(tctx,
940 : "filename '%s' ino mismatch. "
941 : "From smbc_readdirplus2 = %"PRIx64" "
942 : "From smbc_stat = %"PRIx64"",
943 : filename,
944 : (uint64_t)st2.st_ino,
945 : (uint64_t)st.st_ino));
946 :
947 :
948 : /* Remove it again. */
949 4 : smbc_unlink(filename);
950 4 : ret = smbc_closedir(dhandle);
951 4 : torture_assert_int_equal_goto(tctx,
952 : ret,
953 : 0,
954 : success,
955 : done,
956 : talloc_asprintf(tctx,
957 : "failed to close directory handle for '%s'",
958 : filename));
959 4 : success = true;
960 :
961 4 : done:
962 4 : smbc_free_context(ctx, 1);
963 4 : return success;
964 : }
965 :
966 4 : bool torture_libsmbclient_configuration(struct torture_context *tctx)
967 : {
968 0 : SMBCCTX *ctx;
969 4 : bool ok = true;
970 :
971 4 : ctx = smbc_new_context();
972 4 : torture_assert(tctx, ctx, "failed to get new context");
973 4 : torture_assert(tctx, smbc_init_context(ctx), "failed to init context");
974 :
975 4 : torture_comment(tctx, "Testing smbc_(set|get)Debug\n");
976 4 : smbc_setDebug(ctx, DEBUGLEVEL);
977 4 : torture_assert_int_equal_goto(tctx,
978 : smbc_getDebug(ctx),
979 : DEBUGLEVEL,
980 : ok,
981 : done,
982 : "failed to set DEBUGLEVEL");
983 :
984 4 : torture_comment(tctx, "Testing smbc_(set|get)NetbiosName\n");
985 4 : smbc_setNetbiosName(ctx, discard_const("torture_netbios"));
986 4 : torture_assert_str_equal_goto(tctx,
987 : smbc_getNetbiosName(ctx),
988 : "torture_netbios",
989 : ok,
990 : done,
991 : "failed to set NetbiosName");
992 :
993 4 : torture_comment(tctx, "Testing smbc_(set|get)Workgroup\n");
994 4 : smbc_setWorkgroup(ctx, discard_const("torture_workgroup"));
995 4 : torture_assert_str_equal_goto(tctx,
996 : smbc_getWorkgroup(ctx),
997 : "torture_workgroup",
998 : ok,
999 : done,
1000 : "failed to set Workgroup");
1001 :
1002 4 : torture_comment(tctx, "Testing smbc_(set|get)User\n");
1003 4 : smbc_setUser(ctx, "torture_user");
1004 4 : torture_assert_str_equal_goto(tctx,
1005 : smbc_getUser(ctx),
1006 : "torture_user",
1007 : ok,
1008 : done,
1009 : "failed to set User");
1010 :
1011 4 : torture_comment(tctx, "Testing smbc_(set|get)Timeout\n");
1012 4 : smbc_setTimeout(ctx, 12345);
1013 4 : torture_assert_int_equal_goto(tctx,
1014 : smbc_getTimeout(ctx),
1015 : 12345,
1016 : ok,
1017 : done,
1018 : "failed to set Timeout");
1019 :
1020 4 : done:
1021 4 : smbc_free_context(ctx, 1);
1022 :
1023 4 : return ok;
1024 : }
1025 :
1026 4 : bool torture_libsmbclient_options(struct torture_context *tctx)
1027 : {
1028 0 : SMBCCTX *ctx;
1029 4 : bool ok = true;
1030 :
1031 4 : ctx = smbc_new_context();
1032 4 : torture_assert(tctx, ctx, "failed to get new context");
1033 4 : torture_assert(tctx, smbc_init_context(ctx), "failed to init context");
1034 :
1035 4 : torture_comment(tctx, "Testing smbc_(set|get)OptionDebugToStderr\n");
1036 4 : smbc_setOptionDebugToStderr(ctx, true);
1037 4 : torture_assert_goto(tctx,
1038 : smbc_getOptionDebugToStderr(ctx),
1039 : ok,
1040 : done,
1041 : "failed to set OptionDebugToStderr");
1042 :
1043 4 : torture_comment(tctx, "Testing smbc_(set|get)OptionFullTimeNames\n");
1044 4 : smbc_setOptionFullTimeNames(ctx, true);
1045 4 : torture_assert_goto(tctx,
1046 : smbc_getOptionFullTimeNames(ctx),
1047 : ok,
1048 : done,
1049 : "failed to set OptionFullTimeNames");
1050 :
1051 4 : torture_comment(tctx, "Testing smbc_(set|get)OptionOpenShareMode\n");
1052 4 : smbc_setOptionOpenShareMode(ctx, SMBC_SHAREMODE_DENY_ALL);
1053 4 : torture_assert_int_equal_goto(tctx,
1054 : smbc_getOptionOpenShareMode(ctx),
1055 : SMBC_SHAREMODE_DENY_ALL,
1056 : ok,
1057 : done,
1058 : "failed to set OptionOpenShareMode");
1059 :
1060 4 : torture_comment(tctx, "Testing smbc_(set|get)OptionUserData\n");
1061 4 : smbc_setOptionUserData(ctx, (void *)discard_const("torture_user_data"));
1062 4 : torture_assert_str_equal_goto(tctx,
1063 : (const char*)smbc_getOptionUserData(ctx),
1064 : "torture_user_data",
1065 : ok,
1066 : done,
1067 : "failed to set OptionUserData");
1068 :
1069 4 : torture_comment(tctx,
1070 : "Testing smbc_(set|get)OptionSmbEncryptionLevel\n");
1071 4 : smbc_setOptionSmbEncryptionLevel(ctx, SMBC_ENCRYPTLEVEL_REQUEST);
1072 4 : torture_assert_int_equal_goto(tctx,
1073 : smbc_getOptionSmbEncryptionLevel(ctx),
1074 : SMBC_ENCRYPTLEVEL_REQUEST,
1075 : ok,
1076 : done,
1077 : "failed to set OptionSmbEncryptionLevel");
1078 :
1079 4 : torture_comment(tctx, "Testing smbc_(set|get)OptionCaseSensitive\n");
1080 4 : smbc_setOptionCaseSensitive(ctx, false);
1081 4 : torture_assert_goto(tctx,
1082 : !smbc_getOptionCaseSensitive(ctx),
1083 : ok,
1084 : done,
1085 : "failed to set OptionCaseSensitive");
1086 :
1087 4 : torture_comment(tctx,
1088 : "Testing smbc_(set|get)OptionBrowseMaxLmbCount\n");
1089 4 : smbc_setOptionBrowseMaxLmbCount(ctx, 2);
1090 4 : torture_assert_int_equal_goto(tctx,
1091 : smbc_getOptionBrowseMaxLmbCount(ctx),
1092 : 2,
1093 : ok,
1094 : done,
1095 : "failed to set OptionBrowseMaxLmbCount");
1096 :
1097 4 : torture_comment(tctx,
1098 : "Testing smbc_(set|get)OptionUrlEncodeReaddirEntries\n");
1099 4 : smbc_setOptionUrlEncodeReaddirEntries(ctx, true);
1100 4 : torture_assert_goto(tctx,
1101 : smbc_getOptionUrlEncodeReaddirEntries(ctx),
1102 : ok,
1103 : done,
1104 : "failed to set OptionUrlEncodeReaddirEntries");
1105 :
1106 4 : torture_comment(tctx,
1107 : "Testing smbc_(set|get)OptionOneSharePerServer\n");
1108 4 : smbc_setOptionOneSharePerServer(ctx, true);
1109 4 : torture_assert_goto(tctx,
1110 : smbc_getOptionOneSharePerServer(ctx),
1111 : ok,
1112 : done,
1113 : "failed to set OptionOneSharePerServer");
1114 :
1115 4 : torture_comment(tctx, "Testing smbc_(set|get)OptionUseKerberos\n");
1116 4 : smbc_setOptionUseKerberos(ctx, false);
1117 4 : torture_assert_goto(tctx,
1118 : !smbc_getOptionUseKerberos(ctx),
1119 : ok,
1120 : done,
1121 : "failed to set OptionUseKerberos");
1122 :
1123 4 : torture_comment(tctx,
1124 : "Testing smbc_(set|get)OptionFallbackAfterKerberos\n");
1125 4 : smbc_setOptionFallbackAfterKerberos(ctx, false);
1126 4 : torture_assert_goto(tctx,
1127 : !smbc_getOptionFallbackAfterKerberos(ctx),
1128 : ok,
1129 : done,
1130 : "failed to set OptionFallbackAfterKerberos");
1131 :
1132 4 : torture_comment(tctx,
1133 : "Testing smbc_(set|get)OptionNoAutoAnonymousLogin\n");
1134 4 : smbc_setOptionNoAutoAnonymousLogin(ctx, true);
1135 4 : torture_assert_goto(tctx,
1136 : smbc_getOptionNoAutoAnonymousLogin(ctx),
1137 : ok,
1138 : done,
1139 : "failed to set OptionNoAutoAnonymousLogin");
1140 :
1141 4 : torture_comment(tctx, "Testing smbc_(set|get)OptionUseCCache\n");
1142 4 : smbc_setOptionUseCCache(ctx, true);
1143 4 : torture_assert_goto(tctx,
1144 : smbc_getOptionUseCCache(ctx),
1145 : ok,
1146 : done,
1147 : "failed to set OptionUseCCache");
1148 :
1149 4 : done:
1150 4 : smbc_free_context(ctx, 1);
1151 :
1152 4 : return ok;
1153 : }
1154 :
1155 4 : static bool torture_libsmbclient_list_shares(struct torture_context *tctx)
1156 : {
1157 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
1158 4 : struct smbc_dirent *dirent = NULL;
1159 4 : SMBCCTX *ctx = NULL;
1160 4 : int dhandle = -1;
1161 4 : bool ipc_share_found = false;
1162 4 : bool ok = true;
1163 :
1164 4 : if (smburl == NULL) {
1165 0 : torture_fail(tctx,
1166 : "option --option=torture:smburl="
1167 : "smb://user:password@server missing\n");
1168 : }
1169 :
1170 4 : ok = torture_libsmbclient_init_context(tctx, &ctx);
1171 4 : torture_assert_goto(tctx,
1172 : ok,
1173 : ok,
1174 : out,
1175 : "Failed to init context");
1176 4 : smbc_set_context(ctx);
1177 :
1178 4 : torture_comment(tctx, "Listing: %s\n", smburl);
1179 4 : dhandle = smbc_opendir(smburl);
1180 4 : torture_assert_int_not_equal_goto(tctx,
1181 : dhandle,
1182 : -1,
1183 : ok,
1184 : out,
1185 : "Failed to open smburl");
1186 :
1187 640 : while((dirent = smbc_readdir(dhandle)) != NULL) {
1188 636 : torture_comment(tctx, "DIR: %s\n", dirent->name);
1189 636 : torture_assert_not_null_goto(tctx,
1190 : dirent->name,
1191 : ok,
1192 : out,
1193 : "Failed to read name");
1194 :
1195 636 : if (strequal(dirent->name, "IPC$")) {
1196 4 : ipc_share_found = true;
1197 : }
1198 : }
1199 :
1200 4 : torture_assert_goto(tctx,
1201 : ipc_share_found,
1202 : ok,
1203 : out,
1204 : "Failed to list IPC$ share");
1205 :
1206 4 : out:
1207 4 : smbc_closedir(dhandle);
1208 4 : return ok;
1209 : }
1210 :
1211 4 : static bool torture_libsmbclient_utimes(struct torture_context *tctx)
1212 : {
1213 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
1214 4 : SMBCCTX *ctx = NULL;
1215 0 : struct stat st;
1216 0 : int fhandle, ret;
1217 0 : struct timeval tbuf[2];
1218 0 : bool ok;
1219 :
1220 4 : if (smburl == NULL) {
1221 0 : torture_fail(tctx,
1222 : "option --option=torture:smburl="
1223 : "smb://user:password@server missing\n");
1224 : }
1225 :
1226 4 : ok = torture_libsmbclient_init_context(tctx, &ctx);
1227 4 : torture_assert(tctx, ok, "Failed to init context");
1228 4 : smbc_set_context(ctx);
1229 :
1230 4 : fhandle = smbc_open(smburl, O_RDWR|O_CREAT, 0644);
1231 4 : torture_assert_int_not_equal(tctx, fhandle, -1, "smbc_open failed");
1232 :
1233 4 : ret = smbc_fstat(fhandle, &st);
1234 4 : torture_assert_int_not_equal(tctx, ret, -1, "smbc_fstat failed");
1235 :
1236 4 : tbuf[0] = convert_timespec_to_timeval(get_atimespec(&st));
1237 4 : tbuf[1] = convert_timespec_to_timeval(get_mtimespec(&st));
1238 :
1239 4 : tbuf[1] = timeval_add(&tbuf[1], 0, 100000); /* 100 msec */
1240 :
1241 4 : ret = smbc_utimes(smburl, tbuf);
1242 4 : torture_assert_int_not_equal(tctx, ret, -1, "smbc_utimes failed");
1243 :
1244 4 : ret = smbc_fstat(fhandle, &st);
1245 4 : torture_assert_int_not_equal(tctx, ret, -1, "smbc_fstat failed");
1246 :
1247 4 : torture_assert_int_equal(
1248 : tctx,
1249 : get_mtimensec(&st) / 1000,
1250 : tbuf[1].tv_usec,
1251 : "smbc_utimes did not update msec");
1252 :
1253 4 : smbc_close(fhandle);
1254 4 : smbc_unlink(smburl);
1255 4 : return true;
1256 : }
1257 :
1258 6 : static bool torture_libsmbclient_noanon_list(struct torture_context *tctx)
1259 : {
1260 6 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
1261 6 : struct smbc_dirent *dirent = NULL;
1262 6 : SMBCCTX *ctx = NULL;
1263 6 : int dhandle = -1;
1264 6 : bool ok = true;
1265 :
1266 6 : if (smburl == NULL) {
1267 0 : torture_fail(tctx,
1268 : "option --option=torture:smburl="
1269 : "smb://user:password@server missing\n");
1270 : }
1271 :
1272 6 : ok = torture_libsmbclient_init_context(tctx, &ctx);
1273 6 : torture_assert_goto(tctx,
1274 : ok,
1275 : ok,
1276 : out,
1277 : "Failed to init context");
1278 6 : torture_comment(tctx,
1279 : "Testing smbc_setOptionNoAutoAnonymousLogin\n");
1280 6 : smbc_setOptionNoAutoAnonymousLogin(ctx, true);
1281 6 : smbc_set_context(ctx);
1282 :
1283 6 : torture_comment(tctx, "Listing: %s\n", smburl);
1284 6 : dhandle = smbc_opendir(smburl);
1285 6 : torture_assert_int_not_equal_goto(tctx,
1286 : dhandle,
1287 : -1,
1288 : ok,
1289 : out,
1290 : "Failed to open smburl");
1291 :
1292 378 : while((dirent = smbc_readdir(dhandle)) != NULL) {
1293 372 : torture_comment(tctx, "DIR: %s\n", dirent->name);
1294 372 : torture_assert_not_null_goto(tctx,
1295 : dirent->name,
1296 : ok,
1297 : out,
1298 : "Failed to read name");
1299 : }
1300 :
1301 6 : out:
1302 6 : smbc_closedir(dhandle);
1303 6 : return ok;
1304 : }
1305 :
1306 4 : static bool torture_libsmbclient_rename(struct torture_context *tctx)
1307 : {
1308 4 : SMBCCTX *ctx = NULL;
1309 4 : int fhandle = -1;
1310 4 : bool success = false;
1311 4 : const char *filename_src = NULL;
1312 4 : const char *filename_dst = NULL;
1313 0 : int ret;
1314 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
1315 :
1316 4 : if (smburl == NULL) {
1317 0 : torture_fail(tctx,
1318 : "option --option=torture:smburl="
1319 : "smb://user:password@server/share missing\n");
1320 : }
1321 :
1322 4 : torture_assert_goto(tctx,
1323 : torture_libsmbclient_init_context(tctx, &ctx),
1324 : success,
1325 : done,
1326 : "");
1327 :
1328 4 : smbc_set_context(ctx);
1329 :
1330 4 : filename_src = talloc_asprintf(tctx,
1331 : "%s/src",
1332 : smburl);
1333 4 : if (filename_src == NULL) {
1334 0 : torture_fail_goto(tctx, done, "talloc fail\n");
1335 : }
1336 :
1337 4 : filename_dst = talloc_asprintf(tctx,
1338 : "%s/dst",
1339 : smburl);
1340 4 : if (filename_dst == NULL) {
1341 0 : torture_fail_goto(tctx, done, "talloc fail\n");
1342 : }
1343 :
1344 : /* Ensure the files don't exist. */
1345 4 : smbc_unlink(filename_src);
1346 4 : smbc_unlink(filename_dst);
1347 :
1348 : /* Create them. */
1349 4 : fhandle = smbc_creat(filename_src, 0666);
1350 4 : if (fhandle < 0) {
1351 0 : torture_fail_goto(tctx,
1352 : done,
1353 : talloc_asprintf(tctx,
1354 : "failed to create file '%s': %s",
1355 : filename_src,
1356 : strerror(errno)));
1357 : }
1358 4 : ret = smbc_close(fhandle);
1359 4 : torture_assert_int_equal_goto(tctx,
1360 : ret,
1361 : 0,
1362 : success,
1363 : done,
1364 : talloc_asprintf(tctx,
1365 : "failed to close handle for '%s'",
1366 : filename_src));
1367 :
1368 4 : fhandle = smbc_creat(filename_dst, 0666);
1369 4 : if (fhandle < 0) {
1370 0 : torture_fail_goto(tctx,
1371 : done,
1372 : talloc_asprintf(tctx,
1373 : "failed to create file '%s': %s",
1374 : filename_dst,
1375 : strerror(errno)));
1376 : }
1377 4 : ret = smbc_close(fhandle);
1378 4 : torture_assert_int_equal_goto(tctx,
1379 : ret,
1380 : 0,
1381 : success,
1382 : done,
1383 : talloc_asprintf(tctx,
1384 : "failed to close handle for '%s'",
1385 : filename_dst));
1386 :
1387 4 : ret = smbc_rename(filename_src, filename_dst);
1388 :
1389 : /*
1390 : * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14938
1391 : * gives ret == -1, but errno = 0 for overwrite renames
1392 : * over SMB2.
1393 : */
1394 4 : torture_assert_int_equal_goto(tctx,
1395 : ret,
1396 : 0,
1397 : success,
1398 : done,
1399 : talloc_asprintf(tctx,
1400 : "smbc_rename '%s' -> '%s' failed with %s\n",
1401 : filename_src,
1402 : filename_dst,
1403 : strerror(errno)));
1404 :
1405 : /* Remove them again. */
1406 4 : smbc_unlink(filename_src);
1407 4 : smbc_unlink(filename_dst);
1408 4 : success = true;
1409 :
1410 4 : done:
1411 4 : smbc_free_context(ctx, 1);
1412 4 : return success;
1413 : }
1414 :
1415 4 : static bool torture_libsmbclient_getatr(struct torture_context *tctx)
1416 : {
1417 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
1418 4 : SMBCCTX *ctx = NULL;
1419 4 : char *getatr_name = NULL;
1420 4 : struct stat st = {0};
1421 0 : bool ok;
1422 4 : int ret = 0;
1423 4 : int err = 0;
1424 :
1425 4 : if (smburl == NULL) {
1426 0 : torture_fail(tctx,
1427 : "option --option=torture:smburl="
1428 : "smb://user:password@server missing\n");
1429 : }
1430 :
1431 4 : ok = torture_libsmbclient_init_context(tctx, &ctx);
1432 4 : torture_assert(tctx, ok, "Failed to init context");
1433 4 : smbc_set_context(ctx);
1434 :
1435 4 : getatr_name = talloc_asprintf(tctx,
1436 : "%s/noexist",
1437 : smburl);
1438 4 : if (getatr_name == NULL) {
1439 0 : torture_result(tctx,
1440 : TORTURE_FAIL,
1441 : __location__": %s",
1442 : "talloc fail\n");
1443 0 : return false;
1444 : }
1445 : /* Ensure the file doesn't exist. */
1446 4 : smbc_unlink(getatr_name);
1447 : /*
1448 : * smbc_stat() internally uses SMBC_getatr().
1449 : * Make sure doing getatr on a non-existent file gives
1450 : * an error of -1, errno = ENOENT.
1451 : */
1452 :
1453 4 : ret = smbc_stat(getatr_name, &st);
1454 4 : if (ret == -1) {
1455 4 : err = errno;
1456 : }
1457 4 : torture_assert_int_equal(tctx,
1458 : ret,
1459 : -1,
1460 : talloc_asprintf(tctx,
1461 : "smbc_stat on '%s' should "
1462 : "get -1, got %d\n",
1463 : getatr_name,
1464 : ret));
1465 4 : torture_assert_int_equal(tctx,
1466 : err,
1467 : ENOENT,
1468 : talloc_asprintf(tctx,
1469 : "smbc_stat on '%s' should "
1470 : "get errno = ENOENT, got %s\n",
1471 : getatr_name,
1472 : strerror(err)));
1473 4 : return true;
1474 : }
1475 :
1476 4 : static bool torture_libsmbclient_getxattr(struct torture_context *tctx)
1477 : {
1478 4 : const char *smburl = torture_setting_string(tctx, "smburl", NULL);
1479 4 : int fhandle = -1;
1480 4 : SMBCCTX *ctx = NULL;
1481 4 : char *getxattr_name = NULL;
1482 0 : char value[4096];
1483 4 : bool ok = false;
1484 4 : int ret = -1;
1485 :
1486 4 : if (smburl == NULL) {
1487 0 : torture_fail(tctx,
1488 : "option --option=torture:smburl="
1489 : "smb://user:password@server missing\n");
1490 : }
1491 :
1492 4 : ok = torture_libsmbclient_init_context(tctx, &ctx);
1493 4 : torture_assert(tctx, ok, "Failed to init context");
1494 4 : smbc_set_context(ctx);
1495 :
1496 4 : getxattr_name = talloc_asprintf(tctx,
1497 : "%s/getxattr",
1498 : smburl);
1499 4 : if (getxattr_name == NULL) {
1500 0 : torture_result(tctx,
1501 : TORTURE_FAIL,
1502 : __location__": %s",
1503 : "talloc fail\n");
1504 0 : return false;
1505 : }
1506 : /* Ensure the file doesn't exist. */
1507 4 : smbc_unlink(getxattr_name);
1508 :
1509 : /* Create testfile. */
1510 4 : fhandle = smbc_creat(getxattr_name, 0666);
1511 4 : if (fhandle < 0) {
1512 0 : torture_fail_goto(tctx,
1513 : done,
1514 : talloc_asprintf(tctx,
1515 : "failed to create file '%s': %s",
1516 : getxattr_name,
1517 : strerror(errno)));
1518 : }
1519 4 : ret = smbc_close(fhandle);
1520 4 : torture_assert_int_equal_goto(tctx,
1521 : ret,
1522 : 0,
1523 : ok,
1524 : done,
1525 : talloc_asprintf(tctx,
1526 : "failed to close handle for '%s'",
1527 : getxattr_name));
1528 :
1529 : /*
1530 : * Ensure getting a non-existent attribute returns -1.
1531 : */
1532 4 : ret = smbc_getxattr(getxattr_name, "foobar", value, sizeof(value));
1533 4 : torture_assert_int_equal_goto(tctx,
1534 : ret,
1535 : -1,
1536 : ok,
1537 : done,
1538 : talloc_asprintf(tctx,
1539 : "smbc_getxattr(foobar) on '%s' should "
1540 : "get -1, got %d\n",
1541 : getxattr_name,
1542 : ret));
1543 :
1544 : /*
1545 : * Ensure getting a valid attribute computes its size.
1546 : */
1547 4 : ret = smbc_getxattr(getxattr_name, "system.*", NULL, 0);
1548 4 : torture_assert_goto(tctx,
1549 : ret >= 0,
1550 : ok,
1551 : done,
1552 : talloc_asprintf(tctx,
1553 : "smbc_getxattr(foobar, NULL) on '%s' should "
1554 : "get >=0, got %d\n",
1555 : getxattr_name,
1556 : ret));
1557 :
1558 : /*
1559 : * Ensure getting a valid attribute returns its size.
1560 : */
1561 4 : ret = smbc_getxattr(getxattr_name, "system.*", value, sizeof(value));
1562 4 : torture_assert_goto(tctx,
1563 : ret >= 0,
1564 : ok,
1565 : done,
1566 : talloc_asprintf(tctx,
1567 : "smbc_getxattr(foobar, value) on '%s' should "
1568 : "get >=0, got %d\n",
1569 : getxattr_name,
1570 : ret));
1571 :
1572 4 : ok = true;
1573 :
1574 4 : done:
1575 :
1576 4 : smbc_unlink(getxattr_name);
1577 4 : smbc_free_context(ctx, 1);
1578 4 : return ok;
1579 : }
1580 :
1581 2354 : NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx)
1582 : {
1583 125 : struct torture_suite *suite;
1584 :
1585 2354 : suite = torture_suite_create(ctx, "libsmbclient");
1586 :
1587 2354 : torture_suite_add_simple_test(suite, "version", torture_libsmbclient_version);
1588 2354 : torture_suite_add_simple_test(suite, "initialize", torture_libsmbclient_initialize);
1589 2354 : torture_suite_add_simple_test(suite, "configuration", torture_libsmbclient_configuration);
1590 2354 : torture_suite_add_simple_test(suite, "setConfiguration", torture_libsmbclient_setConfiguration);
1591 2354 : torture_suite_add_simple_test(suite, "options", torture_libsmbclient_options);
1592 2354 : torture_suite_add_simple_test(suite, "opendir", torture_libsmbclient_opendir);
1593 2354 : torture_suite_add_simple_test(suite, "list_shares", torture_libsmbclient_list_shares);
1594 2354 : torture_suite_add_simple_test(suite, "readdirplus",
1595 : torture_libsmbclient_readdirplus);
1596 2354 : torture_suite_add_simple_test(suite, "readdirplus_seek",
1597 : torture_libsmbclient_readdirplus_seek);
1598 2354 : torture_suite_add_simple_test(suite, "readdirplus2",
1599 : torture_libsmbclient_readdirplus2);
1600 2354 : torture_suite_add_simple_test(
1601 : suite, "utimes", torture_libsmbclient_utimes);
1602 2354 : torture_suite_add_simple_test(
1603 : suite, "noanon_list", torture_libsmbclient_noanon_list);
1604 2354 : torture_suite_add_simple_test(suite,
1605 : "rename",
1606 : torture_libsmbclient_rename);
1607 2354 : torture_suite_add_simple_test(suite, "getatr",
1608 : torture_libsmbclient_getatr);
1609 2354 : torture_suite_add_simple_test(suite, "getxattr",
1610 : torture_libsmbclient_getxattr);
1611 :
1612 2354 : suite->description = talloc_strdup(suite, "libsmbclient interface tests");
1613 :
1614 2354 : torture_register_suite(ctx, suite);
1615 :
1616 2354 : return NT_STATUS_OK;
1617 : }
|