Ejemplo n.º 1
0
static bool test_lease_upgrade2(struct torture_context *tctx,
                                struct smb2_tree *tree)
{
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	struct smb2_handle h, hnew;
	NTSTATUS status;
	struct smb2_create io;
	struct smb2_lease ls;
	const char *fname = "lease.dat";
	bool ret = true;
	int i;
	uint32_t caps;

	caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
	if (!(caps & SMB2_CAP_LEASING)) {
		torture_skip(tctx, "leases are not supported");
	}

	for (i = 0; i < NUM_UPGRADE_TESTS; i++) {
		struct lease_upgrade2_test t = lease_upgrade2_tests[i];

		smb2_util_unlink(tree, fname);

		/* Grab a lease. */
		smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.initial));
		status = smb2_create(tree, mem_ctx, &io);
		CHECK_STATUS(status, NT_STATUS_OK);
		CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
		CHECK_LEASE(&io, t.initial, true, LEASE1);
		h = io.out.file.handle;

		/* Upgrade. */
		smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state(t.upgrade_to));
		status = smb2_create(tree, mem_ctx, &io);
		CHECK_STATUS(status, NT_STATUS_OK);
		CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
		CHECK_LEASE(&io, t.expected, true, LEASE1);
		hnew = io.out.file.handle;

		smb2_util_close(tree, hnew);
		smb2_util_close(tree, h);
	}

 done:
	smb2_util_close(tree, h);
	smb2_util_close(tree, hnew);

	smb2_util_unlink(tree, fname);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 2
0
/**
 * basic test for doing a durable open
 * and do a durable reopen on the same connection
 * while the first open is still active (fails)
 */
bool test_durable_v2_open_reopen1(struct torture_context *tctx,
				  struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	struct smb2_create io;
	struct GUID create_guid = GUID_random();
	bool ret = true;

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "durable_v2_open_reopen1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io.in.durable_open = false;
	io.in.durable_open_v2 = true;
	io.in.persistent_open = false;
	io.in.create_guid = create_guid;
	io.in.timeout = UINT32_MAX;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, true);
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.timeout, io.in.timeout);

	/* try a durable reconnect while the file is still open */
	ZERO_STRUCT(io);
	io.in.fname = "";
	io.in.durable_handle_v2 = h;
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 3
0
/**
 * basic test for doing a session reconnect on one connection
 */
bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	uint64_t previous_session_id;
	bool ret = true;
	struct smb2_session *session2;
	union smb_fileinfo qfinfo;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reconnect_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* disconnect, reconnect and then do durable reopen */
	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);

	torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
				previous_session_id, tctx, &session2),
				"session reconnect (on the same connection) failed");

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
	h1 = NULL;

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	talloc_free(tree);
	talloc_free(session2);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 4
0
/*
   basic testing of change notify on directories
*/
static bool torture_smb2_notify_disabled(struct torture_context *torture,
					 struct smb2_tree *tree1)
{
	bool ret = true;
	NTSTATUS status;
	union smb_notify notify;
	union smb_open io;
	struct smb2_handle h1;
	struct smb2_request *req;

	torture_comment(torture, "TESTING CHANGE NOTIFY DISABLED\n");

	smb2_deltree(tree1, BASEDIR);
	smb2_util_rmdir(tree1, BASEDIR);
	/*
	  get a handle on the directory
	*/
	ZERO_STRUCT(io.smb2);
	io.generic.level = RAW_OPEN_SMB2;
	io.smb2.in.create_flags = 0;
	io.smb2.in.desired_access = SEC_FILE_ALL;
	io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
	io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
	io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
				NTCREATEX_SHARE_ACCESS_WRITE;
	io.smb2.in.alloc_size = 0;
	io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
	io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
	io.smb2.in.security_flags = 0;
	io.smb2.in.fname = BASEDIR;

	status = smb2_create(tree1, torture, &(io.smb2));
	torture_assert_ntstatus_equal_goto(torture, status, NT_STATUS_OK,
					   ret, done, "smb2_create");
	h1 = io.smb2.out.file.handle;

	ZERO_STRUCT(notify.smb2);
	notify.smb2.level = RAW_NOTIFY_SMB2;
	notify.smb2.in.buffer_size = 1000;
	notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
	notify.smb2.in.file.handle = h1;
	notify.smb2.in.recursive = true;

	req = smb2_notify_send(tree1, &(notify.smb2));
	status = smb2_notify_recv(req, torture, &(notify.smb2));
	torture_assert_ntstatus_equal_goto(torture, status, NT_STATUS_NOT_IMPLEMENTED,
					   ret, done, "smb2_notify_recv");

	status = smb2_util_close(tree1, h1);
	torture_assert_ntstatus_equal_goto(torture, status, NT_STATUS_OK,
					   ret, done, "smb2_create");

done:
	smb2_deltree(tree1, BASEDIR);
	return ret;
}
Ejemplo n.º 5
0
static NTSTATUS populate_tree(struct torture_context *tctx,
			      TALLOC_CTX *mem_ctx,
			      struct smb2_tree *tree,
			      struct file_elem *files,
			      int nfiles,
			      struct smb2_handle *h_out)
{
	struct smb2_create create;
	char **strs = NULL;
	NTSTATUS status;
	bool ret;
	int i;

	smb2_deltree(tree, DNAME);

	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_CREATE;
	create.in.fname = DNAME;

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

	ZERO_STRUCT(create);
	create.in.desired_access = SEC_RIGHTS_FILE_ALL;
	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
	create.in.create_disposition = NTCREATEX_DISP_CREATE;

	strs = generate_unique_strs(mem_ctx, 8, nfiles);
	if (strs == NULL) {
		status = NT_STATUS_OBJECT_NAME_COLLISION;
		goto done;
	}
	for (i = 0; i < nfiles; i++) {
		files[i].name = strs[i];
		create.in.fname = talloc_asprintf(mem_ctx, "%s\\%s",
		    DNAME, files[i].name);
		status = smb2_create(tree, mem_ctx, &create);
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "");
		smb2_util_close(tree, create.out.file.handle);
	}
 done:
	return status;
}
Ejemplo n.º 6
0
static bool test_one_durable_v2_open_lease(struct torture_context *tctx,
					   struct smb2_tree *tree,
					   const char *fname,
					   bool request_persistent,
					   struct durable_open_vs_lease test)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	bool ret = true;
	struct smb2_create io;
	struct smb2_lease ls;
	uint64_t lease;

	smb2_util_unlink(tree, fname);

	lease = random();

	smb2_lease_create_share(&io, &ls, false /* dir */, fname,
				smb2_util_share_access(test.share_mode),
				lease,
				smb2_util_lease_state(test.type));
	io.in.durable_open = false;
	io.in.durable_open_v2 = true;
	io.in.persistent_open = request_persistent;
	io.in.create_guid = GUID_random();

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, test.durable);
	CHECK_VAL(io.out.persistent_open, test.persistent);
	CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
	CHECK_VAL(io.out.lease_response.lease_key.data[0], lease);
	CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease);
	CHECK_VAL(io.out.lease_response.lease_state,
		  smb2_util_lease_state(test.type));
done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}
	smb2_util_unlink(tree, fname);
	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 7
0
static bool test_one_durable_v2_open_oplock(struct torture_context *tctx,
					    struct smb2_tree *tree,
					    const char *fname,
					    bool request_persistent,
					    struct durable_open_vs_oplock test)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	bool ret = true;
	struct smb2_create io;

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io, fname,
				 smb2_util_share_access(test.share_mode),
				 smb2_util_oplock_level(test.level));
	io.in.durable_open = false;
	io.in.durable_open_v2 = true;
	io.in.persistent_open = request_persistent;
	io.in.create_guid = GUID_random();

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, test.durable);
	CHECK_VAL(io.out.persistent_open, test.persistent);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(test.level));

done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}
	smb2_util_unlink(tree, fname);
	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 8
0
/**
 * test setting security descriptor after reauth.
 */
bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	union smb_fileinfo qfinfo;
	union smb_setfileinfo sfinfo;
	struct cli_credentials *anon_creds = NULL;
	uint32_t secinfo_flags = SECINFO_OWNER
				| SECINFO_GROUP
				| SECINFO_DACL
				| SECINFO_PROTECTED_DACL
				| SECINFO_UNPROTECTED_DACL;
	struct security_descriptor *sd1;
	struct security_ace ace;
	struct dom_sid *extra_sid;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth4_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	sd1 = qfinfo.query_secdesc.out.sd;

	/* re-authenticate as anonymous */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* give full access on the file to anonymous */

	extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);

	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
	ace.trustee = *extra_sid;

	status = security_descriptor_dacl_add(sd1, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(sfinfo);
	sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
	sfinfo.set_secdesc.in.file.handle = _h1;
	sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
	sfinfo.set_secdesc.in.sd = sd1;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-authenticate as original user again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	ret = true;

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 9
0
/**
 * test getting security descriptor after reauth
 */
bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	union smb_fileinfo qfinfo;
	struct cli_credentials *anon_creds = NULL;
	uint32_t secinfo_flags = SECINFO_OWNER
				| SECINFO_GROUP
				| SECINFO_DACL
				| SECINFO_PROTECTED_DACL
				| SECINFO_UNPROTECTED_DACL;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth3_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	/* re-authenticate as anonymous */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-authenticate as original user again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 10
0
bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	union smb_fileinfo qfinfo;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 11
0
/* Send a compound request where we expect the last request (Create, Notify)
 * to go asynchronous. This works against a Win7 server and the reply is
 * sent in two different packets. */
static bool test_compound_interim1(struct torture_context *tctx,
				   struct smb2_tree *tree)
{
    struct smb2_handle hd;
    struct smb2_create cr;
    NTSTATUS status = NT_STATUS_OK;
    const char *dname = "compound_interim_dir";
    struct smb2_notify nt;
    bool ret = true;
    struct smb2_request *req[2];

    /* Win7 compound request implementation deviates substantially from the
     * SMB2 spec as noted in MS-SMB2 <159>, <162>.  This, test currently
     * verifies the Windows behavior, not the general spec behavior. */

    smb2_transport_credits_ask_num(tree->session->transport, 5);

    smb2_deltree(tree, dname);

    smb2_transport_credits_ask_num(tree->session->transport, 1);

    ZERO_STRUCT(cr);
    cr.in.desired_access	= SEC_RIGHTS_FILE_ALL;
    cr.in.create_options	= NTCREATEX_OPTIONS_DIRECTORY;
    cr.in.file_attributes	= FILE_ATTRIBUTE_DIRECTORY;
    cr.in.share_access		= NTCREATEX_SHARE_ACCESS_READ |
				  NTCREATEX_SHARE_ACCESS_WRITE |
				  NTCREATEX_SHARE_ACCESS_DELETE;
    cr.in.create_disposition	= NTCREATEX_DISP_CREATE;
    cr.in.fname			= dname;

    smb2_transport_compound_start(tree->session->transport, 2);

    req[0] = smb2_create_send(tree, &cr);

    smb2_transport_compound_set_related(tree->session->transport, true);

    hd.data[0] = UINT64_MAX;
    hd.data[1] = UINT64_MAX;

    ZERO_STRUCT(nt);
    nt.in.recursive          = true;
    nt.in.buffer_size        = 0x1000;
    nt.in.file.handle        = hd;
    nt.in.completion_filter  = FILE_NOTIFY_CHANGE_NAME;
    nt.in.unknown            = 0x00000000;

    req[1] = smb2_notify_send(tree, &nt);

    status = smb2_create_recv(req[0], tree, &cr);
    CHECK_STATUS(status, NT_STATUS_OK);

    smb2_cancel(req[1]);
    status = smb2_notify_recv(req[1], tree, &nt);
    CHECK_STATUS(status, NT_STATUS_CANCELLED);

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

    smb2_deltree(tree, dname);
done:
    return ret;
}
Ejemplo n.º 12
0
/* basic testing of all SMB2 setinfo calls 
   for each call we test that it succeeds, and where possible test 
   for consistency between the calls. 
*/
BOOL torture_smb2_setinfo(struct torture_context *torture)
{
	struct smb2_tree *tree;
	BOOL ret = True;
	TALLOC_CTX *mem_ctx = talloc_new(NULL);
	struct smb2_handle handle;
	char *fname;
	char *fname_new;
	union smb_fileinfo finfo2;
	union smb_setfileinfo sfinfo;
	struct security_ace ace;
	struct security_descriptor *sd;
	struct dom_sid *test_sid;
	NTSTATUS status, status2=NT_STATUS_OK;
	const char *call_name;
	time_t basetime = (time(NULL) - 86400) & ~1;
	int n = time(NULL) % 100;
	
	ZERO_STRUCT(handle);
	
	fname = talloc_asprintf(mem_ctx, BASEDIR "fnum_test_%d.txt", n);
	fname_new = talloc_asprintf(mem_ctx, BASEDIR "fnum_test_new_%d.txt", n);

	if (!torture_smb2_connection(mem_ctx, &tree)) {
		return False;
	}

#define RECREATE_FILE(fname) do { \
	smb2_util_close(tree, handle); \
	status = smb2_create_complex_file(tree, fname, &handle); \
	if (!NT_STATUS_IS_OK(status)) { \
		printf("(%s) ERROR: open of %s failed (%s)\n", \
		       __location__, fname, nt_errstr(status)); \
		ret = False; \
		goto done; \
	}} while (0)

#define RECREATE_BOTH do { \
		RECREATE_FILE(fname); \
	} while (0)

	RECREATE_BOTH;
	
#define CHECK_CALL(call, rightstatus) do { \
	call_name = #call; \
	sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
	sfinfo.generic.in.file.handle = handle; \
	status = smb2_setinfo_file(tree, &sfinfo); \
	if (!NT_STATUS_EQUAL(status, rightstatus)) { \
		printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
			nt_errstr(status), nt_errstr(rightstatus)); \
		ret = False; \
		goto done; \
	} \
	} while (0)

#define CHECK1(call) \
	do { if (NT_STATUS_IS_OK(status)) { \
		finfo2.generic.level = RAW_FILEINFO_ ## call; \
		finfo2.generic.in.file.handle = handle; \
		status2 = smb2_getinfo_file(tree, mem_ctx, &finfo2); \
		if (!NT_STATUS_IS_OK(status2)) { \
			printf("(%s) %s - %s\n", __location__, #call, nt_errstr(status2)); \
		ret = False; \
		goto done; \
		} \
	}} while (0)

#define CHECK_VALUE(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		       call_name, #stype, #field, \
		       (uint_t)value, (uint_t)finfo2.stype.out.field); \
		torture_smb2_all_info(tree, handle); \
		ret = False; \
		goto done; \
	}} while (0)

#define CHECK_TIME(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		        call_name, #stype, #field, \
		        (uint_t)value, \
			(uint_t)nt_time_to_unix(finfo2.stype.out.field)); \
		printf("\t%s", timestring(mem_ctx, value)); \
		printf("\t%s\n", nt_time_string(mem_ctx, finfo2.stype.out.field)); \
		torture_smb2_all_info(tree, handle); \
		ret = False; \
		goto done; \
	}} while (0)

#define CHECK_STATUS(status, correct) do { \
	if (!NT_STATUS_EQUAL(status, correct)) { \
		printf("(%s) Incorrect status %s - should be %s\n", \
		       __location__, nt_errstr(status), nt_errstr(correct)); \
		ret = False; \
		goto done; \
	}} while (0)

	torture_smb2_all_info(tree, handle);
	
	printf("test basic_information level\n");
	basetime += 86400;
	unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
	unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
	unix_to_nt_time(&sfinfo.basic_info.in.write_time,  basetime + 300);
	unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time,  basetime + 300);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib,     FILE_ATTRIBUTE_READONLY);

	printf("a zero time means don't change\n");
	unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
	unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
	unix_to_nt_time(&sfinfo.basic_info.in.write_time,  0);
	unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time,  basetime + 300);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib,     FILE_ATTRIBUTE_NORMAL);

	printf("change the attribute\n");
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);

	printf("zero attrib means don't change\n");
	sfinfo.basic_info.in.attrib = 0;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);

	printf("restore attribute\n");
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL);

	printf("test disposition_information level\n");
	sfinfo.disposition_info.in.delete_on_close = 1;
	CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 1);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 0);

	sfinfo.disposition_info.in.delete_on_close = 0;
	CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 0);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 1);

	printf("test allocation_information level\n");
	sfinfo.allocation_info.in.alloc_size = 0;
	CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 0);

	sfinfo.allocation_info.in.alloc_size = 4096;
	CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 4096);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);

	printf("test end_of_file_info level\n");
	sfinfo.end_of_file_info.in.size = 37;
	CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 37);

	sfinfo.end_of_file_info.in.size = 7;
	CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 7);

	printf("test position_information level\n");
	sfinfo.position_information.in.position = 123456;
	CHECK_CALL(POSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, position, 123456);

	printf("test mode_information level\n");
	sfinfo.mode_information.in.mode = 2;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, mode, 2);

	sfinfo.mode_information.in.mode = 1;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);

	sfinfo.mode_information.in.mode = 0;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);

	printf("test sec_desc level\n");
	ZERO_STRUCT(finfo2);
	finfo2.query_secdesc.in.secinfo_flags =
		SECINFO_OWNER |
		SECINFO_GROUP |
		SECINFO_DACL;
 	CHECK1(SEC_DESC);
	sd = finfo2.query_secdesc.out.sd;

	test_sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1234-5432");
	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_STD_ALL;
	ace.trustee = *test_sid;
	status = security_descriptor_dacl_add(sd, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	printf("add a new ACE to the DACL\n");

	sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
	sfinfo.set_secdesc.in.sd = sd;
	CHECK_CALL(SEC_DESC, NT_STATUS_OK);
 	CHECK1(SEC_DESC);

	if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) {
		printf("%s: security descriptors don't match!\n", __location__);
		printf("got:\n");
		NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd);
		printf("expected:\n");
		NDR_PRINT_DEBUG(security_descriptor, sd);
		ret = False;
	}

	printf("remove it again\n");

	status = security_descriptor_dacl_del(sd, test_sid);
	CHECK_STATUS(status, NT_STATUS_OK);

	sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
	sfinfo.set_secdesc.in.sd = sd;
	CHECK_CALL(SEC_DESC, NT_STATUS_OK);
 	CHECK1(SEC_DESC);

	if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) {
		printf("%s: security descriptors don't match!\n", __location__);
		printf("got:\n");
		NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd);
		printf("expected:\n");
		NDR_PRINT_DEBUG(security_descriptor, sd);
		ret = False;
	}

done:
	status = smb2_util_close(tree, handle);
	if (NT_STATUS_IS_ERR(status)) {
		printf("Failed to delete %s - %s\n", fname, nt_errstr(status));
	}
	smb2_util_unlink(tree, fname);

	talloc_free(mem_ctx);
	return ret;
}
Ejemplo n.º 13
0
static BOOL test_valid_request(TALLOC_CTX *mem_ctx, struct smb2_tree *tree)
{
	BOOL ret = True;
	NTSTATUS status;
	struct smb2_handle dh;
	struct smb2_notify n;
	struct smb2_request *req;

	status = smb2_util_roothandle(tree, &dh);
	CHECK_STATUS(status, NT_STATUS_OK);

	n.in.recursive		= 0x0000;
	n.in.buffer_size	= 0x00080000;
	n.in.file.handle	= dh;
	n.in.completion_filter	= 0x00000FFF;
	n.in.unknown		= 0x00000000;
	req = smb2_notify_send(tree, &n);

	while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
		if (event_loop_once(req->transport->socket->event.ctx) != 0) {
			break;
		}
	}

	status = torture_setup_complex_file(tree, FNAME);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb2_notify_recv(req, mem_ctx, &n);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(n.out.num_changes, 1);
	CHECK_VALUE(n.out.changes[0].action, NOTIFY_ACTION_REMOVED);
	CHECK_WIRE_STR(n.out.changes[0].name, FNAME);

	/* 
	 * if the change response doesn't fit in the buffer
	 * NOTIFY_ENUM_DIR is returned.
	 */
	n.in.buffer_size	= 0x00000000;
	req = smb2_notify_send(tree, &n);

	while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
		if (event_loop_once(req->transport->socket->event.ctx) != 0) {
			break;
		}
	}

	status = torture_setup_complex_file(tree, FNAME);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb2_notify_recv(req, mem_ctx, &n);
	CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR);

	/* 
	 * if the change response fits in the buffer we get
	 * NT_STATUS_OK again
	 */
	n.in.buffer_size	= 0x00080000;
	req = smb2_notify_send(tree, &n);

	while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
		if (event_loop_once(req->transport->socket->event.ctx) != 0) {
			break;
		}
	}

	status = torture_setup_complex_file(tree, FNAME);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb2_notify_recv(req, mem_ctx, &n);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_VALUE(n.out.num_changes, 3);
	CHECK_VALUE(n.out.changes[0].action, NOTIFY_ACTION_REMOVED);
	CHECK_WIRE_STR(n.out.changes[0].name, FNAME);
	CHECK_VALUE(n.out.changes[1].action, NOTIFY_ACTION_ADDED);
	CHECK_WIRE_STR(n.out.changes[1].name, FNAME);
	CHECK_VALUE(n.out.changes[2].action, NOTIFY_ACTION_MODIFIED);
	CHECK_WIRE_STR(n.out.changes[2].name, FNAME);

	/* if the first notify returns NOTIFY_ENUM_DIR, all do */
	status = smb2_util_close(tree, dh);
	CHECK_STATUS(status, NT_STATUS_OK);
	status = smb2_util_roothandle(tree, &dh);
	CHECK_STATUS(status, NT_STATUS_OK);

	n.in.recursive		= 0x0000;
	n.in.buffer_size	= 0x00000001;
	n.in.file.handle	= dh;
	n.in.completion_filter	= 0x00000FFF;
	n.in.unknown		= 0x00000000;
	req = smb2_notify_send(tree, &n);

	while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
		if (event_loop_once(req->transport->socket->event.ctx) != 0) {
			break;
		}
	}

	status = torture_setup_complex_file(tree, FNAME);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb2_notify_recv(req, mem_ctx, &n);
	CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR);

	n.in.buffer_size	= 0x00080000;
	req = smb2_notify_send(tree, &n);
	while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) {
		if (event_loop_once(req->transport->socket->event.ctx) != 0) {
			break;
		}
	}

	status = torture_setup_complex_file(tree, FNAME);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb2_notify_recv(req, mem_ctx, &n);
	CHECK_STATUS(status, STATUS_NOTIFY_ENUM_DIR);

	/* if the buffer size is too large, we get invalid parameter */
	n.in.recursive		= 0x0000;
	n.in.buffer_size	= 0x00080001;
	n.in.file.handle	= dh;
	n.in.completion_filter	= 0x00000FFF;
	n.in.unknown		= 0x00000000;
	req = smb2_notify_send(tree, &n);
	status = smb2_notify_recv(req, mem_ctx, &n);
	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

done:
	return ret;
}
Ejemplo n.º 14
0
/**
 * do reauth with wrong credentials,
 * hence triggering the error path in reauth.
 * The invalid reauth deletes the session.
 */
bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	char *corrupted_password;
	struct cli_credentials *broken_creds;
	bool ok;
	bool encrypted;
	NTSTATUS expected;
	enum credentials_use_kerberos krb_state;

	krb_state = cli_credentials_get_kerberos_state(cmdline_credentials);
	if (krb_state == CRED_MUST_USE_KERBEROS) {
		torture_skip(tctx,
			     "Can't test failing session setup with kerberos.");
	}

	encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/*
	 * reauthentication with invalid credentials:
	 */

	broken_creds = cli_credentials_shallow_copy(mem_ctx,
						    cmdline_credentials);
	torture_assert(tctx, (broken_creds != NULL), "talloc error");

	corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
				cli_credentials_get_password(broken_creds),
				"corrupt");
	torture_assert(tctx, (corrupted_password != NULL), "talloc error");

	ok = cli_credentials_set_password(broken_creds, corrupted_password,
					  CRED_SPECIFIED);
	CHECK_VAL(ok, true);

	status = smb2_session_setup_spnego(tree->session,
					   broken_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);

	torture_comment(tctx, "did failed reauth\n");
	/*
	 * now verify that the invalid session reauth has closed our session
	 */

	if (encrypted) {
		expected = NT_STATUS_CONNECTION_DISCONNECTED;
	} else {
		expected = NT_STATUS_USER_SESSION_DELETED;
	}

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, expected);

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 15
0
/*
  try creating with acls
 */
static bool test_create_acl_ext(struct torture_context *tctx, struct smb2_tree *tree, bool test_dir)
{
    bool ret = true;
    struct smb2_create io;
    NTSTATUS status;
    struct security_ace ace;
    struct security_descriptor *sd;
    struct dom_sid *test_sid;
    union smb_fileinfo q = {};
    uint32_t attrib =
        FILE_ATTRIBUTE_HIDDEN |
        FILE_ATTRIBUTE_SYSTEM |
        (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
    NTSTATUS (*delete_func)(struct smb2_tree *, const char *) =
        test_dir ? smb2_util_rmdir : smb2_util_unlink;

    smb2_deltree(tree, FNAME);

    ZERO_STRUCT(io);
    io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
    io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
    io.in.create_disposition = NTCREATEX_DISP_CREATE;
    io.in.share_access =
        NTCREATEX_SHARE_ACCESS_DELETE |
        NTCREATEX_SHARE_ACCESS_READ |
        NTCREATEX_SHARE_ACCESS_WRITE;
    io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT | 0x00200000 |
                           (test_dir ?  NTCREATEX_OPTIONS_DIRECTORY :
                            (NTCREATEX_OPTIONS_NON_DIRECTORY_FILE));

    io.in.fname = FNAME;

    torture_comment(tctx, "basic create\n");

    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    q.query_secdesc.in.file.handle = io.out.file.handle;
    q.query_secdesc.in.secinfo_flags =
        SECINFO_OWNER |
        SECINFO_GROUP |
        SECINFO_DACL;
    status = smb2_getinfo_file(tree, tctx, &q);
    CHECK_STATUS(status, NT_STATUS_OK);
    sd = q.query_secdesc.out.sd;

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);
    status = delete_func(tree, FNAME);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "adding a new ACE\n");
    test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);

    ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
    ace.flags = 0;
    ace.access_mask = SEC_STD_ALL;
    ace.trustee = *test_sid;

    status = security_descriptor_dacl_add(sd, &ace);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "creating a file with an initial ACL\n");

    io.in.sec_desc = sd;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);
    status = delete_func(tree, FNAME);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "creating with attributes\n");

    io.in.sec_desc = NULL;
    io.in.file_attributes = attrib;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);
    status = delete_func(tree, FNAME);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "creating with attributes and ACL\n");

    io.in.sec_desc = sd;
    io.in.file_attributes = attrib;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
    FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);
    status = delete_func(tree, FNAME);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "creating with attributes, ACL and owner\n");
    sd = security_descriptor_dacl_create(tctx,
                                         0, SID_WORLD, SID_BUILTIN_USERS,
                                         SID_WORLD,
                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
                                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
                                         0,
                                         NULL);

    io.in.sec_desc = sd;
    io.in.file_attributes = attrib;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
    FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));

done:
    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);
    status = delete_func(tree, FNAME);
    CHECK_STATUS(status, NT_STATUS_OK);

    return ret;
}
Ejemplo n.º 16
0
/*
  try the various request blobs
 */
static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tree)
{
    struct smb2_create io;
    NTSTATUS status;

    smb2_deltree(tree, FNAME);

    ZERO_STRUCT(io);
    io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
    io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
    io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    io.in.share_access =
        NTCREATEX_SHARE_ACCESS_DELETE|
        NTCREATEX_SHARE_ACCESS_READ|
        NTCREATEX_SHARE_ACCESS_WRITE;
    io.in.create_options		= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
                                  NTCREATEX_OPTIONS_ASYNC_ALERT	|
                                  NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
                                  0x00200000;
    io.in.fname = FNAME;

    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Testing alloc size\n");
    io.in.alloc_size = 4096;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Testing durable open\n");
    io.in.durable_open = true;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Testing query maximal access\n");
    io.in.query_maximal_access = true;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Testing timewarp\n");
    io.in.timewarp = 10000;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    io.in.timewarp = 0;

    torture_comment(tctx, "Testing query_on_disk\n");
    io.in.query_on_disk_id = true;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Testing unknown tag\n");
    status = smb2_create_blob_add(tctx, &io.in.blobs,
                                  "FooO", data_blob(NULL, 0));
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "Testing bad tag length\n");
    status = smb2_create_blob_add(tctx, &io.in.blobs,
                                  "xxx", data_blob(NULL, 0));
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    smb2_deltree(tree, FNAME);

    return true;
}
Ejemplo n.º 17
0
/*
  test some interesting combinations found by gentest
 */
static bool test_create_gentest(struct torture_context *tctx, struct smb2_tree *tree)
{
    struct smb2_create io;
    NTSTATUS status;
    uint32_t access_mask, file_attributes_set;
    uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
    uint32_t not_a_directory_mask, unexpected_mask;
    union smb_fileinfo q;

    ZERO_STRUCT(io);
    io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
    io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
    io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    io.in.share_access =
        NTCREATEX_SHARE_ACCESS_DELETE|
        NTCREATEX_SHARE_ACCESS_READ|
        NTCREATEX_SHARE_ACCESS_WRITE;
    io.in.create_options = 0;
    io.in.fname = FNAME;

    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    io.in.create_options = 0xF0000000;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    io.in.create_options = 0;

    io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    io.in.create_disposition = NTCREATEX_DISP_OPEN;
    io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    io.in.create_disposition = NTCREATEX_DISP_CREATE;
    io.in.desired_access = 0x08000000;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

    io.in.desired_access = 0x04000000;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

    io.in.file_attributes = 0;
    io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
    ok_mask = 0;
    not_supported_mask = 0;
    invalid_parameter_mask = 0;
    not_a_directory_mask = 0;
    unexpected_mask = 0;
    {
        int i;
        for (i=0; i<32; i++) {
            io.in.create_options = 1<<i;
            if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
                continue;
            }
            status = smb2_create(tree, tctx, &io);
            if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
                not_supported_mask |= 1<<i;
            } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
                invalid_parameter_mask |= 1<<i;
            } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
                not_a_directory_mask |= 1<<i;
            } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
                ok_mask |= 1<<i;
                status = smb2_util_close(tree, io.out.file.handle);
                CHECK_STATUS(status, NT_STATUS_OK);
            } else {
                unexpected_mask |= 1<<i;
                torture_comment(tctx,
                                "create option 0x%08x returned %s\n",
                                1<<i, nt_errstr(status));
            }
        }
    }
    io.in.create_options = 0;

    CHECK_EQUAL(ok_mask,                0x00efcf7e);
    CHECK_EQUAL(not_a_directory_mask,   0x00000001);
    CHECK_EQUAL(not_supported_mask,     0x00102080);
    CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
    CHECK_EQUAL(unexpected_mask,        0x00000000);

    io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    io.in.file_attributes = 0;
    access_mask = 0;
    {
        int i;
        for (i=0; i<32; i++) {
            io.in.desired_access = 1<<i;
            status = smb2_create(tree, tctx, &io);
            if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
                    NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
                access_mask |= io.in.desired_access;
            } else {
                CHECK_STATUS(status, NT_STATUS_OK);
                status = smb2_util_close(tree, io.out.file.handle);
                CHECK_STATUS(status, NT_STATUS_OK);
            }
        }
    }

    if (TARGET_IS_WIN7(tctx)) {
        CHECK_EQUAL(access_mask, 0x0de0fe00);
    } else if (torture_setting_bool(tctx, "samba4", false)) {
        CHECK_EQUAL(access_mask, 0x0cf0fe00);
    } else {
        CHECK_EQUAL(access_mask, 0x0df0fe00);
    }

    io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
    io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    io.in.file_attributes = 0;
    ok_mask = 0;
    invalid_parameter_mask = 0;
    unexpected_mask = 0;
    file_attributes_set = 0;
    {
        int i;
        for (i=0; i<32; i++) {
            io.in.file_attributes = 1<<i;
            if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
                continue;
            }
            smb2_deltree(tree, FNAME);
            status = smb2_create(tree, tctx, &io);
            if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
                invalid_parameter_mask |= 1<<i;
            } else if (NT_STATUS_IS_OK(status)) {
                uint32_t expected;
                ok_mask |= 1<<i;

                expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
                CHECK_EQUAL(io.out.file_attr, expected);
                file_attributes_set |= io.out.file_attr;

                status = smb2_util_close(tree, io.out.file.handle);
                CHECK_STATUS(status, NT_STATUS_OK);
            } else {
                unexpected_mask |= 1<<i;
                torture_comment(tctx,
                                "file attribute 0x%08x returned %s\n",
                                1<<i, nt_errstr(status));
            }
        }
    }

    CHECK_EQUAL(ok_mask,                0x00003fb7);
    CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
    CHECK_EQUAL(unexpected_mask,        0x00000000);
    CHECK_EQUAL(file_attributes_set,    0x00001127);

    smb2_deltree(tree, FNAME);

    /*
     * Standalone servers doesn't support encryption
     */
    io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
    status = smb2_create(tree, tctx, &io);
    if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
        torture_comment(tctx,
                        "FILE_ATTRIBUTE_ENCRYPTED returned %s\n",
                        nt_errstr(status));
    } else {
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
        status = smb2_util_close(tree, io.out.file.handle);
        CHECK_STATUS(status, NT_STATUS_OK);
    }

    smb2_deltree(tree, FNAME);

    ZERO_STRUCT(io);
    io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
    io.in.file_attributes    = 0;
    io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    io.in.share_access =
        NTCREATEX_SHARE_ACCESS_READ|
        NTCREATEX_SHARE_ACCESS_WRITE;
    io.in.create_options = 0;
    io.in.fname = FNAME ":stream1";
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_util_close(tree, io.out.file.handle);
    CHECK_STATUS(status, NT_STATUS_OK);

    io.in.fname = FNAME;
    io.in.file_attributes = 0x8040;
    io.in.share_access =
        NTCREATEX_SHARE_ACCESS_READ;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

    io.in.fname = FNAME;
    io.in.file_attributes = 0;
    io.in.desired_access  = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
    io.in.query_maximal_access = true;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);

    q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
    q.access_information.in.file.handle = io.out.file.handle;
    status = smb2_getinfo_file(tree, tctx, &q);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);

    io.in.file_attributes = 0;
    io.in.desired_access  = 0;
    io.in.query_maximal_access = false;
    io.in.share_access = 0;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

    smb2_deltree(tree, FNAME);

    return true;
}
Ejemplo n.º 18
0
/*
 * Test creating a file with a NULL DACL.
 */
static bool test_create_null_dacl(struct torture_context *tctx,
                                  struct smb2_tree *tree)
{
    NTSTATUS status;
    struct smb2_create io;
    const char *fname = "nulldacl.txt";
    bool ret = true;
    struct smb2_handle handle;
    union smb_fileinfo q;
    union smb_setfileinfo s;
    struct security_descriptor *sd = security_descriptor_initialise(tctx);
    struct security_acl dacl;

    torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");

    smb2_util_unlink(tree, fname);

    ZERO_STRUCT(io);
    io.level = RAW_OPEN_SMB2;
    io.in.create_flags = 0;
    io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
                           | SEC_STD_WRITE_OWNER;
    io.in.create_options = 0;
    io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    io.in.share_access =
        NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
    io.in.alloc_size = 0;
    io.in.create_disposition = NTCREATEX_DISP_CREATE;
    io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
    io.in.security_flags = 0;
    io.in.fname = fname;
    io.in.sec_desc = sd;
    /* XXX create_options ? */
    io.in.create_options		= NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
                                  NTCREATEX_OPTIONS_ASYNC_ALERT	|
                                  NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
                                  0x00200000;

    torture_comment(tctx, "creating a file with a empty sd\n");
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    handle = io.out.file.handle;

    torture_comment(tctx, "get the original sd\n");
    q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    q.query_secdesc.in.file.handle = handle;
    q.query_secdesc.in.secinfo_flags =
        SECINFO_OWNER |
        SECINFO_GROUP |
        SECINFO_DACL;
    status = smb2_getinfo_file(tree, tctx, &q);
    CHECK_STATUS(status, NT_STATUS_OK);

    /*
     * Testing the created DACL,
     * the server should add the inherited DACL
     * when SEC_DESC_DACL_PRESENT isn't specified
     */
    if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
        ret = false;
        torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    }
    if (q.query_secdesc.out.sd->dacl == NULL) {
        ret = false;
        torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    }

    torture_comment(tctx, "set NULL DACL\n");
    sd->type |= SEC_DESC_DACL_PRESENT;

    s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    s.set_secdesc.in.file.handle = handle;
    s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    s.set_secdesc.in.sd = sd;
    status = smb2_setinfo_file(tree, &s);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "get the sd\n");
    q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    q.query_secdesc.in.file.handle = handle;
    q.query_secdesc.in.secinfo_flags =
        SECINFO_OWNER |
        SECINFO_GROUP |
        SECINFO_DACL;
    status = smb2_getinfo_file(tree, tctx, &q);
    CHECK_STATUS(status, NT_STATUS_OK);

    /* Testing the modified DACL */
    if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
        ret = false;
        torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    }
    if (q.query_secdesc.out.sd->dacl != NULL) {
        ret = false;
        torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    }

    io.in.create_disposition = NTCREATEX_DISP_OPEN;

    torture_comment(tctx, "try open for read control\n");
    io.in.desired_access = SEC_STD_READ_CONTROL;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_ACCESS_FLAGS(io.out.file.handle,
                       SEC_STD_READ_CONTROL);
    smb2_util_close(tree, io.out.file.handle);

    torture_comment(tctx, "try open for write\n");
    io.in.desired_access = SEC_FILE_WRITE_DATA;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_ACCESS_FLAGS(io.out.file.handle,
                       SEC_FILE_WRITE_DATA);
    smb2_util_close(tree, io.out.file.handle);

    torture_comment(tctx, "try open for read\n");
    io.in.desired_access = SEC_FILE_READ_DATA;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_ACCESS_FLAGS(io.out.file.handle,
                       SEC_FILE_READ_DATA);
    smb2_util_close(tree, io.out.file.handle);

    torture_comment(tctx, "try open for generic write\n");
    io.in.desired_access = SEC_GENERIC_WRITE;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_ACCESS_FLAGS(io.out.file.handle,
                       SEC_RIGHTS_FILE_WRITE);
    smb2_util_close(tree, io.out.file.handle);

    torture_comment(tctx, "try open for generic read\n");
    io.in.desired_access = SEC_GENERIC_READ;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_ACCESS_FLAGS(io.out.file.handle,
                       SEC_RIGHTS_FILE_READ);
    smb2_util_close(tree, io.out.file.handle);

    torture_comment(tctx, "set DACL with 0 aces\n");
    ZERO_STRUCT(dacl);
    dacl.revision = SECURITY_ACL_REVISION_NT4;
    dacl.num_aces = 0;
    sd->dacl = &dacl;

    s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    s.set_secdesc.in.file.handle = handle;
    s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    s.set_secdesc.in.sd = sd;
    status = smb2_setinfo_file(tree, &s);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "get the sd\n");
    q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    q.query_secdesc.in.file.handle = handle;
    q.query_secdesc.in.secinfo_flags =
        SECINFO_OWNER |
        SECINFO_GROUP |
        SECINFO_DACL;
    status = smb2_getinfo_file(tree, tctx, &q);
    CHECK_STATUS(status, NT_STATUS_OK);

    /* Testing the modified DACL */
    if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
        ret = false;
        torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    }
    if (q.query_secdesc.out.sd->dacl == NULL) {
        ret = false;
        torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
    }
    if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
        torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
                       q.query_secdesc.out.sd->dacl->num_aces);
        ret = false;
        goto done;
    }

    torture_comment(tctx, "try open for read control\n");
    io.in.desired_access = SEC_STD_READ_CONTROL;
    status = smb2_create(tree, tctx, &io);
    CHECK_STATUS(status, NT_STATUS_OK);
    CHECK_ACCESS_FLAGS(io.out.file.handle,
                       SEC_STD_READ_CONTROL);
    smb2_util_close(tree, io.out.file.handle);

    torture_comment(tctx, "try open for write => access_denied\n");
    io.in.desired_access = SEC_FILE_WRITE_DATA;
    status = smb2_create(tree, tctx, &io);
    if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
        CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    } else {
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    }

    torture_comment(tctx, "try open for read => access_denied\n");
    io.in.desired_access = SEC_FILE_READ_DATA;
    status = smb2_create(tree, tctx, &io);
    if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
        CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    } else {
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    }

    torture_comment(tctx, "try open for generic write => access_denied\n");
    io.in.desired_access = SEC_GENERIC_WRITE;
    status = smb2_create(tree, tctx, &io);
    if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
        CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    } else {
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    }

    torture_comment(tctx, "try open for generic read => access_denied\n");
    io.in.desired_access = SEC_GENERIC_READ;
    status = smb2_create(tree, tctx, &io);
    if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
        CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
    } else {
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
    }

    torture_comment(tctx, "set empty sd\n");
    sd->type &= ~SEC_DESC_DACL_PRESENT;
    sd->dacl = NULL;

    s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
    s.set_secdesc.in.file.handle = handle;
    s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
    s.set_secdesc.in.sd = sd;
    status = smb2_setinfo_file(tree, &s);
    CHECK_STATUS(status, NT_STATUS_OK);

    torture_comment(tctx, "get the sd\n");
    q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
    q.query_secdesc.in.file.handle = handle;
    q.query_secdesc.in.secinfo_flags =
        SECINFO_OWNER |
        SECINFO_GROUP |
        SECINFO_DACL;
    status = smb2_getinfo_file(tree, tctx, &q);
    CHECK_STATUS(status, NT_STATUS_OK);

    /* Testing the modified DACL */
    if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
        ret = false;
        torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
    }
    if (q.query_secdesc.out.sd->dacl != NULL) {
        ret = false;
        torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
    }
done:
    smb2_util_close(tree, handle);
    smb2_util_unlink(tree, fname);
    smb2_tdis(tree);
    smb2_logoff(tree->session);
    return ret;
}
Ejemplo n.º 19
0
bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
{
    NTSTATUS status;
    TALLOC_CTX *mem_ctx = talloc_new(tctx);
    char fname[256];
    struct smb2_handle _h1;
    struct smb2_handle *h1 = NULL;
    struct smb2_create io1;
    bool ret = true;
    union smb_fileinfo qfinfo;
    struct cli_credentials *anon_creds = NULL;

    /* Add some random component to the file name. */
    snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
             generate_random_str(tctx, 8));

    smb2_util_unlink(tree, fname);

    smb2_oplock_create_share(&io1, fname,
                             smb2_util_share_access(""),
                             smb2_util_oplock_level("b"));

    status = smb2_create(tree, mem_ctx, &io1);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_create failed");
    _h1 = io1.out.file.handle;
    h1 = &_h1;
    CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    torture_assert_int_equal(tctx, io1.out.oplock_level,
                             smb2_util_oplock_level("b"),
                             "oplock_level incorrect");

    /* re-authenticate as anonymous */

    anon_creds = cli_credentials_init_anon(mem_ctx);
    torture_assert(tctx, (anon_creds != NULL), "talloc error");

    status = smb2_session_setup_spnego(tree->session,
                                       anon_creds,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    /* try to access the file via the old handle */

    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

    /* re-authenticate as original user again */

    status = smb2_session_setup_spnego(tree->session,
                                       cmdline_credentials,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    /* try to access the file via the old handle */

    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

done:
    if (h1 != NULL) {
        smb2_util_close(tree, *h1);
    }

    smb2_util_unlink(tree, fname);

    talloc_free(tree);

    talloc_free(mem_ctx);

    return ret;
}
Ejemplo n.º 20
0
bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
{
    const char *host = torture_setting_string(tctx, "host", NULL);
    const char *share = torture_setting_string(tctx, "share", NULL);
    struct cli_credentials *credentials = cmdline_credentials;
    NTSTATUS status;
    TALLOC_CTX *mem_ctx = talloc_new(tctx);
    char fname[256];
    struct smb2_handle _h1;
    struct smb2_handle *h1 = NULL;
    struct smb2_create io1;
    union smb_fileinfo qfinfo;
    bool ret = false;
    struct smb2_tree *tree2 = NULL;
    struct smb2_transport *transport1 = tree1->session->transport;
    struct smb2_transport *transport2 = NULL;
    struct smb2_session *session1_1 = tree1->session;
    struct smb2_session *session1_2 = NULL;
    struct smb2_session *session2_1 = NULL;
    struct smb2_session *session2_2 = NULL;
    uint32_t caps;

    caps = smb2cli_conn_server_capabilities(transport1->conn);
    if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
        torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
    }

    /* Add some random component to the file name. */
    snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
             generate_random_str(tctx, 8));

    smb2_util_unlink(tree1, fname);

    smb2_oplock_create_share(&io1, fname,
                             smb2_util_share_access(""),
                             smb2_util_oplock_level("b"));

    status = smb2_create(tree1, mem_ctx, &io1);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_create failed");
    _h1 = io1.out.file.handle;
    h1 = &_h1;
    CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    torture_assert_int_equal(tctx, io1.out.oplock_level,
                             smb2_util_oplock_level("b"),
                             "oplock_level incorrect");

    status = smb2_connect(tctx,
                          host,
                          lpcfg_smb_ports(tctx->lp_ctx),
                          share,
                          lpcfg_resolve_context(tctx->lp_ctx),
                          credentials,
                          &tree2,
                          tctx->ev,
                          &transport1->options,
                          lpcfg_socket_options(tctx->lp_ctx),
                          lpcfg_gensec_settings(tctx, tctx->lp_ctx)
                         );
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_connect failed");
    session2_2 = tree2->session;
    transport2 = tree2->session->transport;

    /*
     * Now bind the 2nd transport connection to the 1st session
     */
    session1_2 = smb2_session_channel(transport2,
                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx),
                                      tree2,
                                      session1_1);
    torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");

    status = smb2_session_setup_spnego(session1_2,
                                       cmdline_credentials,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    /* use the 1st connection, 1st session */
    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    tree1->session = session1_1;
    status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

    /* use the 2nd connection, 1st session */
    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    tree1->session = session1_2;
    status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

    tree1->session = session1_1;
    status = smb2_util_close(tree1, *h1);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_util_close failed");
    h1 = NULL;

    /*
     * Now bind the 1st transport connection to the 2nd session
     */
    session2_1 = smb2_session_channel(transport1,
                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx),
                                      tree1,
                                      session2_2);
    torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");

    status = smb2_session_setup_spnego(session2_1,
                                       cmdline_credentials,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    tree2->session = session2_1;
    status = smb2_util_unlink(tree2, fname);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_util_unlink failed");
    ret = true;
done:
    talloc_free(tree2);
    tree1->session = session1_1;

    if (h1 != NULL) {
        smb2_util_close(tree1, *h1);
    }

    smb2_util_unlink(tree1, fname);

    talloc_free(tree1);

    talloc_free(mem_ctx);

    return ret;
}
Ejemplo n.º 21
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;
}
Ejemplo n.º 22
0
/**
 * test renaming after reauth.
 * compare security descriptors before and after rename/reauth
 */
bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char dname[256];
	char fname[256];
	char fname2[256];
	struct smb2_handle _dh1;
	struct smb2_handle *dh1 = NULL;
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	bool ok;
	union smb_fileinfo qfinfo;
	union smb_setfileinfo sfinfo;
	struct cli_credentials *anon_creds = NULL;
	uint32_t secinfo_flags = SECINFO_OWNER
				| SECINFO_GROUP
				| SECINFO_DACL
				| SECINFO_PROTECTED_DACL
				| SECINFO_UNPROTECTED_DACL;
	struct security_descriptor *f_sd1;
	struct security_descriptor *d_sd1 = NULL;
	struct security_ace ace;
	struct dom_sid *extra_sid;

	/* Add some random component to the file name. */
	snprintf(dname, 256, "session_reauth5_%s.d",
		 generate_random_str(tctx, 8));
	snprintf(fname, 256, "%s\\file.dat", dname);

	ok = smb2_util_setup_dir(tctx, tree, dname);
	CHECK_VAL(ok, true);

	status = torture_smb2_testdir(tree, dname, &_dh1);
	CHECK_STATUS(status, NT_STATUS_OK);
	dh1 = &_dh1;

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	f_sd1 = qfinfo.query_secdesc.out.sd;

	/* re-authenticate as anonymous */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to rename the file: fails */

	snprintf(fname2, 256, "%s\\file2.dat", dname);

	smb2_util_unlink(tree, fname2);

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

	/* re-authenticate as original user again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* give full access on the file to anonymous */

	extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);

	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_RIGHTS_FILE_ALL;
	ace.trustee = *extra_sid;

	status = security_descriptor_dacl_add(f_sd1, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(sfinfo);
	sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
	sfinfo.set_secdesc.in.file.handle = _h1;
	sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
	sfinfo.set_secdesc.in.sd = f_sd1;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-authenticate as anonymous - again */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to rename the file: fails */

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

	/* give full access on the parent dir to anonymous */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _dh1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	d_sd1 = qfinfo.query_secdesc.out.sd;

	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_RIGHTS_FILE_ALL;
	ace.trustee = *extra_sid;

	status = security_descriptor_dacl_add(d_sd1, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(sfinfo);
	sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
	sfinfo.set_secdesc.in.file.handle = _dh1;
	sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
	sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
	sfinfo.set_secdesc.in.sd = d_sd1;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _dh1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	smb2_util_close(tree, _dh1);
	dh1 = NULL;

	/* try to rename the file: still fails */

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

	/* re-authenticate as original user - again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* rename the file - for verification that it works */

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* closs the file, check it is gone and reopen under the new name */

	smb2_util_close(tree, _h1);

	ZERO_STRUCT(io1);

	smb2_generic_create_share(&io1,
				  NULL /* lease */, false /* dir */,
				  fname,
				  NTCREATEX_DISP_OPEN,
				  smb2_util_share_access(""),
				  smb2_util_oplock_level("b"),
				  0 /* leasekey */, 0 /* leasestate */);

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	ZERO_STRUCT(io1);

	smb2_generic_create_share(&io1,
				  NULL /* lease */, false /* dir */,
				  fname2,
				  NTCREATEX_DISP_OPEN,
				  smb2_util_share_access(""),
				  smb2_util_oplock_level("b"),
				  0 /* leasekey */, 0 /* leasestate */);

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

done:
	if (dh1 != NULL) {
		smb2_util_close(tree, *dh1);
	}
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_deltree(tree, dname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 23
0
/**
 * basic test for doing a session reconnect
 */
bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_handle _h2;
	struct smb2_handle *h2 = NULL;
	struct smb2_create io1, io2;
	uint64_t previous_session_id;
	bool ret = true;
	struct smb2_tree *tree2;
	union smb_fileinfo qfinfo;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reconnect_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* disconnect, reconnect and then do durable reopen */
	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);

	if (!torture_smb2_connection_ext(tctx, previous_session_id,
					 &tree->session->transport->options,
					 &tree2))
	{
		torture_warning(tctx, "session reconnect failed\n");
		ret = false;
		goto done;
	}

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
	h1 = NULL;

	smb2_oplock_create_share(&io2, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree2, mem_ctx, &io2);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
	_h2 = io2.out.file.handle;
	h2 = &_h2;

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}
	if (h2 != NULL) {
		smb2_util_close(tree2, *h2);
	}

	smb2_util_unlink(tree2, fname);

	talloc_free(tree);
	talloc_free(tree2);

	talloc_free(mem_ctx);

	return ret;
}
Ejemplo n.º 24
0
static bool test_default_acl_posix(struct torture_context *tctx,
				   struct smb2_tree *tree_unused)
{
	struct smb2_tree *tree = NULL;
	NTSTATUS status;
	bool ok;
	bool ret = true;
	const char *dname = BASEDIR "\\testdir";
	const char *fname = BASEDIR "\\testdir\\testfile";
	struct smb2_handle fhandle = {{0}};
	struct smb2_handle dhandle = {{0}};
	union smb_fileinfo q;
	union smb_setfileinfo set;
	struct security_descriptor *sd = NULL;
	struct security_descriptor *exp_sd = NULL;
	char *owner_sid = NULL;
	char *group_sid = NULL;

	ok = torture_smb2_con_share(tctx, "acl_xattr_ign_sysacl_posix", &tree);
	torture_assert_goto(tctx, ok == true, ret, done,
			    "Unable to connect to 'acl_xattr_ign_sysacl_posix'\n");

	ok = smb2_util_setup_dir(tctx, tree, BASEDIR);
	torture_assert_goto(tctx, ok == true, ret, done, "Unable to setup testdir\n");

	ZERO_STRUCT(dhandle);
	status = torture_smb2_testdir(tree, dname, &dhandle);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "torture_smb2_testdir\n");

	torture_comment(tctx, "Get the original sd\n");

	ZERO_STRUCT(q);
	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	q.query_secdesc.in.file.handle = dhandle;
	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
	status = smb2_getinfo_file(tree, tctx, &q);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n");

	sd = q.query_secdesc.out.sd;
	owner_sid = dom_sid_string(tctx, sd->owner_sid);
	group_sid = dom_sid_string(tctx, sd->group_sid);
	torture_comment(tctx, "owner [%s] group [%s]\n", owner_sid, group_sid);

	torture_comment(tctx, "Set ACL with no inheritable ACE\n");

	sd = security_descriptor_dacl_create(tctx,
					     0, NULL, NULL,
					     owner_sid,
					     SEC_ACE_TYPE_ACCESS_ALLOWED,
					     SEC_RIGHTS_DIR_ALL,
					     0,
					     NULL);

	ZERO_STRUCT(set);
	set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
	set.set_secdesc.in.file.handle = dhandle;
	set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
	set.set_secdesc.in.sd = sd;
	status = smb2_setinfo_file(tree, &set);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_setinfo_file\n");

	TALLOC_FREE(sd);
	smb2_util_close(tree, dhandle);

	torture_comment(tctx, "Create file\n");

	ZERO_STRUCT(fhandle);
	status = torture_smb2_testfile(tree, fname, &fhandle);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_create_complex_file\n");

	torture_comment(tctx, "Query file SD\n");

	ZERO_STRUCT(q);
	q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	q.query_secdesc.in.file.handle = fhandle;
	q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP;
	status = smb2_getinfo_file(tree, tctx, &q);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_getinfo_file\n");
	sd = q.query_secdesc.out.sd;

	smb2_util_close(tree, fhandle);
	ZERO_STRUCT(fhandle);

	torture_comment(tctx, "Checking actual file SD against expected SD\n");

	exp_sd = security_descriptor_dacl_create(
		tctx, 0, owner_sid, group_sid,
		owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0,
		group_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE, 0,
		SID_WORLD, SEC_ACE_TYPE_ACCESS_ALLOWED, FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE, 0,
		SID_NT_SYSTEM, SEC_ACE_TYPE_ACCESS_ALLOWED, SEC_RIGHTS_FILE_ALL, 0,
		NULL);

	CHECK_SECURITY_DESCRIPTOR(sd, exp_sd);

done:
	if (!smb2_util_handle_empty(fhandle)) {
		smb2_util_close(tree, fhandle);
	}
	if (!smb2_util_handle_empty(dhandle)) {
		smb2_util_close(tree, dhandle);
	}
	if (tree != NULL) {
		smb2_deltree(tree, BASEDIR);
		smb2_tdis(tree);
	}

	return ret;
}
Ejemplo n.º 25
0
static bool test_session_expire1(struct torture_context *tctx)
{
	NTSTATUS status;
	bool ret = false;
	struct smbcli_options options;
	const char *host = torture_setting_string(tctx, "host", NULL);
	const char *share = torture_setting_string(tctx, "share", NULL);
	struct cli_credentials *credentials = cmdline_credentials;
	struct smb2_tree *tree = NULL;
	enum credentials_use_kerberos use_kerberos;
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	union smb_fileinfo qfinfo;
	size_t i;

	use_kerberos = cli_credentials_get_kerberos_state(credentials);
	if (use_kerberos != CRED_MUST_USE_KERBEROS) {
		torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
		torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
	}

	torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
				 "please use -k yes");

	lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");

	lpcfg_smbcli_options(tctx->lp_ctx, &options);

	status = smb2_connect(tctx,
			      host,
			      lpcfg_smb_ports(tctx->lp_ctx),
			      share,
			      lpcfg_resolve_context(tctx->lp_ctx),
			      credentials,
			      &tree,
			      tctx->ev,
			      &options,
			      lpcfg_socket_options(tctx->lp_ctx),
			      lpcfg_gensec_settings(tctx, tctx->lp_ctx)
			      );
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
					"smb2_connect failed");

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_expire1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;

	status = smb2_create(tree, tctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
	qfinfo.access_information.in.file.handle = _h1;

	for (i=0; i < 2; i++) {
		torture_comment(tctx, "query info => OK\n");

		ZERO_STRUCT(qfinfo.access_information.out);
		status = smb2_getinfo_file(tree, tctx, &qfinfo);
		CHECK_STATUS(status, NT_STATUS_OK);

		torture_comment(tctx, "sleep 5 seconds\n");
		smb_msleep(5*1000);

		torture_comment(tctx, "query info => EXPIRED\n");
		ZERO_STRUCT(qfinfo.access_information.out);
		status = smb2_getinfo_file(tree, tctx, &qfinfo);
		CHECK_STATUS(status, NT_STATUS_NETWORK_SESSION_EXPIRED);

		/*
		 * the krb5 library may not handle expired creds
		 * well, lets start with an empty ccache.
		 */
		cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);

		torture_comment(tctx, "reauth => OK\n");
		status = smb2_session_setup_spnego(tree->session,
						   credentials,
						   0 /* previous_session_id */);
		CHECK_STATUS(status, NT_STATUS_OK);
	}

	ZERO_STRUCT(qfinfo.access_information.out);
	status = smb2_getinfo_file(tree, tctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	ret = true;
done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	talloc_free(tree);
	lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
	return ret;
}
Ejemplo n.º 26
0
/* 
   basic testing of SMB2 connection calls
*/
BOOL torture_smb2_connect(struct torture_context *torture)
{
	TALLOC_CTX *mem_ctx = talloc_new(NULL);
	struct smb2_tree *tree;
	struct smb2_handle h1, h2;
	NTSTATUS status;

	if (!torture_smb2_connection(mem_ctx, &tree)) {
		return False;
	}

	h1 = torture_smb2_create(tree, "test9.dat");
	h2 = torture_smb2_create(tree, "test9.dat");
	status = torture_smb2_write(tree, h1);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Write failed - %s\n", nt_errstr(status));
		return False;
	}
	status = torture_smb2_close(tree, h1);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Close failed - %s\n", nt_errstr(status));
		return False;
	}
	status = torture_smb2_close(tree, h2);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Close failed - %s\n", nt_errstr(status));
		return False;
	}

	status = smb2_util_close(tree, h1);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) {
		printf("close should have closed the handle - %s\n", nt_errstr(status));
		return False;
	}

	status = smb2_tdis(tree);
	if (!NT_STATUS_IS_OK(status)) {
		printf("tdis failed - %s\n", nt_errstr(status));
		return False;
	}

	status = smb2_tdis(tree);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) {
		printf("tdis should have disabled session - %s\n", nt_errstr(status));
		return False;
	}

 	status = smb2_logoff(tree->session);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Logoff failed - %s\n", nt_errstr(status));
		return False;
	}

	status = smb2_logoff(tree->session);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
		printf("Logoff should have disabled session - %s\n", nt_errstr(status));
		return False;
	}

	status = smb2_keepalive(tree->session->transport);
	if (!NT_STATUS_IS_OK(status)) {
		printf("keepalive failed? - %s\n", nt_errstr(status));
		return False;
	}

	talloc_free(mem_ctx);

	return True;
}
Ejemplo n.º 27
0
static bool test_smb2_open_brlocked(struct torture_context *tctx,
                                    struct smb2_tree *tree)
{
    union smb_open io, io1;
    union smb_lock io2;
    struct smb2_lock_element lock[1];
    const char *fname = DNAME "\\torture_ntcreatex.txt";
    NTSTATUS status;
    bool ret = true;
    struct smb2_handle h;
    char b = 42;

    torture_comment(tctx,
                    "Testing SMB2 open with a byte range locked file\n");

    smb2_util_unlink(tree, fname);

    status = torture_smb2_testdir(tree, DNAME, &h);
    CHECK_STATUS(status, NT_STATUS_OK);

    ZERO_STRUCT(io.smb2);
    io.generic.level = RAW_OPEN_SMB2;
    io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    io.smb2.in.desired_access = 0x2019f;
    io.smb2.in.alloc_size = 0;
    io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
                              NTCREATEX_SHARE_ACCESS_WRITE;
    io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
    io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
    io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
    io.smb2.in.fname = fname;

    status = smb2_create(tree, tctx, &(io.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);

    status = smb2_util_write(tree, io.smb2.out.file.handle, &b, 0, 1);
    CHECK_STATUS(status, NT_STATUS_OK);

    ZERO_STRUCT(io2.smb2);
    io2.smb2.level = RAW_LOCK_SMB2;
    io2.smb2.in.file.handle = io.smb2.out.file.handle;
    io2.smb2.in.lock_count = 1;

    ZERO_STRUCT(lock);
    lock[0].offset = 0;
    lock[0].length = 1;
    lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
                    SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
    io2.smb2.in.locks = &lock[0];
    status = smb2_lock(tree, &(io2.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);

    ZERO_STRUCT(io1.smb2);
    io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    io1.smb2.in.desired_access = 0x20196;
    io1.smb2.in.alloc_size = 0;
    io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
                               NTCREATEX_SHARE_ACCESS_WRITE;
    io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
    io1.smb2.in.create_options = 0;
    io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
    io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
    io1.smb2.in.fname = fname;

    status = smb2_create(tree, tctx, &(io1.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);

    smb2_util_close(tree, io.smb2.out.file.handle);
    smb2_util_close(tree, io1.smb2.out.file.handle);
    smb2_util_unlink(tree, fname);
    smb2_deltree(tree, DNAME);

    return ret;
}
Ejemplo n.º 28
0
static bool test_smb2_open_for_delete(struct torture_context *tctx,
                                      struct smb2_tree *tree)
{
    union smb_open io;
    union smb_fileinfo finfo;
    const char *fname = DNAME "\\torture_open_for_delete.txt";
    NTSTATUS status;
    struct smb2_handle h, h1;
    bool ret = true;

    torture_comment(tctx,
                    "Checking SMB2_OPEN for delete on a readonly file.\n");
    smb2_util_unlink(tree, fname);
    smb2_deltree(tree, fname);

    status = torture_smb2_testdir(tree, DNAME, &h);
    CHECK_STATUS(status, NT_STATUS_OK);

    /* reasonable default parameters */
    ZERO_STRUCT(io.smb2);
    io.generic.level = RAW_OPEN_SMB2;
    io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    io.smb2.in.alloc_size = 0;
    io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
    io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    io.smb2.in.create_options = 0;
    io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    io.smb2.in.security_flags = 0;
    io.smb2.in.fname = fname;

    /* Create the readonly file. */

    status = smb2_create(tree, tctx, &(io.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);
    h1 = io.smb2.out.file.handle;

    CHECK_VAL(io.smb2.out.oplock_level, 0);
    io.smb2.in.create_options = 0;
    CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    smb2_util_close(tree, h1);

    /* Now try and open for delete only - should succeed. */
    io.smb2.in.desired_access = SEC_STD_DELETE;
    io.smb2.in.file_attributes = 0;
    io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
                              NTCREATEX_SHARE_ACCESS_WRITE |
                              NTCREATEX_SHARE_ACCESS_DELETE;
    io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    status = smb2_create(tree, tctx, &(io.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);

    smb2_util_unlink(tree, fname);

    smb2_util_close(tree, h1);
    smb2_util_unlink(tree, fname);
    smb2_deltree(tree, DNAME);

    return ret;
}
Ejemplo n.º 29
0
/*
  test SMB2 open
*/
static bool test_smb2_open(struct torture_context *tctx,
                           struct smb2_tree *tree)
{
    union smb_open io;
    union smb_fileinfo finfo;
    const char *fname = DNAME "\\torture_ntcreatex.txt";
    const char *dname = DNAME "\\torture_ntcreatex.dir";
    NTSTATUS status;
    struct smb2_handle h, h1;
    bool ret = true;
    int i;
    struct {
        uint32_t create_disp;
        bool with_file;
        NTSTATUS correct_status;
    } open_funcs[] = {
        { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
        { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
        { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
        { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
        { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
        { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
        { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
        { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
        { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
        { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
        { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
        { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
        { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
        { 6,                            false, NT_STATUS_INVALID_PARAMETER },
    };

    torture_comment(tctx, "Checking SMB2 Open\n");

    smb2_util_unlink(tree, fname);
    smb2_util_rmdir(tree, dname);

    status = torture_smb2_testdir(tree, DNAME, &h);
    CHECK_STATUS(status, NT_STATUS_OK);

    ZERO_STRUCT(io.smb2);
    /* reasonable default parameters */
    io.generic.level = RAW_OPEN_SMB2;
    io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
    io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    io.smb2.in.alloc_size = 1024*1024;
    io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    io.smb2.in.create_options = 0;
    io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
    io.smb2.in.security_flags = 0;
    io.smb2.in.fname = fname;

    /* test the create disposition */
    for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
        if (open_funcs[i].with_file) {
            io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
            status= smb2_create(tree, tctx, &(io.smb2));
            if (!NT_STATUS_IS_OK(status)) {
                torture_comment(tctx,
                                "Failed to create file %s status %s %d\n",
                                fname, nt_errstr(status), i);

                ret = false;
                goto done;
            }
            smb2_util_close(tree, io.smb2.out.file.handle);
        }
        io.smb2.in.create_disposition = open_funcs[i].create_disp;
        status = smb2_create(tree, tctx, &(io.smb2));
        if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
            torture_comment(tctx,
                            "(%s) incorrect status %s should be %s (i=%d "
                            "with_file=%d open_disp=%d)\n",
                            __location__, nt_errstr(status),
                            nt_errstr(open_funcs[i].correct_status),
                            i, (int)open_funcs[i].with_file,
                            (int)open_funcs[i].create_disp);

            ret = false;
            goto done;
        }
        if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
            smb2_util_close(tree, io.smb2.out.file.handle);
            smb2_util_unlink(tree, fname);
        }
    }

    /* basic field testing */
    io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;

    status = smb2_create(tree, tctx, &(io.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);
    h1 = io.smb2.out.file.handle;

    CHECK_VAL(io.smb2.out.oplock_level, 0);
    CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    CHECK_NTTIME(io.smb2.out.create_time, create_time);
    CHECK_NTTIME(io.smb2.out.access_time, access_time);
    CHECK_NTTIME(io.smb2.out.write_time, write_time);
    CHECK_NTTIME(io.smb2.out.change_time, change_time);
    CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
    CHECK_ALL_INFO(io.smb2.out.size, size);

    /* check fields when the file already existed */
    smb2_util_close(tree, h1);
    smb2_util_unlink(tree, fname);

    status = smb2_create_complex_file(tree, fname, &h1);
    CHECK_STATUS(status, NT_STATUS_OK);

    smb2_util_close(tree, h1);

    io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
    status = smb2_create(tree, tctx, &(io.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);
    h1 = io.smb2.out.file.handle;

    CHECK_VAL(io.smb2.out.oplock_level, 0);
    CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED);
    CHECK_NTTIME(io.smb2.out.create_time, create_time);
    CHECK_NTTIME(io.smb2.out.access_time, access_time);
    CHECK_NTTIME(io.smb2.out.write_time, write_time);
    CHECK_NTTIME(io.smb2.out.change_time, change_time);
    CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
    CHECK_ALL_INFO(io.smb2.out.size, size);
    smb2_util_close(tree, h1);
    smb2_util_unlink(tree, fname);

    /* create a directory */
    io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
    io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
    io.smb2.in.alloc_size = 0;
    io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
    io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
    io.smb2.in.create_options = 0;
    io.smb2.in.fname = dname;
    fname = dname;

    smb2_util_rmdir(tree, fname);
    smb2_util_unlink(tree, fname);

    io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
    io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
    io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
    io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
                              NTCREATEX_SHARE_ACCESS_WRITE;
    status = smb2_create(tree, tctx, &(io.smb2));
    CHECK_STATUS(status, NT_STATUS_OK);
    h1 = io.smb2.out.file.handle;

    CHECK_VAL(io.smb2.out.oplock_level, 0);
    CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
    CHECK_NTTIME(io.smb2.out.create_time, create_time);
    CHECK_NTTIME(io.smb2.out.access_time, access_time);
    CHECK_NTTIME(io.smb2.out.write_time, write_time);
    CHECK_NTTIME(io.smb2.out.change_time, change_time);
    CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
    CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED,
              FILE_ATTRIBUTE_DIRECTORY);
    CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
    CHECK_ALL_INFO(io.smb2.out.size, size);
    CHECK_VAL(io.smb2.out.size, 0);
    CHECK_VAL(io.smb2.out.alloc_size, 0);
    smb2_util_unlink(tree, fname);

done:
    smb2_util_close(tree, h1);
    smb2_util_unlink(tree, fname);
    smb2_deltree(tree, DNAME);
    return ret;
}
Ejemplo n.º 30
0
/*
  test writing
*/
static NTSTATUS torture_smb2_write(TALLOC_CTX *mem_ctx, 
				   struct smb2_tree *tree, 
				   struct smb2_handle handle)
{
	struct smb2_write w;
	struct smb2_read r;
	NTSTATUS status;
	int i, len;
	int max = 80000000;
	int min = 1;

	while (max > min) {
		TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);


		len = 1+(min+max)/2;

		ZERO_STRUCT(w);
		w.in.file.handle = handle;
		w.in.offset      = 0;
		w.in.data        = data_blob_talloc(tmp_ctx, NULL, len);

		for (i=0;i<len;i++) {
			w.in.data.data[i] = i % 256;
		}

		printf("trying to write %d bytes (min=%d max=%d)\n", 
		       len, min, max);

		status = smb2_write(tree, &w);
		if (!NT_STATUS_IS_OK(status)) {
			printf("write failed - %s\n", nt_errstr(status));
			max = len-1;
			status = smb2_util_close(tree, handle);
			if (!NT_STATUS_IS_OK(status)) {
				/* vista bug */
				printf("coping with server disconnect\n");
				talloc_free(tree);
				if (!torture_smb2_connection(mem_ctx, &tree)) {
					printf("failed to reconnect\n");
					return NT_STATUS_NET_WRITE_FAULT;
				}
			}
			handle = torture_smb2_create(tree, FNAME);
			continue;
		} else {
			min = len;
		}

		
		ZERO_STRUCT(r);
		r.in.file.handle = handle;
		r.in.length      = len;
		r.in.offset      = 0;
		
		printf("reading %d bytes\n", len);

		status = smb2_read(tree, tmp_ctx, &r);
		if (!NT_STATUS_IS_OK(status)) {
			printf("read failed - %s\n", nt_errstr(status));
		} else if (w.in.data.length != r.out.data.length ||
		    memcmp(w.in.data.data, r.out.data.data, len) != 0) {
			printf("read data mismatch\n");
		}

		talloc_free(tmp_ctx);
	}

	printf("converged: len=%d\n", max);
	smb2_util_close(tree, handle);
	smb2_util_unlink(tree, FNAME);

	return NT_STATUS_OK;
}