PageRenderTime 23ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/release/src/router/samba3/source/torture/masktest.c

https://gitlab.com/envieidoc/tomato
C | 544 lines | 499 code | 23 blank | 22 comment | 35 complexity | 202a06afd81c20e6dd3da828c4939c71 MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. mask_match tester
  4. Copyright (C) Andrew Tridgell 1999
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include "includes.h"
  18. static fstring password;
  19. static fstring username;
  20. static int got_pass;
  21. static int max_protocol = PROTOCOL_NT1;
  22. static BOOL showall = False;
  23. static BOOL old_list = False;
  24. static const char *maskchars = "<>\"?*abc.";
  25. static const char *filechars = "abcdefghijklm.";
  26. static int verbose;
  27. static int die_on_error;
  28. static int NumLoops = 0;
  29. static int ignore_dot_errors = 0;
  30. extern char *optarg;
  31. extern int optind;
  32. extern BOOL AllowDebugChange;
  33. /* a test fn for LANMAN mask support */
  34. static int ms_fnmatch_lanman_core(const char *pattern, const char *string)
  35. {
  36. const char *p = pattern, *n = string;
  37. char c;
  38. if (strcmp(p,"?")==0 && strcmp(n,".")==0) goto match;
  39. while ((c = *p++)) {
  40. switch (c) {
  41. case '.':
  42. /* if (! *n && ! *p) goto match; */
  43. if (*n != '.') goto nomatch;
  44. n++;
  45. break;
  46. case '?':
  47. if ((*n == '.' && n[1] != '.') || ! *n) goto next;
  48. n++;
  49. break;
  50. case '>':
  51. if (n[0] == '.') {
  52. if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match;
  53. if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
  54. goto nomatch;
  55. }
  56. if (! *n) goto next;
  57. n++;
  58. break;
  59. case '*':
  60. if (! *p) goto match;
  61. for (; *n; n++) {
  62. if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
  63. }
  64. break;
  65. case '<':
  66. for (; *n; n++) {
  67. if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
  68. if (*n == '.' && !strchr_m(n+1,'.')) {
  69. n++;
  70. break;
  71. }
  72. }
  73. break;
  74. case '"':
  75. if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match;
  76. if (*n != '.') goto nomatch;
  77. n++;
  78. break;
  79. default:
  80. if (c != *n) goto nomatch;
  81. n++;
  82. }
  83. }
  84. if (! *n) goto match;
  85. nomatch:
  86. if (verbose) printf("NOMATCH pattern=[%s] string=[%s]\n", pattern, string);
  87. return -1;
  88. next:
  89. if (ms_fnmatch_lanman_core(p, n) == 0) goto match;
  90. goto nomatch;
  91. match:
  92. if (verbose) printf("MATCH pattern=[%s] string=[%s]\n", pattern, string);
  93. return 0;
  94. }
  95. static int ms_fnmatch_lanman(const char *pattern, const char *string)
  96. {
  97. if (!strpbrk(pattern, "?*<>\"")) {
  98. if (strcmp(string,"..") == 0)
  99. string = ".";
  100. return strcmp(pattern, string);
  101. }
  102. if (strcmp(string,"..") == 0 || strcmp(string,".") == 0) {
  103. return ms_fnmatch_lanman_core(pattern, "..") &&
  104. ms_fnmatch_lanman_core(pattern, ".");
  105. }
  106. return ms_fnmatch_lanman_core(pattern, string);
  107. }
  108. static BOOL reg_match_one(struct cli_state *cli, const char *pattern, const char *file)
  109. {
  110. /* oh what a weird world this is */
  111. if (old_list && strcmp(pattern, "*.*") == 0) return True;
  112. if (strcmp(pattern,".") == 0) return False;
  113. if (max_protocol <= PROTOCOL_LANMAN2) {
  114. return ms_fnmatch_lanman(pattern, file)==0;
  115. }
  116. if (strcmp(file,"..") == 0) file = ".";
  117. return ms_fnmatch(pattern, file, cli->protocol, False) == 0;
  118. }
  119. static char *reg_test(struct cli_state *cli, char *pattern, char *long_name, char *short_name)
  120. {
  121. static fstring ret;
  122. fstrcpy(ret, "---");
  123. pattern = 1+strrchr_m(pattern,'\\');
  124. if (reg_match_one(cli, pattern, ".")) ret[0] = '+';
  125. if (reg_match_one(cli, pattern, "..")) ret[1] = '+';
  126. if (reg_match_one(cli, pattern, long_name) ||
  127. (*short_name && reg_match_one(cli, pattern, short_name))) ret[2] = '+';
  128. return ret;
  129. }
  130. /*****************************************************
  131. return a connection to a server
  132. *******************************************************/
  133. static struct cli_state *connect_one(char *share)
  134. {
  135. struct cli_state *c;
  136. struct nmb_name called, calling;
  137. char *server_n;
  138. char *server;
  139. struct in_addr ip;
  140. NTSTATUS status;
  141. server = share+2;
  142. share = strchr_m(server,'\\');
  143. if (!share) return NULL;
  144. *share = 0;
  145. share++;
  146. server_n = server;
  147. zero_ip(&ip);
  148. make_nmb_name(&calling, "masktest", 0x0);
  149. make_nmb_name(&called , server, 0x20);
  150. again:
  151. zero_ip(&ip);
  152. /* have to open a new connection */
  153. if (!(c=cli_initialise())) {
  154. DEBUG(0,("Connection to %s failed\n", server_n));
  155. return NULL;
  156. }
  157. status = cli_connect(c, server_n, &ip);
  158. if (!NT_STATUS_IS_OK(status)) {
  159. DEBUG(0,("Connection to %s failed. Error %s\n", server_n, nt_errstr(status) ));
  160. return NULL;
  161. }
  162. c->protocol = max_protocol;
  163. if (!cli_session_request(c, &calling, &called)) {
  164. DEBUG(0,("session request to %s failed\n", called.name));
  165. cli_shutdown(c);
  166. if (strcmp(called.name, "*SMBSERVER")) {
  167. make_nmb_name(&called , "*SMBSERVER", 0x20);
  168. goto again;
  169. }
  170. return NULL;
  171. }
  172. DEBUG(4,(" session request ok\n"));
  173. if (!cli_negprot(c)) {
  174. DEBUG(0,("protocol negotiation failed\n"));
  175. cli_shutdown(c);
  176. return NULL;
  177. }
  178. if (!got_pass) {
  179. char *pass = getpass("Password: ");
  180. if (pass) {
  181. fstrcpy(password, pass);
  182. }
  183. }
  184. if (!NT_STATUS_IS_OK(cli_session_setup(c, username,
  185. password, strlen(password),
  186. password, strlen(password),
  187. lp_workgroup()))) {
  188. DEBUG(0,("session setup failed: %s\n", cli_errstr(c)));
  189. return NULL;
  190. }
  191. /*
  192. * These next two lines are needed to emulate
  193. * old client behaviour for people who have
  194. * scripts based on client output.
  195. * QUESTION ? Do we want to have a 'client compatibility
  196. * mode to turn these on/off ? JRA.
  197. */
  198. if (*c->server_domain || *c->server_os || *c->server_type)
  199. DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
  200. c->server_domain,c->server_os,c->server_type));
  201. DEBUG(4,(" session setup ok\n"));
  202. if (!cli_send_tconX(c, share, "?????",
  203. password, strlen(password)+1)) {
  204. DEBUG(0,("tree connect failed: %s\n", cli_errstr(c)));
  205. cli_shutdown(c);
  206. return NULL;
  207. }
  208. DEBUG(4,(" tconx ok\n"));
  209. return c;
  210. }
  211. static char *resultp;
  212. static file_info *f_info;
  213. static void listfn(const char *mnt, file_info *f, const char *s, void *state)
  214. {
  215. if (strcmp(f->name,".") == 0) {
  216. resultp[0] = '+';
  217. } else if (strcmp(f->name,"..") == 0) {
  218. resultp[1] = '+';
  219. } else {
  220. resultp[2] = '+';
  221. }
  222. f_info = f;
  223. }
  224. static void get_real_name(struct cli_state *cli,
  225. pstring long_name, fstring short_name)
  226. {
  227. /* nasty hack to force level 260 listings - tridge */
  228. cli->capabilities |= CAP_NT_SMBS;
  229. if (max_protocol <= PROTOCOL_LANMAN1) {
  230. cli_list_new(cli, "\\masktest\\*.*", aHIDDEN | aDIR, listfn, NULL);
  231. } else {
  232. cli_list_new(cli, "\\masktest\\*", aHIDDEN | aDIR, listfn, NULL);
  233. }
  234. if (f_info) {
  235. fstrcpy(short_name, f_info->short_name);
  236. strlower_m(short_name);
  237. pstrcpy(long_name, f_info->name);
  238. strlower_m(long_name);
  239. }
  240. if (*short_name == 0) {
  241. fstrcpy(short_name, long_name);
  242. }
  243. #if 0
  244. if (!strchr_m(short_name,'.')) {
  245. fstrcat(short_name,".");
  246. }
  247. #endif
  248. }
  249. static void testpair(struct cli_state *cli, char *mask, char *file)
  250. {
  251. int fnum;
  252. fstring res1;
  253. char *res2;
  254. static int count;
  255. fstring short_name;
  256. pstring long_name;
  257. count++;
  258. fstrcpy(res1, "---");
  259. fnum = cli_open(cli, file, O_CREAT|O_TRUNC|O_RDWR, 0);
  260. if (fnum == -1) {
  261. DEBUG(0,("Can't create %s\n", file));
  262. return;
  263. }
  264. cli_close(cli, fnum);
  265. resultp = res1;
  266. fstrcpy(short_name, "");
  267. f_info = NULL;
  268. get_real_name(cli, long_name, short_name);
  269. f_info = NULL;
  270. fstrcpy(res1, "---");
  271. cli_list(cli, mask, aHIDDEN | aDIR, listfn, NULL);
  272. res2 = reg_test(cli, mask, long_name, short_name);
  273. if (showall ||
  274. ((strcmp(res1, res2) && !ignore_dot_errors) ||
  275. (strcmp(res1+2, res2+2) && ignore_dot_errors))) {
  276. DEBUG(0,("%s %s %d mask=[%s] file=[%s] rfile=[%s/%s]\n",
  277. res1, res2, count, mask, file, long_name, short_name));
  278. if (die_on_error) exit(1);
  279. }
  280. cli_unlink(cli, file);
  281. if (count % 100 == 0) DEBUG(0,("%d\n", count));
  282. }
  283. static void test_mask(int argc, char *argv[],
  284. struct cli_state *cli)
  285. {
  286. pstring mask, file;
  287. int l1, l2, i, l;
  288. int mc_len = strlen(maskchars);
  289. int fc_len = strlen(filechars);
  290. cli_mkdir(cli, "\\masktest");
  291. cli_unlink(cli, "\\masktest\\*");
  292. if (argc >= 2) {
  293. while (argc >= 2) {
  294. pstrcpy(mask,"\\masktest\\");
  295. pstrcpy(file,"\\masktest\\");
  296. pstrcat(mask, argv[0]);
  297. pstrcat(file, argv[1]);
  298. testpair(cli, mask, file);
  299. argv += 2;
  300. argc -= 2;
  301. }
  302. goto finished;
  303. }
  304. while (1) {
  305. l1 = 1 + random() % 20;
  306. l2 = 1 + random() % 20;
  307. pstrcpy(mask,"\\masktest\\");
  308. pstrcpy(file,"\\masktest\\");
  309. l = strlen(mask);
  310. for (i=0;i<l1;i++) {
  311. mask[i+l] = maskchars[random() % mc_len];
  312. }
  313. mask[l+l1] = 0;
  314. for (i=0;i<l2;i++) {
  315. file[i+l] = filechars[random() % fc_len];
  316. }
  317. file[l+l2] = 0;
  318. if (strcmp(file+l,".") == 0 ||
  319. strcmp(file+l,"..") == 0 ||
  320. strcmp(mask+l,"..") == 0) continue;
  321. if (strspn(file+l, ".") == strlen(file+l)) continue;
  322. testpair(cli, mask, file);
  323. if (NumLoops && (--NumLoops == 0))
  324. break;
  325. }
  326. finished:
  327. cli_rmdir(cli, "\\masktest");
  328. }
  329. static void usage(void)
  330. {
  331. printf(
  332. "Usage:\n\
  333. masktest //server/share [options..]\n\
  334. options:\n\
  335. -d debuglevel\n\
  336. -n numloops\n\
  337. -W workgroup\n\
  338. -U user%%pass\n\
  339. -s seed\n\
  340. -M max protocol\n\
  341. -f filechars (default %s)\n\
  342. -m maskchars (default %s)\n\
  343. -v verbose mode\n\
  344. -E die on error\n\
  345. -a show all tests\n\
  346. -i ignore . and .. errors\n\
  347. \n\
  348. This program tests wildcard matching between two servers. It generates\n\
  349. random pairs of filenames/masks and tests that they match in the same\n\
  350. way on the servers and internally\n\
  351. ",
  352. filechars, maskchars);
  353. }
  354. /****************************************************************************
  355. main program
  356. ****************************************************************************/
  357. int main(int argc,char *argv[])
  358. {
  359. char *share;
  360. struct cli_state *cli;
  361. int opt;
  362. char *p;
  363. int seed;
  364. setlinebuf(stdout);
  365. dbf = x_stderr;
  366. DEBUGLEVEL = 0;
  367. AllowDebugChange = False;
  368. if (argc < 2 || argv[1][0] == '-') {
  369. usage();
  370. exit(1);
  371. }
  372. share = argv[1];
  373. all_string_sub(share,"/","\\",0);
  374. setup_logging(argv[0],True);
  375. argc -= 1;
  376. argv += 1;
  377. lp_load(dyn_CONFIGFILE,True,False,False,True);
  378. load_interfaces();
  379. if (getenv("USER")) {
  380. fstrcpy(username,getenv("USER"));
  381. }
  382. seed = time(NULL);
  383. while ((opt = getopt(argc, argv, "n:d:U:s:hm:f:aoW:M:vEi")) != EOF) {
  384. switch (opt) {
  385. case 'n':
  386. NumLoops = atoi(optarg);
  387. break;
  388. case 'd':
  389. DEBUGLEVEL = atoi(optarg);
  390. break;
  391. case 'E':
  392. die_on_error = 1;
  393. break;
  394. case 'i':
  395. ignore_dot_errors = 1;
  396. break;
  397. case 'v':
  398. verbose++;
  399. break;
  400. case 'M':
  401. max_protocol = interpret_protocol(optarg, max_protocol);
  402. break;
  403. case 'U':
  404. fstrcpy(username,optarg);
  405. p = strchr_m(username,'%');
  406. if (p) {
  407. *p = 0;
  408. fstrcpy(password, p+1);
  409. got_pass = 1;
  410. }
  411. break;
  412. case 's':
  413. seed = atoi(optarg);
  414. break;
  415. case 'h':
  416. usage();
  417. exit(1);
  418. case 'm':
  419. maskchars = optarg;
  420. break;
  421. case 'f':
  422. filechars = optarg;
  423. break;
  424. case 'a':
  425. showall = 1;
  426. break;
  427. case 'o':
  428. old_list = True;
  429. break;
  430. default:
  431. printf("Unknown option %c (%d)\n", (char)opt, opt);
  432. exit(1);
  433. }
  434. }
  435. argc -= optind;
  436. argv += optind;
  437. cli = connect_one(share);
  438. if (!cli) {
  439. DEBUG(0,("Failed to connect to %s\n", share));
  440. exit(1);
  441. }
  442. /* need to init seed after connect as clientgen uses random numbers */
  443. DEBUG(0,("seed=%d\n", seed));
  444. srandom(seed);
  445. test_mask(argc, argv, cli);
  446. return(0);
  447. }