LCOV - code coverage report
Current view: top level - source4/torture - masktest.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 135 175 77.1 %
Date: 2024-05-31 13:13:24 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    mask_match tester
       4             :    Copyright (C) Andrew Tridgell 1999
       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 "lib/cmdline/cmdline.h"
      22             : #include "system/filesys.h"
      23             : #include "system/dir.h"
      24             : #include "libcli/libcli.h"
      25             : #include "system/time.h"
      26             : #include "auth/credentials/credentials.h"
      27             : #include "auth/gensec/gensec.h"
      28             : #include "param/param.h"
      29             : #include "libcli/resolve/resolve.h"
      30             : #include "lib/events/events.h"
      31             : 
      32             : static bool showall = false;
      33             : static bool old_list = false;
      34             : static const char *maskchars = "<>\"?*abc.";
      35             : static const char *filechars = "abcdefghijklm.";
      36             : static int die_on_error;
      37             : static int NumLoops = 0;
      38             : static int max_length = 20;
      39             : struct masktest_state {
      40             :         TALLOC_CTX *mem_ctx;
      41             : };
      42             : 
      43         789 : static bool reg_match_one(struct smbcli_state *cli, const char *pattern, const char *file)
      44             : {
      45             :         /* oh what a weird world this is */
      46         789 :         if (old_list && strcmp(pattern, "*.*") == 0) return true;
      47             : 
      48         789 :         if (ISDOT(pattern)) return false;
      49             : 
      50         785 :         if (ISDOTDOT(file)) file = ".";
      51             : 
      52         785 :         return ms_fnmatch_protocol(
      53         785 :                 pattern, file, cli->transport->negotiate.protocol, false)==0;
      54             : }
      55             : 
      56         200 : static char *reg_test(struct smbcli_state *cli, TALLOC_CTX *mem_ctx, const char *pattern, const char *long_name, const char *short_name)
      57             : {
      58             :         char *ret;
      59         200 :         ret = talloc_strdup(mem_ctx, "---");
      60             : 
      61         200 :         pattern = 1+strrchr_m(pattern,'\\');
      62             : 
      63         200 :         if (reg_match_one(cli, pattern, ".")) ret[0] = '+';
      64         200 :         if (reg_match_one(cli, pattern, "..")) ret[1] = '+';
      65         200 :         if (reg_match_one(cli, pattern, long_name) || 
      66         200 :             (*short_name && reg_match_one(cli, pattern, short_name))) ret[2] = '+';
      67         200 :         return ret;
      68             : }
      69             : 
      70             : 
      71             : /***************************************************** 
      72             : return a connection to a server
      73             : *******************************************************/
      74           1 : static struct smbcli_state *connect_one(struct resolve_context *resolve_ctx, 
      75             :                                         struct tevent_context *ev,
      76             :                                         TALLOC_CTX *mem_ctx,
      77             :                                         char *share, const char **ports,
      78             :                                         const char *socket_options,
      79             :                                         struct smbcli_options *options,
      80             :                                         struct smbcli_session_options *session_options,
      81             :                                         struct gensec_settings *gensec_settings)
      82             : {
      83             :         struct smbcli_state *c;
      84             :         char *server;
      85             :         NTSTATUS status;
      86           1 :         struct cli_credentials *creds = samba_cmdline_get_creds();
      87             : 
      88           1 :         server = talloc_strdup(mem_ctx, share+2);
      89           1 :         share = strchr_m(server,'\\');
      90           1 :         if (!share) return NULL;
      91           1 :         *share = 0;
      92           1 :         share++;
      93             : 
      94           1 :         cli_credentials_set_workstation(creds,
      95             :                         "masktest", CRED_SPECIFIED);
      96             : 
      97           1 :         status = smbcli_full_connection(NULL, &c,
      98             :                                         server, 
      99             :                                         ports,
     100             :                                         share, NULL,
     101             :                                         socket_options,
     102             :                                         creds,
     103             :                                         resolve_ctx, ev,
     104             :                                         options, session_options,
     105             :                                         gensec_settings);
     106             : 
     107           1 :         if (!NT_STATUS_IS_OK(status)) {
     108           0 :                 return NULL;
     109             :         }
     110             : 
     111           1 :         return c;
     112             : }
     113             : 
     114             : static char *resultp;
     115             : static struct {
     116             :         char *long_name;
     117             :         char *short_name;
     118             : } last_hit;
     119             : static bool f_info_hit;
     120             : 
     121         638 : static void listfn(struct clilist_file_info *f, const char *s, void *state)
     122             : {
     123         638 :         struct masktest_state *m = (struct masktest_state *)state;
     124             : 
     125         638 :         if (ISDOT(f->name)) {
     126         213 :                 resultp[0] = '+';
     127         425 :         } else if (ISDOTDOT(f->name)) {
     128         213 :                 resultp[1] = '+';
     129             :         } else {
     130         212 :                 resultp[2] = '+';
     131             :         }
     132             : 
     133         638 :         last_hit.long_name = talloc_strdup(m->mem_ctx, f->name);
     134         638 :         last_hit.short_name = talloc_strdup(m->mem_ctx, f->short_name);
     135         638 :         f_info_hit = true;
     136         638 : }
     137             : 
     138         200 : static void get_real_name(TALLOC_CTX *mem_ctx, struct smbcli_state *cli,
     139             :                           char **long_name, char **short_name)
     140             : {
     141             :         const char *mask;
     142             :         struct masktest_state state;
     143             : 
     144         200 :         if (cli->transport->negotiate.protocol <= PROTOCOL_LANMAN1) {
     145           0 :                 mask = "\\masktest\\*.*";
     146             :         } else {
     147         200 :                 mask = "\\masktest\\*";
     148             :         }
     149             : 
     150         200 :         f_info_hit = false;
     151             : 
     152         200 :         state.mem_ctx = mem_ctx;
     153             : 
     154         200 :         smbcli_list_new(cli->tree, mask,
     155             :                         FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,
     156             :                         RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
     157             :                         listfn, &state);
     158             : 
     159         200 :         if (f_info_hit) {
     160         200 :                 *short_name = strlower_talloc(mem_ctx, last_hit.short_name);
     161         200 :                 *long_name = strlower_talloc(mem_ctx, last_hit.long_name);
     162             :         }
     163             : 
     164         200 :         if (*short_name[0] == '\0') {
     165           0 :                 *short_name = talloc_strdup(mem_ctx, *long_name);
     166             :         }
     167         200 : }
     168             : 
     169         200 : static void testpair(TALLOC_CTX *mem_ctx, struct smbcli_state *cli, char *mask,
     170             :                 char *file)
     171             : {
     172             :         int fnum;
     173             :         char res1[256];
     174             :         char *res2;
     175             :         static int count;
     176         200 :         char *short_name = NULL;
     177         200 :         char *long_name = NULL;
     178             :         struct masktest_state state;
     179             : 
     180         200 :         count++;
     181             : 
     182         200 :         strlcpy(res1, "---", sizeof(res1));
     183             : 
     184         200 :         state.mem_ctx = mem_ctx;
     185             : 
     186         200 :         fnum = smbcli_open(cli->tree, file, O_CREAT|O_TRUNC|O_RDWR, 0);
     187         200 :         if (fnum == -1) {
     188           0 :                 DEBUG(0,("Can't create %s\n", file));
     189           0 :                 return;
     190             :         }
     191         200 :         smbcli_close(cli->tree, fnum);
     192             : 
     193         200 :         resultp = res1;
     194         200 :         short_name = talloc_strdup(mem_ctx, "");
     195         200 :         get_real_name(mem_ctx, cli, &long_name, &short_name);
     196         200 :         strlcpy(res1, "---", sizeof(res1));
     197         200 :         smbcli_list_new(cli->tree, mask,
     198             :                         FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY,
     199             :                         RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
     200             :                         listfn, &state);
     201             : 
     202         200 :         res2 = reg_test(cli, mem_ctx, mask, long_name, short_name);
     203             : 
     204         200 :         if (showall || strcmp(res1, res2)) {
     205           0 :                 d_printf("%s %s %d mask=[%s] file=[%s] rfile=[%s/%s]\n",
     206             :                          res1, res2, count, mask, file, long_name, short_name);
     207           0 :                 if (die_on_error) exit(1);
     208             :         }
     209             : 
     210         200 :         smbcli_unlink(cli->tree, file);
     211             : 
     212         200 :         if (count % 100 == 0) DEBUG(0,("%d\n", count));
     213             : 
     214         200 :         resultp = NULL;
     215             : }
     216             : 
     217           1 : static void test_mask(int argc, char *argv[],
     218             :                                           TALLOC_CTX *mem_ctx,
     219             :                       struct smbcli_state *cli)
     220             : {
     221             :         char *mask, *file;
     222             :         int l1, l2, i, l;
     223           1 :         int mc_len = strlen(maskchars);
     224           1 :         int fc_len = strlen(filechars);
     225             : 
     226           1 :         smbcli_mkdir(cli->tree, "\\masktest");
     227             : 
     228           1 :         smbcli_unlink_wcard(cli->tree, "\\masktest\\*");
     229             : 
     230           1 :         if (argc >= 2) {
     231           0 :                 while (argc >= 2) {
     232           0 :                         mask = talloc_strdup(mem_ctx, "\\masktest\\");
     233           0 :                         file = talloc_strdup(mem_ctx, "\\masktest\\");
     234           0 :                         mask = talloc_strdup_append(mask, argv[0]);
     235           0 :                         file = talloc_strdup_append(file, argv[1]);
     236           0 :                         testpair(mem_ctx, cli, mask, file);
     237           0 :                         argv += 2;
     238           0 :                         argc -= 2;
     239             :                 }
     240           0 :                 goto finished;
     241             :         }
     242             : 
     243             :         while (1) {
     244         202 :                 l1 = 1 + random() % max_length;
     245         202 :                 l2 = 1 + random() % max_length;
     246         202 :                 mask = talloc_strdup(mem_ctx, "\\masktest\\");
     247         202 :                 file = talloc_strdup(mem_ctx, "\\masktest\\");
     248         202 :                 mask = talloc_realloc_size(mem_ctx, mask, strlen(mask)+l1+1);
     249         202 :                 file = talloc_realloc_size(mem_ctx, file, strlen(file)+l2+1);
     250         202 :                 l = strlen(mask);
     251        2212 :                 for (i=0;i<l1;i++) {
     252        2010 :                         mask[i+l] = maskchars[random() % mc_len];
     253             :                 }
     254         202 :                 mask[l+l1] = 0;
     255             : 
     256        2326 :                 for (i=0;i<l2;i++) {
     257        2124 :                         file[i+l] = filechars[random() % fc_len];
     258             :                 }
     259         202 :                 file[l+l2] = 0;
     260             : 
     261         202 :                 if (ISDOT(file+l) || ISDOTDOT(file+l) || ISDOTDOT(mask+l)) {
     262           2 :                         continue;
     263             :                 }
     264             : 
     265         200 :                 if (strspn(file+l, ".") == strlen(file+l)) continue;
     266             : 
     267         200 :                 testpair(mem_ctx, cli, mask, file);
     268         200 :                 if (NumLoops && (--NumLoops == 0))
     269           1 :                         break;
     270             :         }
     271             : 
     272           1 :  finished:
     273           1 :         smbcli_rmdir(cli->tree, "\\masktest");
     274           1 : }
     275             : 
     276             : 
     277           0 : static void usage(poptContext pc)
     278             : {
     279           0 :         printf(
     280             : "Usage:\n\
     281             :   masktest //server/share [options..]\n\
     282             : \n\
     283             :   This program tests wildcard matching between two servers. It generates\n\
     284             :   random pairs of filenames/masks and tests that they match in the same\n\
     285             :   way on the servers and internally\n");
     286           0 :         poptPrintUsage(pc, stdout, 0);
     287           0 : }
     288             : 
     289             : /****************************************************************************
     290             :   main program
     291             : ****************************************************************************/
     292           1 : int main(int argc, const char *argv[])
     293             : {
     294             :         char *share;
     295             :         struct smbcli_state *cli;       
     296             :         int opt;
     297             :         int seed;
     298             :         struct tevent_context *ev;
     299             :         struct loadparm_context *lp_ctx;
     300             :         struct smbcli_options options;
     301             :         struct smbcli_session_options session_options;
     302             :         poptContext pc;
     303             :         int argc_new, i;
     304             :         char **argv_new;
     305           1 :         TALLOC_CTX *mem_ctx = NULL;
     306             :         enum {OPT_UNCLIST=1000};
     307           6 :         struct poptOption long_options[] = {
     308             :                 POPT_AUTOHELP
     309             :                 {"seed",        0, POPT_ARG_INT,  &seed,  0,      "Seed to use for randomizer",         NULL},
     310             :                 {"num-ops",     0, POPT_ARG_INT,  &NumLoops,      0,      "num ops",    NULL},
     311             :                 {"maxlength",   0, POPT_ARG_INT,  &max_length,0,  "maximum length",     NULL},
     312             :                 {"dieonerror",    0, POPT_ARG_NONE, &die_on_error, 0,   "die on errors", NULL},
     313             :                 {"showall",       0, POPT_ARG_NONE, &showall,    0,      "display all operations", NULL},
     314             :                 {"oldlist",       0, POPT_ARG_NONE, &old_list,    0,     "use old list call", NULL},
     315             :                 {"maskchars",   0, POPT_ARG_STRING,   &maskchars,    0,"mask characters",       NULL},
     316             :                 {"filechars",   0, POPT_ARG_STRING,   &filechars,    0,"file characters",       NULL},
     317           1 :                 POPT_COMMON_SAMBA
     318           1 :                 POPT_COMMON_CONNECTION
     319           1 :                 POPT_COMMON_CREDENTIALS
     320           1 :                 POPT_COMMON_VERSION
     321           1 :                 POPT_LEGACY_S4
     322             :                 POPT_TABLEEND
     323             :         };
     324             :         bool ok;
     325             : 
     326           1 :         setlinebuf(stdout);
     327           1 :         seed = time(NULL);
     328             : 
     329           1 :         mem_ctx = talloc_named_const(NULL, 0, "masktest_ctx");
     330           1 :         if (mem_ctx == NULL) {
     331           0 :                 exit(1);
     332             :         }
     333             : 
     334           1 :         ok = samba_cmdline_init(mem_ctx,
     335             :                                 SAMBA_CMDLINE_CONFIG_CLIENT,
     336             :                                 false /* require_smbconf */);
     337           1 :         if (!ok) {
     338           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
     339           0 :                 exit(1);
     340             :         }
     341             : 
     342           1 :         pc = samba_popt_get_context(getprogname(),
     343             :                                     argc,
     344             :                                     argv,
     345             :                                     long_options,
     346             :                                     POPT_CONTEXT_KEEP_FIRST);
     347           1 :         if (pc == NULL) {
     348           0 :                 DBG_ERR("Failed to setup popt context!\n");
     349           0 :                 exit(1);
     350             :         }
     351             : 
     352           1 :         poptSetOtherOptionHelp(pc, "<unc>");
     353             : 
     354           1 :         lp_ctx = samba_cmdline_get_lp_ctx();
     355             : 
     356           1 :         while((opt = poptGetNextOpt(pc)) != -1) {
     357           0 :                 switch (opt) {
     358           0 :                 case OPT_UNCLIST:
     359           0 :                         lpcfg_set_cmdline(lp_ctx,
     360             :                                           "torture:unclist",
     361           0 :                                           poptGetOptArg(pc));
     362           0 :                         break;
     363           0 :                 case POPT_ERROR_BADOPT:
     364           0 :                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
     365             :                                 poptBadOption(pc, 0), poptStrerror(opt));
     366           0 :                         poptPrintUsage(pc, stderr, 0);
     367           0 :                         exit(1);
     368             :                 }
     369             :         }
     370             : 
     371           1 :         argv_new = discard_const_p(char *, poptGetArgs(pc));
     372           1 :         argc_new = argc;
     373           3 :         for (i=0; i<argc; i++) {
     374           3 :                 if (argv_new[i] == NULL) {
     375           1 :                         argc_new = i;
     376           1 :                         break;
     377             :                 }
     378             :         }
     379             : 
     380           1 :         if (!(argc_new >= 2)) {
     381           0 :                 usage(pc);
     382           0 :                 talloc_free(mem_ctx);
     383           0 :                 exit(1);
     384             :         }
     385             : 
     386           1 :         setup_logging("masktest", DEBUG_STDOUT);
     387             : 
     388           1 :         share = argv_new[1];
     389             : 
     390           1 :         all_string_sub(share,"/","\\",0);
     391             : 
     392           1 :         ev = s4_event_context_init(mem_ctx);
     393             : 
     394           1 :         gensec_init();
     395             : 
     396           1 :         lpcfg_smbcli_options(lp_ctx, &options);
     397           1 :         lpcfg_smbcli_session_options(lp_ctx, &session_options);
     398             : 
     399           1 :         cli = connect_one(lpcfg_resolve_context(lp_ctx), ev, mem_ctx, share,
     400             :                           lpcfg_smb_ports(lp_ctx), lpcfg_socket_options(lp_ctx),
     401             :                           &options, &session_options,
     402             :                           lpcfg_gensec_settings(mem_ctx, lp_ctx));
     403           1 :         if (!cli) {
     404           0 :                 DEBUG(0,("Failed to connect to %s\n", share));
     405           0 :                 talloc_free(mem_ctx);
     406           0 :                 exit(1);
     407             :         }
     408             : 
     409             :         /* need to init seed after connect as clientgen uses random numbers */
     410           1 :         DEBUG(0,("seed=%d     format --- --- (server, correct)\n", seed));
     411           1 :         srandom(seed);
     412             : 
     413           1 :         test_mask(argc_new-1, argv_new+1, mem_ctx, cli);
     414             : 
     415           1 :         poptFreeContext(pc);
     416           1 :         talloc_free(mem_ctx);
     417           1 :         return(0);
     418             : }

Generated by: LCOV version 1.14