00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023 static fstring password;
00024 static fstring username;
00025 static int got_pass;
00026 static int max_protocol = PROTOCOL_NT1;
00027 static BOOL showall = False;
00028 static BOOL old_list = False;
00029 static const char *maskchars = "<>\"?*abc.";
00030 static const char *filechars = "abcdefghijklm.";
00031 static int verbose;
00032 static int die_on_error;
00033 static int NumLoops = 0;
00034 static int ignore_dot_errors = 0;
00035
00036 extern char *optarg;
00037 extern int optind;
00038 extern BOOL AllowDebugChange;
00039
00040
00041 static int ms_fnmatch_lanman_core(const char *pattern, const char *string)
00042 {
00043 const char *p = pattern, *n = string;
00044 char c;
00045
00046 if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match;
00047
00048 while ((c = *p++)) {
00049 switch (c) {
00050 case '.':
00051
00052 if (*n != '.') goto nomatch;
00053 n++;
00054 break;
00055
00056 case '?':
00057 if ((*n == '.' && n[1] != '.') || ! *n) goto next;
00058 n++;
00059 break;
00060
00061 case '>':
00062 if (n[0] == '.') {
00063 if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match;
00064 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00065 goto nomatch;
00066 }
00067 if (! *n) goto next;
00068 n++;
00069 break;
00070
00071 case '*':
00072 if (! *p) goto match;
00073 for (; *n; n++) {
00074 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00075 }
00076 break;
00077
00078 case '<':
00079 for (; *n; n++) {
00080 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00081 if (*n == '.' && !strchr_m(n+1,'.')) {
00082 n++;
00083 break;
00084 }
00085 }
00086 break;
00087
00088 case '"':
00089 if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match;
00090 if (*n != '.') goto nomatch;
00091 n++;
00092 break;
00093
00094 default:
00095 if (c != *n) goto nomatch;
00096 n++;
00097 }
00098 }
00099
00100 if (! *n) goto match;
00101
00102 nomatch:
00103 if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string);
00104 return -1;
00105
00106 next:
00107 if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
00108 goto nomatch;
00109
00110 match:
00111 if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string);
00112 return 0;
00113 }
00114
00115 static int ms_fnmatch_lanman(const char *pattern, const char *string)
00116 {
00117 if (!strpbrk(pattern, "?*<>\"")) {
00118 if (strcmp(string,"..") == 0)
00119 string = ".";
00120
00121 return strcmp(pattern, string);
00122 }
00123
00124 if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) {
00125 return ms_fnmatch_lanman_core(pattern, "..") &&
00126 ms_fnmatch_lanman_core(pattern, ".");
00127 }
00128
00129 return ms_fnmatch_lanman_core(pattern, string);
00130 }
00131
00132 static BOOL reg_match_one(struct cli_state *cli, const char *pattern, const char *file)
00133 {
00134
00135 if (old_list && strcmp(pattern, "*.*") == 0) return True;
00136
00137 if (strcmp(pattern,".") == 0) return False;
00138
00139 if (max_protocol <= PROTOCOL_LANMAN2) {
00140 return ms_fnmatch_lanman(pattern, file)==0;
00141 }
00142
00143 if (strcmp(file,"..") == 0) file = ".";
00144
00145 return ms_fnmatch(pattern, file, cli->protocol, False) == 0;
00146 }
00147
00148 static char *reg_test(struct cli_state *cli, char *pattern, char *long_name, char *short_name)
00149 {
00150 static fstring ret;
00151 fstrcpy(ret, "---");
00152
00153 pattern = 1+strrchr_m(pattern,'\\');
00154
00155 if (reg_match_one(cli, pattern, ".")) ret[0] = '+';
00156 if (reg_match_one(cli, pattern, "..")) ret[1] = '+';
00157 if (reg_match_one(cli, pattern, long_name) ||
00158 (*short_name && reg_match_one(cli, pattern, short_name))) ret[2] = '+';
00159 return ret;
00160 }
00161
00162
00163
00164
00165
00166 static struct cli_state *connect_one(char *share)
00167 {
00168 struct cli_state *c;
00169 struct nmb_name called, calling;
00170 char *server_n;
00171 char *server;
00172 struct in_addr ip;
00173 NTSTATUS status;
00174
00175 server = share+2;
00176 share = strchr_m(server,'\\');
00177 if (!share) return NULL;
00178 *share = 0;
00179 share++;
00180
00181 server_n = server;
00182
00183 zero_ip(&ip);
00184
00185 make_nmb_name(&calling, "masktest", 0x0);
00186 make_nmb_name(&called , server, 0x20);
00187
00188 again:
00189 zero_ip(&ip);
00190
00191
00192 if (!(c=cli_initialise())) {
00193 DEBUG(0,("Connection to %s failed\n", server_n));
00194 return NULL;
00195 }
00196
00197 status = cli_connect(c, server_n, &ip);
00198 if (!NT_STATUS_IS_OK(status)) {
00199 DEBUG(0,("Connection to %s failed. Error %s\n", server_n, nt_errstr(status) ));
00200 return NULL;
00201 }
00202
00203 c->protocol = max_protocol;
00204
00205 if (!cli_session_request(c, &calling, &called)) {
00206 DEBUG(0,("session request to %s failed\n", called.name));
00207 cli_shutdown(c);
00208 if (strcmp(called.name, "*SMBSERVER")) {
00209 make_nmb_name(&called , "*SMBSERVER", 0x20);
00210 goto again;
00211 }
00212 return NULL;
00213 }
00214
00215 DEBUG(4,(" session request ok\n"));
00216
00217 if (!cli_negprot(c)) {
00218 DEBUG(0,("protocol negotiation failed\n"));
00219 cli_shutdown(c);
00220 return NULL;
00221 }
00222
00223 if (!got_pass) {
00224 char *pass = getpass("Password: ");
00225 if (pass) {
00226 fstrcpy(password, pass);
00227 }
00228 }
00229
00230 if (!NT_STATUS_IS_OK(cli_session_setup(c, username,
00231 password, strlen(password),
00232 password, strlen(password),
00233 lp_workgroup()))) {
00234 DEBUG(0,("session setup failed: %s\n", cli_errstr(c)));
00235 return NULL;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 if (*c->server_domain || *c->server_os || *c->server_type)
00247 DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
00248 c->server_domain,c->server_os,c->server_type));
00249
00250 DEBUG(4,(" session setup ok\n"));
00251
00252 if (!cli_send_tconX(c, share, "?????",
00253 password, strlen(password)+1)) {
00254 DEBUG(0,("tree connect failed: %s\n", cli_errstr(c)));
00255 cli_shutdown(c);
00256 return NULL;
00257 }
00258
00259 DEBUG(4,(" tconx ok\n"));
00260
00261 return c;
00262 }
00263
00264 static char *resultp;
00265 static file_info *f_info;
00266
00267 static void listfn(const char *mnt, file_info *f, const char *s, void *state)
00268 {
00269 if (strcmp(f->name,".") == 0) {
00270 resultp[0] = '+';
00271 } else if (strcmp(f->name,"..") == 0) {
00272 resultp[1] = '+';
00273 } else {
00274 resultp[2] = '+';
00275 }
00276 f_info = f;
00277 }
00278
00279 static void get_real_name(struct cli_state *cli,
00280 pstring long_name, fstring short_name)
00281 {
00282
00283 cli->capabilities |= CAP_NT_SMBS;
00284 if (max_protocol <= PROTOCOL_LANMAN1) {
00285 cli_list_new(cli, "\\masktest\\*.*", aHIDDEN | aDIR, listfn, NULL);
00286 } else {
00287 cli_list_new(cli, "\\masktest\\*", aHIDDEN | aDIR, listfn, NULL);
00288 }
00289 if (f_info) {
00290 fstrcpy(short_name, f_info->short_name);
00291 strlower_m(short_name);
00292 pstrcpy(long_name, f_info->name);
00293 strlower_m(long_name);
00294 }
00295
00296 if (*short_name == 0) {
00297 fstrcpy(short_name, long_name);
00298 }
00299
00300 #if 0
00301 if (!strchr_m(short_name,'.')) {
00302 fstrcat(short_name,".");
00303 }
00304 #endif
00305 }
00306
00307 static void testpair(struct cli_state *cli, char *mask, char *file)
00308 {
00309 int fnum;
00310 fstring res1;
00311 char *res2;
00312 static int count;
00313 fstring short_name;
00314 pstring long_name;
00315
00316 count++;
00317
00318 fstrcpy(res1, "---");
00319
00320 fnum = cli_open(cli, file, O_CREAT|O_TRUNC|O_RDWR, 0);
00321 if (fnum == -1) {
00322 DEBUG(0,("Can't create %s\n", file));
00323 return;
00324 }
00325 cli_close(cli, fnum);
00326
00327 resultp = res1;
00328 fstrcpy(short_name, "");
00329 f_info = NULL;
00330 get_real_name(cli, long_name, short_name);
00331 f_info = NULL;
00332 fstrcpy(res1, "---");
00333 cli_list(cli, mask, aHIDDEN | aDIR, listfn, NULL);
00334
00335 res2 = reg_test(cli, mask, long_name, short_name);
00336
00337 if (showall ||
00338 ((strcmp(res1, res2) && !ignore_dot_errors) ||
00339 (strcmp(res1+2, res2+2) && ignore_dot_errors))) {
00340 DEBUG(0,("%s %s %d mask=[%s] file=[%s] rfile=[%s/%s]\n",
00341 res1, res2, count, mask, file, long_name, short_name));
00342 if (die_on_error) exit(1);
00343 }
00344
00345 cli_unlink(cli, file);
00346
00347 if (count % 100 == 0) DEBUG(0,("%d\n", count));
00348 }
00349
00350 static void test_mask(int argc, char *argv[],
00351 struct cli_state *cli)
00352 {
00353 pstring mask, file;
00354 int l1, l2, i, l;
00355 int mc_len = strlen(maskchars);
00356 int fc_len = strlen(filechars);
00357
00358 cli_mkdir(cli, "\\masktest");
00359
00360 cli_unlink(cli, "\\masktest\\*");
00361
00362 if (argc >= 2) {
00363 while (argc >= 2) {
00364 pstrcpy(mask,"\\masktest\\");
00365 pstrcpy(file,"\\masktest\\");
00366 pstrcat(mask, argv[0]);
00367 pstrcat(file, argv[1]);
00368 testpair(cli, mask, file);
00369 argv += 2;
00370 argc -= 2;
00371 }
00372 goto finished;
00373 }
00374
00375 while (1) {
00376 l1 = 1 + random() % 20;
00377 l2 = 1 + random() % 20;
00378 pstrcpy(mask,"\\masktest\\");
00379 pstrcpy(file,"\\masktest\\");
00380 l = strlen(mask);
00381 for (i=0;i<l1;i++) {
00382 mask[i+l] = maskchars[random() % mc_len];
00383 }
00384 mask[l+l1] = 0;
00385
00386 for (i=0;i<l2;i++) {
00387 file[i+l] = filechars[random() % fc_len];
00388 }
00389 file[l+l2] = 0;
00390
00391 if (strcmp(file+l,".") == 0 ||
00392 strcmp(file+l,"..") == 0 ||
00393 strcmp(mask+l,"..") == 0) continue;
00394
00395 if (strspn(file+l, ".") == strlen(file+l)) continue;
00396
00397 testpair(cli, mask, file);
00398 if (NumLoops && (--NumLoops == 0))
00399 break;
00400 }
00401
00402 finished:
00403 cli_rmdir(cli, "\\masktest");
00404 }
00405
00406
00407 static void usage(void)
00408 {
00409 printf(
00410 "Usage:\n\
00411 masktest //server/share [options..]\n\
00412 options:\n\
00413 -d debuglevel\n\
00414 -n numloops\n\
00415 -W workgroup\n\
00416 -U user%%pass\n\
00417 -s seed\n\
00418 -M max protocol\n\
00419 -f filechars (default %s)\n\
00420 -m maskchars (default %s)\n\
00421 -v verbose mode\n\
00422 -E die on error\n\
00423 -a show all tests\n\
00424 -i ignore . and .. errors\n\
00425 \n\
00426 This program tests wildcard matching between two servers. It generates\n\
00427 random pairs of filenames/masks and tests that they match in the same\n\
00428 way on the servers and internally\n\
00429 ",
00430 filechars, maskchars);
00431 }
00432
00433
00434
00435
00436 int main(int argc,char *argv[])
00437 {
00438 char *share;
00439 struct cli_state *cli;
00440 int opt;
00441 char *p;
00442 int seed;
00443
00444 setlinebuf(stdout);
00445
00446 dbf = x_stderr;
00447
00448 DEBUGLEVEL = 0;
00449 AllowDebugChange = False;
00450
00451 if (argc < 2 || argv[1][0] == '-') {
00452 usage();
00453 exit(1);
00454 }
00455
00456 share = argv[1];
00457
00458 all_string_sub(share,"/","\\",0);
00459
00460 setup_logging(argv[0],True);
00461
00462 argc -= 1;
00463 argv += 1;
00464
00465 lp_load(dyn_CONFIGFILE,True,False,False,True);
00466 load_interfaces();
00467
00468 if (getenv("USER")) {
00469 fstrcpy(username,getenv("USER"));
00470 }
00471
00472 seed = time(NULL);
00473
00474 while ((opt = getopt(argc, argv, "n:d:U:s:hm:f:aoW:M:vEi")) != EOF) {
00475 switch (opt) {
00476 case 'n':
00477 NumLoops = atoi(optarg);
00478 break;
00479 case 'd':
00480 DEBUGLEVEL = atoi(optarg);
00481 break;
00482 case 'E':
00483 die_on_error = 1;
00484 break;
00485 case 'i':
00486 ignore_dot_errors = 1;
00487 break;
00488 case 'v':
00489 verbose++;
00490 break;
00491 case 'M':
00492 max_protocol = interpret_protocol(optarg, max_protocol);
00493 break;
00494 case 'U':
00495 fstrcpy(username,optarg);
00496 p = strchr_m(username,'%');
00497 if (p) {
00498 *p = 0;
00499 fstrcpy(password, p+1);
00500 got_pass = 1;
00501 }
00502 break;
00503 case 's':
00504 seed = atoi(optarg);
00505 break;
00506 case 'h':
00507 usage();
00508 exit(1);
00509 case 'm':
00510 maskchars = optarg;
00511 break;
00512 case 'f':
00513 filechars = optarg;
00514 break;
00515 case 'a':
00516 showall = 1;
00517 break;
00518 case 'o':
00519 old_list = True;
00520 break;
00521 default:
00522 printf("Unknown option %c (%d)\n", (char)opt, opt);
00523 exit(1);
00524 }
00525 }
00526
00527 argc -= optind;
00528 argv += optind;
00529
00530
00531 cli = connect_one(share);
00532 if (!cli) {
00533 DEBUG(0,("Failed to connect to %s\n", share));
00534 exit(1);
00535 }
00536
00537
00538 DEBUG(0,("seed=%d\n", seed));
00539 srandom(seed);
00540
00541 test_mask(argc, argv, cli);
00542
00543 return(0);
00544 }