LCOV - code coverage report
Current view: top level - source4/torture/libsmbclient - libsmbclient.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 533 600 88.8 %
Date: 2024-02-28 12:06:22 Functions: 20 20 100.0 %

          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          15 : 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          15 :                 cli_credentials_get_domain(samba_cmdline_get_creds());
      54           0 :         const char *username =
      55          15 :                 cli_credentials_get_username(samba_cmdline_get_creds());
      56           0 :         const char *password =
      57          15 :                 cli_credentials_get_password(samba_cmdline_get_creds());
      58           0 :         ssize_t ret;
      59             : 
      60          15 :         if (workgroup != NULL) {
      61          15 :                 ret = strlcpy(wg, workgroup, wglen);
      62          15 :                 if (ret >= wglen) {
      63           0 :                         abort();
      64             :                 }
      65             :         }
      66             : 
      67          15 :         if (username != NULL) {
      68          15 :                 ret = strlcpy(un, username, unlen);
      69          15 :                 if (ret >= unlen) {
      70           0 :                         abort();
      71             :                 }
      72             :         }
      73             : 
      74          15 :         if (password != NULL) {
      75          15 :                 ret = strlcpy(pw, password, pwlen);
      76          15 :                 if (ret >= pwlen) {
      77           0 :                         abort();
      78             :                 }
      79             :         }
      80          15 : };
      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         119 :         for (;;) {
     360           0 :                 const struct libsmb_file_info *exstat =
     361         123 :                         smbc_readdirplus(dhandle);
     362         123 :                 if (exstat == NULL) {
     363           0 :                         break;
     364             :                 }
     365         123 :                 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         119 :         for (;;) {
     885           0 :                 const struct libsmb_file_info *exstat =
     886         123 :                         smbc_readdirplus2(dhandle, &st2);
     887         123 :                 if (exstat == NULL) {
     888           0 :                         break;
     889             :                 }
     890             : 
     891         123 :                 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        2379 : NTSTATUS torture_libsmbclient_init(TALLOC_CTX *ctx)
    1582             : {
    1583         125 :         struct torture_suite *suite;
    1584             : 
    1585        2379 :         suite = torture_suite_create(ctx, "libsmbclient");
    1586             : 
    1587        2379 :         torture_suite_add_simple_test(suite, "version", torture_libsmbclient_version);
    1588        2379 :         torture_suite_add_simple_test(suite, "initialize", torture_libsmbclient_initialize);
    1589        2379 :         torture_suite_add_simple_test(suite, "configuration", torture_libsmbclient_configuration);
    1590        2379 :         torture_suite_add_simple_test(suite, "setConfiguration", torture_libsmbclient_setConfiguration);
    1591        2379 :         torture_suite_add_simple_test(suite, "options", torture_libsmbclient_options);
    1592        2379 :         torture_suite_add_simple_test(suite, "opendir", torture_libsmbclient_opendir);
    1593        2379 :         torture_suite_add_simple_test(suite, "list_shares", torture_libsmbclient_list_shares);
    1594        2379 :         torture_suite_add_simple_test(suite, "readdirplus",
    1595             :                 torture_libsmbclient_readdirplus);
    1596        2379 :         torture_suite_add_simple_test(suite, "readdirplus_seek",
    1597             :                 torture_libsmbclient_readdirplus_seek);
    1598        2379 :         torture_suite_add_simple_test(suite, "readdirplus2",
    1599             :                 torture_libsmbclient_readdirplus2);
    1600        2379 :         torture_suite_add_simple_test(
    1601             :                 suite, "utimes", torture_libsmbclient_utimes);
    1602        2379 :         torture_suite_add_simple_test(
    1603             :                 suite, "noanon_list", torture_libsmbclient_noanon_list);
    1604        2379 :         torture_suite_add_simple_test(suite,
    1605             :                                         "rename",
    1606             :                                         torture_libsmbclient_rename);
    1607        2379 :         torture_suite_add_simple_test(suite, "getatr",
    1608             :                 torture_libsmbclient_getatr);
    1609        2379 :         torture_suite_add_simple_test(suite, "getxattr",
    1610             :                 torture_libsmbclient_getxattr);
    1611             : 
    1612        2379 :         suite->description = talloc_strdup(suite, "libsmbclient interface tests");
    1613             : 
    1614        2379 :         torture_register_suite(ctx, suite);
    1615             : 
    1616        2379 :         return NT_STATUS_OK;
    1617             : }

Generated by: LCOV version 1.14