1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-03 01:18:10 +03:00

s4:libcli: allow smb2_composite_unlink* to truncate the file before close

This is needed to delete streams...

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15656

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
This commit is contained in:
Stefan Metzmacher 2024-07-30 16:33:15 +02:00 committed by Volker Lendecke
parent 41df9e1c74
commit b1b1f2ea6b
2 changed files with 69 additions and 0 deletions

View File

@ -139,6 +139,12 @@ union smb_unlink {
struct { struct {
const char *pattern; const char *pattern;
uint16_t attrib; uint16_t attrib;
/*
* only used by
* smb2_composite_unlink*
*/
bool truncate_if_needed;
} in; } in;
} unlink; } unlink;
}; };

View File

@ -47,6 +47,38 @@ static void continue_close(struct smb2_request *req)
composite_error(ctx, status); composite_error(ctx, status);
} }
struct smb2_composite_unlink_state {
bool truncate_if_needed;
struct smb2_handle handle;
};
/*
continue after the truncate in a composite unlink
*/
static void continue_truncate(struct smb2_request *req)
{
struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context);
struct smb2_composite_unlink_state *state =
talloc_get_type_abort(ctx->private_data,
struct smb2_composite_unlink_state);
struct smb2_tree *tree = req->tree;
struct smb2_close close_parm;
NTSTATUS status;
status = smb2_setinfo_recv(req);
if (!NT_STATUS_IS_OK(status)) {
/* we ignore errors as we should not leak the handle */
}
ZERO_STRUCT(close_parm);
close_parm.in.file.handle = state->handle;
close_parm.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
req = smb2_close_send(tree, &close_parm);
composite_continue_smb2(ctx, req, continue_close, ctx);
}
/* /*
continue after the create in a composite unlink continue after the create in a composite unlink
*/ */
@ -54,6 +86,9 @@ static void continue_unlink(struct smb2_request *req)
{ {
struct composite_context *ctx = talloc_get_type(req->async.private_data, struct composite_context *ctx = talloc_get_type(req->async.private_data,
struct composite_context); struct composite_context);
struct smb2_composite_unlink_state *state =
talloc_get_type_abort(ctx->private_data,
struct smb2_composite_unlink_state);
struct smb2_tree *tree = req->tree; struct smb2_tree *tree = req->tree;
struct smb2_create create_parm; struct smb2_create create_parm;
struct smb2_close close_parm; struct smb2_close close_parm;
@ -65,6 +100,23 @@ static void continue_unlink(struct smb2_request *req)
return; return;
} }
if (create_parm.out.size != 0 &&
state->truncate_if_needed)
{
union smb_setfileinfo sinfo;
state->handle = create_parm.out.file.handle;
ZERO_STRUCT(sinfo);
sinfo.end_of_file_info.level =
RAW_SFILEINFO_END_OF_FILE_INFORMATION;
sinfo.end_of_file_info.in.file.handle = state->handle;
sinfo.end_of_file_info.in.size = 0;
req = smb2_setinfo_file_send(tree, &sinfo);
composite_continue_smb2(ctx, req, continue_truncate, ctx);
return;
}
ZERO_STRUCT(close_parm); ZERO_STRUCT(close_parm);
close_parm.in.file.handle = create_parm.out.file.handle; close_parm.in.file.handle = create_parm.out.file.handle;
@ -79,12 +131,20 @@ struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
union smb_unlink *io) union smb_unlink *io)
{ {
struct composite_context *ctx; struct composite_context *ctx;
struct smb2_composite_unlink_state *state = NULL;
struct smb2_create create_parm; struct smb2_create create_parm;
struct smb2_request *req; struct smb2_request *req;
ctx = composite_create(tree, tree->session->transport->ev); ctx = composite_create(tree, tree->session->transport->ev);
if (ctx == NULL) return NULL; if (ctx == NULL) return NULL;
state = talloc_zero(ctx, struct smb2_composite_unlink_state);
if (composite_nomem(state, ctx)) {
return ctx;
}
ctx->private_data = state;
state->truncate_if_needed = io->unlink.in.truncate_if_needed;
/* check for wildcards - we could support these with a /* check for wildcards - we could support these with a
search, but for now they aren't necessary */ search, but for now they aren't necessary */
if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) { if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
@ -94,6 +154,9 @@ struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
ZERO_STRUCT(create_parm); ZERO_STRUCT(create_parm);
create_parm.in.desired_access = SEC_STD_DELETE; create_parm.in.desired_access = SEC_STD_DELETE;
if (state->truncate_if_needed) {
create_parm.in.desired_access |= SEC_FILE_WRITE_DATA;
}
create_parm.in.create_disposition = NTCREATEX_DISP_OPEN; create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
create_parm.in.share_access = create_parm.in.share_access =
NTCREATEX_SHARE_ACCESS_DELETE| NTCREATEX_SHARE_ACCESS_DELETE|