PageRenderTime 70ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/source3/torture/scanner.c

https://bitbucket.org/mikedep333/rdssamba4
C | 514 lines | 436 code | 45 blank | 33 comment | 42 complexity | 9198eaee7960bbeb14c676912f5a4861 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-3.0, LGPL-2.1, LGPL-3.0
  1. /*
  2. Unix SMB/CIFS implementation.
  3. SMB torture tester - scanning functions
  4. Copyright (C) Andrew Tridgell 2001
  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 3 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, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "includes.h"
  17. #include "system/filesys.h"
  18. #include "torture/proto.h"
  19. #include "libsmb/libsmb.h"
  20. #define VERBOSE 0
  21. #define OP_MIN 0
  22. #define OP_MAX 20
  23. #define DATA_SIZE 1024
  24. #define PARAM_SIZE 1024
  25. /****************************************************************************
  26. look for a partial hit
  27. ****************************************************************************/
  28. static void trans2_check_hit(const char *format, int op, int level, NTSTATUS status)
  29. {
  30. if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
  31. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
  32. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
  33. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
  34. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
  35. return;
  36. }
  37. #if VERBOSE
  38. printf("possible %s hit op=%3d level=%5d status=%s\n",
  39. format, op, level, nt_errstr(status));
  40. #endif
  41. }
  42. /****************************************************************************
  43. check for existance of a trans2 call
  44. ****************************************************************************/
  45. static NTSTATUS try_trans2(struct cli_state *cli,
  46. int op,
  47. uint8_t *param, uint8_t *data,
  48. uint32_t param_len, uint32_t data_len,
  49. uint32_t *rparam_len, uint32_t *rdata_len)
  50. {
  51. uint16_t setup[1];
  52. uint8_t *rparam=NULL, *rdata=NULL;
  53. NTSTATUS status;
  54. SSVAL(setup+0, 0, op);
  55. status = cli_trans(talloc_tos(), cli, SMBtrans2,
  56. NULL, -1, /* name, fid */
  57. op, 0,
  58. NULL, 0, 0, /* setup */
  59. param, param_len, 2,
  60. data, data_len, CLI_BUFFER_SIZE,
  61. NULL, /* recv_flags2 */
  62. NULL, 0, NULL, /* rsetup */
  63. &rparam, 0, rparam_len,
  64. &rdata, 0, rdata_len);
  65. TALLOC_FREE(rdata);
  66. TALLOC_FREE(rparam);
  67. return status;
  68. }
  69. static NTSTATUS try_trans2_len(struct cli_state *cli,
  70. const char *format,
  71. int op, int level,
  72. uint8_t *param, uint8_t *data,
  73. uint32_t param_len, uint32_t *data_len,
  74. uint32_t *rparam_len, uint32_t *rdata_len)
  75. {
  76. NTSTATUS ret=NT_STATUS_OK;
  77. ret = try_trans2(cli, op, param, data, param_len,
  78. DATA_SIZE, rparam_len, rdata_len);
  79. #if VERBOSE
  80. printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
  81. #endif
  82. if (!NT_STATUS_IS_OK(ret)) return ret;
  83. *data_len = 0;
  84. while (*data_len < DATA_SIZE) {
  85. ret = try_trans2(cli, op, param, data, param_len,
  86. *data_len, rparam_len, rdata_len);
  87. if (NT_STATUS_IS_OK(ret)) break;
  88. *data_len += 2;
  89. }
  90. if (NT_STATUS_IS_OK(ret)) {
  91. printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
  92. format, level, *data_len, *rparam_len, *rdata_len);
  93. } else {
  94. trans2_check_hit(format, op, level, ret);
  95. }
  96. return ret;
  97. }
  98. /****************************************************************************
  99. check for existance of a trans2 call
  100. ****************************************************************************/
  101. static bool scan_trans2(struct cli_state *cli, int op, int level,
  102. int fnum, int dnum, const char *fname)
  103. {
  104. uint32_t data_len = 0;
  105. uint32_t param_len = 0;
  106. uint32_t rparam_len, rdata_len;
  107. uint8_t *param = NULL;
  108. uint8_t data[DATA_SIZE];
  109. const char *newfname;
  110. const char *dname;
  111. NTSTATUS status;
  112. memset(data, 0, sizeof(data));
  113. data_len = 4;
  114. /* try with a info level only */
  115. TALLOC_FREE(param);
  116. param = talloc_array(talloc_tos(), uint8_t, 2);
  117. if (param == NULL) return True;
  118. SSVAL(param, 0, level);
  119. param_len = talloc_get_size(param);
  120. status = try_trans2_len(cli, "void", op, level, param, data, param_len, &data_len,
  121. &rparam_len, &rdata_len);
  122. if (NT_STATUS_IS_OK(status)) return True;
  123. /* try with a file descriptor */
  124. TALLOC_FREE(param);
  125. param = talloc_array(talloc_tos(), uint8_t, 6);
  126. if (param == NULL) return True;
  127. SSVAL(param, 0, fnum);
  128. SSVAL(param, 2, level);
  129. SSVAL(param, 4, 0);
  130. param_len = talloc_get_size(param);
  131. status = try_trans2_len(cli, "fnum", op, level, param, data, param_len, &data_len,
  132. &rparam_len, &rdata_len);
  133. if (NT_STATUS_IS_OK(status)) return True;
  134. /* try with a notify style */
  135. TALLOC_FREE(param);
  136. param = talloc_array(talloc_tos(), uint8_t, 6);
  137. if (param == NULL) return True;
  138. SSVAL(param, 0, dnum);
  139. SSVAL(param, 2, dnum);
  140. SSVAL(param, 4, level);
  141. param_len = talloc_get_size(param);
  142. status = try_trans2_len(cli, "notify", op, level, param, data, param_len, &data_len,
  143. &rparam_len, &rdata_len);
  144. if (NT_STATUS_IS_OK(status)) return True;
  145. /* try with a file name */
  146. TALLOC_FREE(param);
  147. param = talloc_array(talloc_tos(), uint8_t, 6);
  148. if (param == NULL) return True;
  149. SSVAL(param, 0, level);
  150. SSVAL(param, 2, 0);
  151. SSVAL(param, 4, 0);
  152. param = trans2_bytes_push_str(param, cli_ucs2(cli),
  153. fname, strlen(fname)+1, NULL);
  154. if (param == NULL) return True;
  155. param_len = talloc_get_size(param);
  156. status = try_trans2_len(cli, "fname", op, level, param, data, param_len, &data_len,
  157. &rparam_len, &rdata_len);
  158. if (NT_STATUS_IS_OK(status)) return True;
  159. /* try with a new file name */
  160. newfname = "\\newfile.dat";
  161. TALLOC_FREE(param);
  162. param = talloc_array(talloc_tos(), uint8_t, 6);
  163. if (param == NULL) return True;
  164. SSVAL(param, 0, level);
  165. SSVAL(param, 2, 0);
  166. SSVAL(param, 4, 0);
  167. param = trans2_bytes_push_str(param, cli_ucs2(cli),
  168. newfname, strlen(newfname)+1, NULL);
  169. if (param == NULL) return True;
  170. param_len = talloc_get_size(param);
  171. status = try_trans2_len(cli, "newfile", op, level, param, data, param_len, &data_len,
  172. &rparam_len, &rdata_len);
  173. cli_unlink(cli, newfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
  174. cli_rmdir(cli, newfname);
  175. if (NT_STATUS_IS_OK(status)) return True;
  176. /* try dfs style */
  177. dname = "\\testdir";
  178. cli_mkdir(cli, dname);
  179. TALLOC_FREE(param);
  180. param = talloc_array(talloc_tos(), uint8_t, 2);
  181. if (param == NULL) return True;
  182. SSVAL(param, 0, level);
  183. param = trans2_bytes_push_str(param, cli_ucs2(cli),
  184. dname, strlen(dname)+1, NULL);
  185. if (param == NULL) return True;
  186. param_len = talloc_get_size(param);
  187. status = try_trans2_len(cli, "dfs", op, level, param, data, param_len, &data_len,
  188. &rparam_len, &rdata_len);
  189. cli_rmdir(cli, dname);
  190. if (NT_STATUS_IS_OK(status)) return True;
  191. return False;
  192. }
  193. bool torture_trans2_scan(int dummy)
  194. {
  195. static struct cli_state *cli;
  196. int op, level;
  197. const char *fname = "\\scanner.dat";
  198. uint16_t fnum, dnum;
  199. printf("starting trans2 scan test\n");
  200. if (!torture_open_connection(&cli, 0)) {
  201. return False;
  202. }
  203. if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
  204. DENY_NONE, &fnum))) {
  205. printf("open of %s failed\n", fname);
  206. return false;
  207. }
  208. if (!NT_STATUS_IS_OK(cli_open(cli, "\\", O_RDONLY, DENY_NONE, &dnum))) {
  209. printf("open of \\ failed\n");
  210. return false;
  211. }
  212. for (op=OP_MIN; op<=OP_MAX; op++) {
  213. printf("Scanning op=%d\n", op);
  214. for (level = 0; level <= 50; level++) {
  215. scan_trans2(cli, op, level, fnum, dnum, fname);
  216. }
  217. for (level = 0x100; level <= 0x130; level++) {
  218. scan_trans2(cli, op, level, fnum, dnum, fname);
  219. }
  220. for (level = 1000; level < 1050; level++) {
  221. scan_trans2(cli, op, level, fnum, dnum, fname);
  222. }
  223. }
  224. torture_close_connection(cli);
  225. printf("trans2 scan finished\n");
  226. return True;
  227. }
  228. /****************************************************************************
  229. look for a partial hit
  230. ****************************************************************************/
  231. static void nttrans_check_hit(const char *format, int op, int level, NTSTATUS status)
  232. {
  233. if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_LEVEL) ||
  234. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ||
  235. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED) ||
  236. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) ||
  237. NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) {
  238. return;
  239. }
  240. #if VERBOSE
  241. printf("possible %s hit op=%3d level=%5d status=%s\n",
  242. format, op, level, nt_errstr(status));
  243. #endif
  244. }
  245. /****************************************************************************
  246. check for existance of a nttrans call
  247. ****************************************************************************/
  248. static NTSTATUS try_nttrans(struct cli_state *cli,
  249. int op,
  250. uint8_t *param, uint8_t *data,
  251. int32_t param_len, uint32_t data_len,
  252. uint32_t *rparam_len,
  253. uint32_t *rdata_len)
  254. {
  255. uint8_t *rparam=NULL, *rdata=NULL;
  256. NTSTATUS status;
  257. status = cli_trans(talloc_tos(), cli, SMBnttrans,
  258. NULL, -1, /* name, fid */
  259. op, 0,
  260. NULL, 0, 0, /* setup */
  261. param, param_len, 2,
  262. data, data_len, CLI_BUFFER_SIZE,
  263. NULL, /* recv_flags2 */
  264. NULL, 0, NULL, /* rsetup */
  265. &rparam, 0, rparam_len,
  266. &rdata, 0, rdata_len);
  267. SAFE_FREE(rdata);
  268. SAFE_FREE(rparam);
  269. return status;
  270. }
  271. static NTSTATUS try_nttrans_len(struct cli_state *cli,
  272. const char *format,
  273. int op, int level,
  274. uint8_t *param, uint8_t *data,
  275. int param_len, uint32_t *data_len,
  276. uint32_t *rparam_len, uint32_t *rdata_len)
  277. {
  278. NTSTATUS ret=NT_STATUS_OK;
  279. ret = try_nttrans(cli, op, param, data, param_len,
  280. DATA_SIZE, rparam_len, rdata_len);
  281. #if VERBOSE
  282. printf("op=%d level=%d ret=%s\n", op, level, nt_errstr(ret));
  283. #endif
  284. if (!NT_STATUS_IS_OK(ret)) return ret;
  285. *data_len = 0;
  286. while (*data_len < DATA_SIZE) {
  287. ret = try_nttrans(cli, op, param, data, param_len,
  288. *data_len, rparam_len, rdata_len);
  289. if (NT_STATUS_IS_OK(ret)) break;
  290. *data_len += 2;
  291. }
  292. if (NT_STATUS_IS_OK(ret)) {
  293. printf("found %s level=%d data_len=%d rparam_len=%d rdata_len=%d\n",
  294. format, level, *data_len, *rparam_len, *rdata_len);
  295. } else {
  296. nttrans_check_hit(format, op, level, ret);
  297. }
  298. return ret;
  299. }
  300. /****************************************************************************
  301. check for existance of a nttrans call
  302. ****************************************************************************/
  303. static bool scan_nttrans(struct cli_state *cli, int op, int level,
  304. int fnum, int dnum, const char *fname)
  305. {
  306. uint32_t data_len = 0;
  307. uint32_t param_len = 0;
  308. uint32_t rparam_len, rdata_len;
  309. uint8_t *param = NULL;
  310. uint8_t data[DATA_SIZE];
  311. NTSTATUS status;
  312. const char *newfname;
  313. const char *dname;
  314. memset(data, 0, sizeof(data));
  315. data_len = 4;
  316. /* try with a info level only */
  317. TALLOC_FREE(param);
  318. param = talloc_array(talloc_tos(), uint8_t, 2);
  319. if (param == NULL) return True;
  320. SSVAL(param, 0, level);
  321. param_len = talloc_get_size(param);
  322. status = try_nttrans_len(cli, "void", op, level, param, data, param_len, &data_len,
  323. &rparam_len, &rdata_len);
  324. if (NT_STATUS_IS_OK(status)) return True;
  325. /* try with a file descriptor */
  326. TALLOC_FREE(param);
  327. param = talloc_array(talloc_tos(), uint8_t, 6);
  328. if (param == NULL) return True;
  329. SSVAL(param, 0, fnum);
  330. SSVAL(param, 2, level);
  331. SSVAL(param, 4, 0);
  332. param_len = talloc_get_size(param);
  333. status = try_nttrans_len(cli, "fnum", op, level, param, data, param_len, &data_len,
  334. &rparam_len, &rdata_len);
  335. if (NT_STATUS_IS_OK(status)) return True;
  336. /* try with a notify style */
  337. TALLOC_FREE(param);
  338. param = talloc_array(talloc_tos(), uint8_t, 6);
  339. if (param == NULL) return True;
  340. SSVAL(param, 0, dnum);
  341. SSVAL(param, 2, dnum);
  342. SSVAL(param, 4, level);
  343. param_len = talloc_get_size(param);
  344. status = try_nttrans_len(cli, "notify", op, level, param, data, param_len, &data_len,
  345. &rparam_len, &rdata_len);
  346. if (NT_STATUS_IS_OK(status)) return True;
  347. /* try with a file name */
  348. TALLOC_FREE(param);
  349. param = talloc_array(talloc_tos(), uint8_t, 6);
  350. if (param == NULL) return True;
  351. SSVAL(param, 0, level);
  352. SSVAL(param, 2, 0);
  353. SSVAL(param, 4, 0);
  354. param = trans2_bytes_push_str(param, cli_ucs2(cli),
  355. fname, strlen(fname)+1, NULL);
  356. if (param == NULL) return True;
  357. param_len = talloc_get_size(param);
  358. status = try_nttrans_len(cli, "fname", op, level, param, data, param_len, &data_len,
  359. &rparam_len, &rdata_len);
  360. if (NT_STATUS_IS_OK(status)) return True;
  361. /* try with a new file name */
  362. newfname = "\\newfile.dat";
  363. TALLOC_FREE(param);
  364. param = talloc_array(talloc_tos(), uint8_t, 6);
  365. if (param == NULL) return True;
  366. SSVAL(param, 0, level);
  367. SSVAL(param, 2, 0);
  368. SSVAL(param, 4, 0);
  369. param = trans2_bytes_push_str(param, cli_ucs2(cli),
  370. newfname, strlen(newfname)+1, NULL);
  371. if (param == NULL) return True;
  372. param_len = talloc_get_size(param);
  373. status = try_nttrans_len(cli, "newfile", op, level, param, data, param_len, &data_len,
  374. &rparam_len, &rdata_len);
  375. cli_unlink(cli, newfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
  376. cli_rmdir(cli, newfname);
  377. if (NT_STATUS_IS_OK(status)) return True;
  378. /* try dfs style */
  379. dname = "\\testdir";
  380. cli_mkdir(cli, dname);
  381. TALLOC_FREE(param);
  382. param = talloc_array(talloc_tos(), uint8_t, 2);
  383. if (param == NULL) return True;
  384. SSVAL(param, 0, level);
  385. param = trans2_bytes_push_str(param, cli_ucs2(cli),
  386. dname, strlen(dname)+1, NULL);
  387. if (param == NULL) return True;
  388. param_len = talloc_get_size(param);
  389. status = try_nttrans_len(cli, "dfs", op, level, param, data, param_len, &data_len,
  390. &rparam_len, &rdata_len);
  391. cli_rmdir(cli, dname);
  392. if (NT_STATUS_IS_OK(status)) return True;
  393. return False;
  394. }
  395. bool torture_nttrans_scan(int dummy)
  396. {
  397. static struct cli_state *cli;
  398. int op, level;
  399. const char *fname = "\\scanner.dat";
  400. uint16_t fnum, dnum;
  401. printf("starting nttrans scan test\n");
  402. if (!torture_open_connection(&cli, 0)) {
  403. return False;
  404. }
  405. cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC,
  406. DENY_NONE, &fnum);
  407. cli_open(cli, "\\", O_RDONLY, DENY_NONE, &dnum);
  408. for (op=OP_MIN; op<=OP_MAX; op++) {
  409. printf("Scanning op=%d\n", op);
  410. for (level = 0; level <= 50; level++) {
  411. scan_nttrans(cli, op, level, fnum, dnum, fname);
  412. }
  413. for (level = 0x100; level <= 0x130; level++) {
  414. scan_nttrans(cli, op, level, fnum, dnum, fname);
  415. }
  416. for (level = 1000; level < 1050; level++) {
  417. scan_nttrans(cli, op, level, fnum, dnum, fname);
  418. }
  419. }
  420. torture_close_connection(cli);
  421. printf("nttrans scan finished\n");
  422. return True;
  423. }