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