Exemplo n.º 1
0
NTSTATUS torture_single_file_search(struct smb2_tree *tree,
				    TALLOC_CTX *mem_ctx,
				    const char *pattern,
				    uint8_t level,
				    enum smb_search_data_level data_level,
				    int idx,
				    union smb_search_data *d,
				    unsigned int *count,
				    struct smb2_handle *h)
{
	struct smb2_find f;
	NTSTATUS status;

	ZERO_STRUCT(f);
	f.in.file.handle        = *h;
	f.in.pattern            = pattern;
	f.in.continue_flags     = SMB2_CONTINUE_FLAG_RESTART;
	f.in.max_response_size  = 0x100;
	f.in.level              = level;

	status = smb2_find_level(tree, tree, &f, count, &d);
	if (NT_STATUS_IS_OK(status))
		fill_level_data(mem_ctx, &levels[idx].data, d, *count, level,
				data_level);
	return status;
}
Exemplo n.º 2
0
/* 
   recursively descend a tree deleting all files
   returns the number of files deleted, or -1 on error
*/
int smb2_deltree(struct smb2_tree *tree, const char *dname)
{
	NTSTATUS status;
	uint32_t total_deleted = 0;
	unsigned int count, i;
	union smb_search_data *list;
	TALLOC_CTX *tmp_ctx = talloc_new(tree);
	struct smb2_find f;
	struct smb2_create create_parm;
	bool did_delete;

	/* it might be a file */
	status = smb2_util_unlink(tree, dname);
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return 1;
	}
	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
	    NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
	    NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
		talloc_free(tmp_ctx);
		return 0;
	}

	if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
		/* it could be read-only */
		status = smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
		status = smb2_util_unlink(tree, dname);
	}
	if (NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return 1;
	}

	ZERO_STRUCT(create_parm);
	create_parm.in.desired_access = SEC_FILE_READ_DATA;
	create_parm.in.share_access = 
		NTCREATEX_SHARE_ACCESS_READ|
		NTCREATEX_SHARE_ACCESS_WRITE;
	create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
	create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
	create_parm.in.fname = dname;

	status = smb2_create(tree, tmp_ctx, &create_parm);
	if (NT_STATUS_IS_ERR(status)) {
		DEBUG(2,("Failed to open %s - %s\n", dname, nt_errstr(status)));
		talloc_free(tmp_ctx);
		return -1;
	}
	

	do {
		did_delete = false;

		ZERO_STRUCT(f);
		f.in.file.handle       = create_parm.out.file.handle;
		f.in.max_response_size = 0x10000;
		f.in.level             = SMB2_FIND_NAME_INFO;
		f.in.pattern           = "*";
		
		status = smb2_find_level(tree, tmp_ctx, &f, &count, &list);
		if (NT_STATUS_IS_ERR(status)) {
			DEBUG(2,("Failed to list %s - %s\n", 
				 dname, nt_errstr(status)));
			smb2_util_close(tree, create_parm.out.file.handle);
			talloc_free(tmp_ctx);
			return -1;
		}
		
		for (i=0;i<count;i++) {
			char *name;
			if (strcmp(".", list[i].name_info.name.s) == 0 ||
			    strcmp("..", list[i].name_info.name.s) == 0) {
				continue;
			}
			name = talloc_asprintf(tmp_ctx, "%s\\%s", dname, list[i].name_info.name.s);
			status = smb2_util_unlink(tree, name);
			if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
				/* it could be read-only */
				status = smb2_util_setatr(tree, name, FILE_ATTRIBUTE_NORMAL);
				status = smb2_util_unlink(tree, name);
			}
			
			if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
				int ret;
				ret = smb2_deltree(tree, name);
				if (ret > 0) total_deleted += ret;
			}
			talloc_free(name);
			if (NT_STATUS_IS_OK(status)) {
				total_deleted++;
				did_delete = true;
			}
		}
	} while (did_delete);

	smb2_util_close(tree, create_parm.out.file.handle);

	status = smb2_util_rmdir(tree, dname);
	if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
		/* it could be read-only */
		status = smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
		status = smb2_util_rmdir(tree, dname);
	}

	if (NT_STATUS_IS_ERR(status)) {
		DEBUG(2,("Failed to delete %s - %s\n", 
			 dname, nt_errstr(status)));
		talloc_free(tmp_ctx);
		return -1;
	}

	talloc_free(tmp_ctx);

	return total_deleted;
}
Exemplo n.º 3
0
/* 
   list files in a directory matching a wildcard pattern
*/
static NTSTATUS cvfs_search_first(struct ntvfs_module_context *ntvfs, 
				  struct ntvfs_request *req, union smb_search_first *io, 
				  void *search_private, 
				  bool (*callback)(void *, const union smb_search_data *))
{
	struct cvfs_private *p = ntvfs->private_data;
	struct smb2_find f;
	enum smb_search_data_level smb2_level;
	unsigned int count, i;
	union smb_search_data *data;
	NTSTATUS status;

	if (io->generic.level != RAW_SEARCH_TRANS2) {
		DEBUG(0,("We only support trans2 search in smb2 backend\n"));
		return NT_STATUS_NOT_SUPPORTED;
	}

	switch (io->generic.data_level) {
	case RAW_SEARCH_DATA_DIRECTORY_INFO:
		smb2_level = SMB2_FIND_DIRECTORY_INFO;
		break;
	case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
		smb2_level = SMB2_FIND_FULL_DIRECTORY_INFO;
		break;
	case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
		smb2_level = SMB2_FIND_BOTH_DIRECTORY_INFO;
		break;
	case RAW_SEARCH_DATA_NAME_INFO:
		smb2_level = SMB2_FIND_NAME_INFO;
		break;
	case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
		smb2_level = SMB2_FIND_ID_FULL_DIRECTORY_INFO;
		break;
	case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
		smb2_level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
		break;
	default:
		DEBUG(0,("Unsupported search level %u for smb2 backend\n",
			 (unsigned)io->generic.data_level));
		return NT_STATUS_INVALID_INFO_CLASS;
	}

	/* we do the search on the roothandle. This only works because
	   search is synchronous, otherwise we'd have no way to
	   distinguish multiple searches happening at once
	*/
	ZERO_STRUCT(f);
	f.in.file.handle	= p->roothandle;
	f.in.level              = smb2_level;
	f.in.pattern		= io->t2ffirst.in.pattern;
	while (f.in.pattern[0] == '\\') {
		f.in.pattern++;
	}
	f.in.continue_flags	= 0;
	f.in.max_response_size	= 0x10000;

	status = smb2_find_level(p->tree, req, &f, &count, &data);
	NT_STATUS_NOT_OK_RETURN(status);	

	for (i=0;i<count;i++) {
		if (!callback(search_private, &data[i])) break;
	}

	io->t2ffirst.out.handle = 0;
	io->t2ffirst.out.count = i;
	/* TODO: fix end_of_file */
	io->t2ffirst.out.end_of_search = 1;

	talloc_free(data);
	
	return NT_STATUS_OK;
}
Exemplo n.º 4
0
static bool test_fixed(struct torture_context *tctx,
		       struct smb2_tree *tree)
{
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	struct smb2_create create;
	struct smb2_handle h, h2;
	struct smb2_find f;
	union smb_search_data *d;
	struct file_elem files[NFILES] = {};
	NTSTATUS status;
	bool ret = true;
	unsigned int count;
	int i;

	status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h);

	ZERO_STRUCT(create);
	create.in.desired_access = SEC_RIGHTS_DIR_ALL;
	create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
	create.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
	create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
				 NTCREATEX_SHARE_ACCESS_WRITE |
				 NTCREATEX_SHARE_ACCESS_DELETE;
	create.in.create_disposition = NTCREATEX_DISP_OPEN;
	create.in.fname = DNAME;

	status = smb2_create(tree, mem_ctx, &create);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");
	h2 = create.out.file.handle;

	ZERO_STRUCT(f);
	f.in.file.handle	= h;
	f.in.pattern		= "*";
	f.in.continue_flags	= SMB2_CONTINUE_FLAG_SINGLE;
	f.in.max_response_size	= 0x100;
	f.in.level              = SMB2_FIND_BOTH_DIRECTORY_INFO;

	/* Start enumeration on h, then delete all from h2 */
	status = smb2_find_level(tree, tree, &f, &count, &d);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");

	f.in.file.handle	= h2;

	do {
		status = smb2_find_level(tree, tree, &f, &count, &d);
		if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
			break;
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");

		for (i = 0; i < count; i++) {
			const char *found = d[i].both_directory_info.name.s;
			char *path = talloc_asprintf(mem_ctx, "%s\\%s",
			    DNAME, found);

			if (!strcmp(found, ".") || !strcmp(found, ".."))
				continue;

			status = smb2_util_unlink(tree, path);
			torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
							"");

			talloc_free(path);
		}

		f.in.continue_flags = 0;
		f.in.max_response_size	= 4096;
	} while (count != 0);

	/* Now finish h enumeration. */
	f.in.file.handle = h;

	do {
		status = smb2_find_level(tree, tree, &f, &count, &d);
		if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
			break;
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");

		for (i = 0; i < count; i++) {
			const char *found = d[i].both_directory_info.name.s;

			if (!strcmp(found, ".") || !strcmp(found, ".."))
				continue;

			torture_result(tctx, TORTURE_FAIL,
			    "(%s): didn't expect %s\n",
			    __location__, found);
			ret = false;
			goto done;
		}

		f.in.continue_flags = 0;
		f.in.max_response_size	= 4096;
	} while (count != 0);

 done:
	smb2_util_close(tree, h);
	smb2_util_close(tree, h2);
	smb2_deltree(tree, DNAME);
	talloc_free(mem_ctx);

	return ret;
}
Exemplo n.º 5
0
static bool test_find(struct torture_context *tctx,
		      struct smb2_tree *tree)
{
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	struct smb2_handle h;
	struct smb2_find f;
	union smb_search_data *d;
	struct file_elem files[NFILES] = {};
	NTSTATUS status;
	bool ret = true;
	unsigned int count;
	int i, j, file_count = 0;

	status = populate_tree(tctx, mem_ctx, tree, files, NFILES, &h);

	ZERO_STRUCT(f);
	f.in.file.handle	= h;
	f.in.pattern		= "*";
	f.in.continue_flags	= SMB2_CONTINUE_FLAG_SINGLE;
	f.in.max_response_size	= 0x100;
	f.in.level              = SMB2_FIND_BOTH_DIRECTORY_INFO;

	do {
		status = smb2_find_level(tree, tree, &f, &count, &d);
		if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES))
			break;
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");

		for (i = 0; i < count; i++) {
			bool expected;
			const char *found = d[i].both_directory_info.name.s;

			if (!strcmp(found, ".") || !strcmp(found, ".."))
				continue;

			expected = false;
			for (j = 0; j < NFILES; j++) {
				if (!strcmp(files[j].name, found)) {
					files[j].found = true;
					expected = true;
					break;
				}
			}

			if (expected)
				continue;

			torture_result(tctx, TORTURE_FAIL,
			    "(%s): didn't expect %s\n",
			    __location__, found);
			ret = false;
			goto done;
		}

		file_count = file_count + i;
		f.in.continue_flags = 0;
		f.in.max_response_size	= 4096;
	} while (count != 0);

	torture_assert_int_equal_goto(tctx, file_count, NFILES + 2, ret, done,
				      "");

	for (i = 0; i < NFILES; i++) {
		if (files[j].found)
			continue;

		torture_result(tctx, TORTURE_FAIL,
		    "(%s): expected to find %s, but didn't\n",
		    __location__, files[j].name);
		ret = false;
		goto done;
	}

 done:
	smb2_deltree(tree, DNAME);
	talloc_free(mem_ctx);

	return ret;
}