Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/libcli/smb_composite/appendacl.c
Line
Count
Source
1
#include "includes.h"
2
#include "libcli/raw/libcliraw.h"
3
#include "libcli/raw/raw_proto.h"
4
#include "libcli/composite/composite.h"
5
#include "libcli/security/security.h"
6
#include "libcli/smb_composite/smb_composite.h"
7
8
/* the stages of this call */
9
enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET, 
10
           APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH};
11
12
static void appendacl_handler(struct smbcli_request *req);
13
14
struct appendacl_state {
15
  enum appendacl_stage stage;
16
  struct smb_composite_appendacl *io;
17
18
  union smb_open *io_open;
19
  union smb_setfileinfo *io_setfileinfo;
20
  union smb_fileinfo *io_fileinfo;
21
22
  struct smbcli_request *req;
23
};
24
25
26
static NTSTATUS appendacl_open(struct composite_context *c, 
27
            struct smb_composite_appendacl *io)
28
0
{
29
0
  struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
30
0
  struct smbcli_tree *tree = state->req->tree;
31
0
  NTSTATUS status;
32
33
0
  status = smb_raw_open_recv(state->req, c, state->io_open);
34
0
  NT_STATUS_NOT_OK_RETURN(status);
35
36
  /* setup structures for getting fileinfo */
37
0
  state->io_fileinfo = talloc(c, union smb_fileinfo);
38
0
  NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
39
  
40
0
  state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
41
0
  state->io_fileinfo->query_secdesc.in.file.fnum = state->io_open->ntcreatex.out.file.fnum;
42
0
  state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
43
44
0
  state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
45
0
  NT_STATUS_HAVE_NO_MEMORY(state->req);
46
47
  /* set the handler */
48
0
  state->req->async.fn = appendacl_handler;
49
0
  state->req->async.private_data = c;
50
0
  state->stage = APPENDACL_GET;
51
  
52
0
  talloc_free (state->io_open);
53
54
0
  return NT_STATUS_OK;
55
0
}
56
57
static NTSTATUS appendacl_get(struct composite_context *c, 
58
             struct smb_composite_appendacl *io)
59
0
{
60
0
  struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
61
0
  struct smbcli_tree *tree = state->req->tree;
62
0
  NTSTATUS status;
63
  
64
0
  status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo);
65
0
  NT_STATUS_NOT_OK_RETURN(status);
66
  
67
  /* setup structures for setting fileinfo */
68
0
  state->io_setfileinfo = talloc(c, union smb_setfileinfo);
69
0
  NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo);
70
  
71
0
  state->io_setfileinfo->set_secdesc.level            = RAW_SFILEINFO_SEC_DESC;
72
0
  state->io_setfileinfo->set_secdesc.in.file.fnum     = state->io_fileinfo->query_secdesc.in.file.fnum;
73
  
74
0
  state->io_setfileinfo->set_secdesc.in.secinfo_flags = SECINFO_DACL;
75
0
  state->io_setfileinfo->set_secdesc.in.sd            = state->io_fileinfo->query_secdesc.out.sd;
76
0
  talloc_steal(state->io_setfileinfo, state->io_setfileinfo->set_secdesc.in.sd);
77
78
  /* append all aces from io->in.sd->dacl to new security descriptor */
79
0
  if (io->in.sd->dacl != NULL) {
80
0
    uint32_t i;
81
0
    for (i = 0; i < io->in.sd->dacl->num_aces; i++) {
82
0
      security_descriptor_dacl_add(state->io_setfileinfo->set_secdesc.in.sd,
83
0
                 &(io->in.sd->dacl->aces[i]));
84
0
    }
85
0
  }
86
87
0
  status = smb_raw_setfileinfo(tree, state->io_setfileinfo);
88
0
  NT_STATUS_NOT_OK_RETURN(status);
89
90
0
  state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo);
91
0
  NT_STATUS_HAVE_NO_MEMORY(state->req);
92
93
  /* call handler when done setting new security descriptor on file */
94
0
  state->req->async.fn = appendacl_handler;
95
0
  state->req->async.private_data = c;
96
0
  state->stage = APPENDACL_SET;
97
98
0
  talloc_free (state->io_fileinfo);
99
100
0
  return NT_STATUS_OK;
101
0
}
102
103
static NTSTATUS appendacl_set(struct composite_context *c, 
104
            struct smb_composite_appendacl *io)
105
0
{
106
0
  struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
107
0
  struct smbcli_tree *tree = state->req->tree;
108
0
  NTSTATUS status;
109
110
0
  status = smbcli_request_simple_recv(state->req);
111
0
  NT_STATUS_NOT_OK_RETURN(status);
112
113
  /* setup structures for getting fileinfo */
114
0
  state->io_fileinfo = talloc(c, union smb_fileinfo);
115
0
  NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo);
116
  
117
118
0
  state->io_fileinfo->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
119
0
  state->io_fileinfo->query_secdesc.in.file.fnum = state->io_setfileinfo->set_secdesc.in.file.fnum;
120
0
  state->io_fileinfo->query_secdesc.in.secinfo_flags = SECINFO_DACL;
121
122
0
  state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo);
123
0
  NT_STATUS_HAVE_NO_MEMORY(state->req);
124
125
  /* set the handler */
126
0
  state->req->async.fn = appendacl_handler;
127
0
  state->req->async.private_data = c;
128
0
  state->stage = APPENDACL_GETAGAIN;
129
  
130
0
  talloc_free (state->io_setfileinfo);
131
132
0
  return NT_STATUS_OK;
133
0
}
134
135
136
static NTSTATUS appendacl_getagain(struct composite_context *c, 
137
           struct smb_composite_appendacl *io)
138
0
{
139
0
  struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
140
0
  struct smbcli_tree *tree = state->req->tree;
141
0
  union smb_close *io_close;
142
0
  NTSTATUS status;
143
  
144
0
  status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo);
145
0
  NT_STATUS_NOT_OK_RETURN(status);
146
147
0
  io->out.sd = state->io_fileinfo->query_secdesc.out.sd;
148
149
  /* setup structures for close */
150
0
  io_close = talloc(c, union smb_close);
151
0
  NT_STATUS_HAVE_NO_MEMORY(io_close);
152
  
153
0
  io_close->close.level = RAW_CLOSE_CLOSE;
154
0
  io_close->close.in.file.fnum = state->io_fileinfo->query_secdesc.in.file.fnum;
155
0
  io_close->close.in.write_time = 0;
156
157
0
  state->req = smb_raw_close_send(tree, io_close);
158
0
  NT_STATUS_HAVE_NO_MEMORY(state->req);
159
160
  /* call the handler */
161
0
  state->req->async.fn = appendacl_handler;
162
0
  state->req->async.private_data = c;
163
0
  state->stage = APPENDACL_CLOSEPATH;
164
165
0
  talloc_free (state->io_fileinfo);
166
167
0
  return NT_STATUS_OK;
168
0
}
169
170
171
172
static NTSTATUS appendacl_close(struct composite_context *c, 
173
        struct smb_composite_appendacl *io)
174
0
{
175
0
  struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
176
0
  NTSTATUS status;
177
178
0
  status = smbcli_request_simple_recv(state->req);
179
0
  NT_STATUS_NOT_OK_RETURN(status);
180
  
181
0
  c->state = COMPOSITE_STATE_DONE;
182
183
0
  return NT_STATUS_OK;
184
0
}
185
186
/*
187
  handler for completion of a sub-request in appendacl
188
*/
189
static void appendacl_handler(struct smbcli_request *req)
190
0
{
191
0
  struct composite_context *c = (struct composite_context *)req->async.private_data;
192
0
  struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
193
194
  /* when this handler is called, the stage indicates what
195
     call has just finished */
196
0
  switch (state->stage) {
197
0
  case APPENDACL_OPENPATH:
198
0
    c->status = appendacl_open(c, state->io);
199
0
    break;
200
201
0
  case APPENDACL_GET:
202
0
    c->status = appendacl_get(c, state->io);
203
0
    break;
204
205
0
  case APPENDACL_SET:
206
0
    c->status = appendacl_set(c, state->io);
207
0
    break;
208
209
0
  case APPENDACL_GETAGAIN:
210
0
    c->status = appendacl_getagain(c, state->io);
211
0
    break;
212
213
0
  case APPENDACL_CLOSEPATH:
214
0
    c->status = appendacl_close(c, state->io);
215
0
    break;
216
0
  }
217
218
  /* We should get here if c->state >= SMBCLI_REQUEST_DONE */
219
0
  if (!NT_STATUS_IS_OK(c->status)) {
220
0
    c->state = COMPOSITE_STATE_ERROR;
221
0
  }
222
223
0
  if (c->state >= COMPOSITE_STATE_DONE &&
224
0
      c->async.fn) {
225
0
    c->async.fn(c);
226
0
  }
227
0
}
228
229
230
/*
231
  composite appendacl call - does an open followed by a number setfileinfo,
232
  after that new acls are read with fileinfo, followed by a close
233
*/
234
struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree, 
235
              struct smb_composite_appendacl *io)
236
0
{
237
0
  struct composite_context *c;
238
0
  struct appendacl_state *state;
239
240
0
  c = talloc_zero(tree, struct composite_context);
241
0
  if (c == NULL) goto failed;
242
243
0
  state = talloc(c, struct appendacl_state);
244
0
  if (state == NULL) goto failed;
245
246
0
  state->io = io;
247
248
0
  c->private_data = state;
249
0
  c->state = COMPOSITE_STATE_IN_PROGRESS;
250
0
  c->event_ctx = tree->session->transport->ev;
251
252
  /* setup structures for opening file */
253
0
  state->io_open = talloc_zero(c, union smb_open);
254
0
  if (state->io_open == NULL) goto failed;
255
  
256
0
  state->io_open->ntcreatex.level               = RAW_OPEN_NTCREATEX;
257
0
  state->io_open->ntcreatex.in.root_fid.fnum    = 0;
258
0
  state->io_open->ntcreatex.in.flags            = 0;
259
0
  state->io_open->ntcreatex.in.access_mask      = SEC_FLAG_MAXIMUM_ALLOWED;
260
0
  state->io_open->ntcreatex.in.file_attr        = FILE_ATTRIBUTE_NORMAL;
261
0
  state->io_open->ntcreatex.in.share_access     = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
262
0
  state->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
263
0
  state->io_open->ntcreatex.in.impersonation    = NTCREATEX_IMPERSONATION_ANONYMOUS;
264
0
  state->io_open->ntcreatex.in.security_flags   = 0;
265
0
  state->io_open->ntcreatex.in.fname            = io->in.fname;
266
267
  /* send the open on its way */
268
0
  state->req = smb_raw_open_send(tree, state->io_open);
269
0
  if (state->req == NULL) goto failed;
270
271
  /* setup the callback handler */
272
0
  state->req->async.fn = appendacl_handler;
273
0
  state->req->async.private_data = c;
274
0
  state->stage = APPENDACL_OPENPATH;
275
276
0
  return c;
277
278
0
failed:
279
0
  talloc_free(c);
280
0
  return NULL;
281
0
}
282
283
284
/*
285
  composite appendacl call - recv side
286
*/
287
NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
288
0
{
289
0
  NTSTATUS status;
290
291
0
  status = composite_wait(c);
292
293
0
  if (NT_STATUS_IS_OK(status)) {
294
0
    struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state);
295
0
    state->io->out.sd = security_descriptor_copy (mem_ctx, state->io->out.sd);
296
0
  }
297
298
0
  talloc_free(c);
299
0
  return status;
300
0
}
301
302
303
/*
304
  composite appendacl call - sync interface
305
*/
306
NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree, 
307
        TALLOC_CTX *mem_ctx,
308
        struct smb_composite_appendacl *io)
309
0
{
310
0
  struct composite_context *c = smb_composite_appendacl_send(tree, io);
311
0
  return smb_composite_appendacl_recv(c, mem_ctx);
312
0
}
313