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"
8 /* the stages of this call */
9 enum appendacl_stage
{APPENDACL_OPENPATH
, APPENDACL_GET
,
10 APPENDACL_SET
, APPENDACL_GETAGAIN
, APPENDACL_CLOSEPATH
};
12 static void appendacl_handler(struct smbcli_request
*req
);
14 struct appendacl_state
{
15 enum appendacl_stage stage
;
16 struct smb_composite_appendacl
*io
;
18 union smb_open
*io_open
;
19 union smb_setfileinfo
*io_setfileinfo
;
20 union smb_fileinfo
*io_fileinfo
;
22 struct smbcli_request
*req
;
26 static NTSTATUS
appendacl_open(struct composite_context
*c
,
27 struct smb_composite_appendacl
*io
)
29 struct appendacl_state
*state
= talloc_get_type(c
->private_data
, struct appendacl_state
);
30 struct smbcli_tree
*tree
= state
->req
->tree
;
33 status
= smb_raw_open_recv(state
->req
, c
, state
->io_open
);
34 NT_STATUS_NOT_OK_RETURN(status
);
36 /* setup structures for getting fileinfo */
37 state
->io_fileinfo
= talloc(c
, union smb_fileinfo
);
38 NT_STATUS_HAVE_NO_MEMORY(state
->io_fileinfo
);
40 state
->io_fileinfo
->query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
41 state
->io_fileinfo
->query_secdesc
.in
.file
.fnum
= state
->io_open
->ntcreatex
.out
.file
.fnum
;
42 state
->io_fileinfo
->query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
44 state
->req
= smb_raw_fileinfo_send(tree
, state
->io_fileinfo
);
45 NT_STATUS_HAVE_NO_MEMORY(state
->req
);
48 state
->req
->async
.fn
= appendacl_handler
;
49 state
->req
->async
.private_data
= c
;
50 state
->stage
= APPENDACL_GET
;
52 talloc_free (state
->io_open
);
57 static NTSTATUS
appendacl_get(struct composite_context
*c
,
58 struct smb_composite_appendacl
*io
)
60 struct appendacl_state
*state
= talloc_get_type(c
->private_data
, struct appendacl_state
);
61 struct smbcli_tree
*tree
= state
->req
->tree
;
65 status
= smb_raw_fileinfo_recv(state
->req
, state
->io_fileinfo
, state
->io_fileinfo
);
66 NT_STATUS_NOT_OK_RETURN(status
);
68 /* setup structures for setting fileinfo */
69 state
->io_setfileinfo
= talloc(c
, union smb_setfileinfo
);
70 NT_STATUS_HAVE_NO_MEMORY(state
->io_setfileinfo
);
72 state
->io_setfileinfo
->set_secdesc
.level
= RAW_SFILEINFO_SEC_DESC
;
73 state
->io_setfileinfo
->set_secdesc
.in
.file
.fnum
= state
->io_fileinfo
->query_secdesc
.in
.file
.fnum
;
75 state
->io_setfileinfo
->set_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
76 state
->io_setfileinfo
->set_secdesc
.in
.sd
= state
->io_fileinfo
->query_secdesc
.out
.sd
;
77 talloc_steal(state
->io_setfileinfo
, state
->io_setfileinfo
->set_secdesc
.in
.sd
);
79 /* append all aces from io->in.sd->dacl to new security descriptor */
80 if (io
->in
.sd
->dacl
!= NULL
) {
81 for (i
= 0; i
< io
->in
.sd
->dacl
->num_aces
; i
++) {
82 security_descriptor_dacl_add(state
->io_setfileinfo
->set_secdesc
.in
.sd
,
83 &(io
->in
.sd
->dacl
->aces
[i
]));
87 status
= smb_raw_setfileinfo(tree
, state
->io_setfileinfo
);
88 NT_STATUS_NOT_OK_RETURN(status
);
90 state
->req
= smb_raw_setfileinfo_send(tree
, state
->io_setfileinfo
);
91 NT_STATUS_HAVE_NO_MEMORY(state
->req
);
93 /* call handler when done setting new security descriptor on file */
94 state
->req
->async
.fn
= appendacl_handler
;
95 state
->req
->async
.private_data
= c
;
96 state
->stage
= APPENDACL_SET
;
98 talloc_free (state
->io_fileinfo
);
103 static NTSTATUS
appendacl_set(struct composite_context
*c
,
104 struct smb_composite_appendacl
*io
)
106 struct appendacl_state
*state
= talloc_get_type(c
->private_data
, struct appendacl_state
);
107 struct smbcli_tree
*tree
= state
->req
->tree
;
110 status
= smbcli_request_simple_recv(state
->req
);
111 NT_STATUS_NOT_OK_RETURN(status
);
113 /* setup structures for getting fileinfo */
114 state
->io_fileinfo
= talloc(c
, union smb_fileinfo
);
115 NT_STATUS_HAVE_NO_MEMORY(state
->io_fileinfo
);
118 state
->io_fileinfo
->query_secdesc
.level
= RAW_FILEINFO_SEC_DESC
;
119 state
->io_fileinfo
->query_secdesc
.in
.file
.fnum
= state
->io_setfileinfo
->set_secdesc
.in
.file
.fnum
;
120 state
->io_fileinfo
->query_secdesc
.in
.secinfo_flags
= SECINFO_DACL
;
122 state
->req
= smb_raw_fileinfo_send(tree
, state
->io_fileinfo
);
123 NT_STATUS_HAVE_NO_MEMORY(state
->req
);
125 /* set the handler */
126 state
->req
->async
.fn
= appendacl_handler
;
127 state
->req
->async
.private_data
= c
;
128 state
->stage
= APPENDACL_GETAGAIN
;
130 talloc_free (state
->io_setfileinfo
);
136 static NTSTATUS
appendacl_getagain(struct composite_context
*c
,
137 struct smb_composite_appendacl
*io
)
139 struct appendacl_state
*state
= talloc_get_type(c
->private_data
, struct appendacl_state
);
140 struct smbcli_tree
*tree
= state
->req
->tree
;
141 union smb_close
*io_close
;
144 status
= smb_raw_fileinfo_recv(state
->req
, c
, state
->io_fileinfo
);
145 NT_STATUS_NOT_OK_RETURN(status
);
147 io
->out
.sd
= state
->io_fileinfo
->query_secdesc
.out
.sd
;
149 /* setup structures for close */
150 io_close
= talloc(c
, union smb_close
);
151 NT_STATUS_HAVE_NO_MEMORY(io_close
);
153 io_close
->close
.level
= RAW_CLOSE_CLOSE
;
154 io_close
->close
.in
.file
.fnum
= state
->io_fileinfo
->query_secdesc
.in
.file
.fnum
;
155 io_close
->close
.in
.write_time
= 0;
157 state
->req
= smb_raw_close_send(tree
, io_close
);
158 NT_STATUS_HAVE_NO_MEMORY(state
->req
);
160 /* call the handler */
161 state
->req
->async
.fn
= appendacl_handler
;
162 state
->req
->async
.private_data
= c
;
163 state
->stage
= APPENDACL_CLOSEPATH
;
165 talloc_free (state
->io_fileinfo
);
172 static NTSTATUS
appendacl_close(struct composite_context
*c
,
173 struct smb_composite_appendacl
*io
)
175 struct appendacl_state
*state
= talloc_get_type(c
->private_data
, struct appendacl_state
);
178 status
= smbcli_request_simple_recv(state
->req
);
179 NT_STATUS_NOT_OK_RETURN(status
);
181 c
->state
= COMPOSITE_STATE_DONE
;
187 handler for completion of a sub-request in appendacl
189 static void appendacl_handler(struct smbcli_request
*req
)
191 struct composite_context
*c
= (struct composite_context
*)req
->async
.private_data
;
192 struct appendacl_state
*state
= talloc_get_type(c
->private_data
, struct appendacl_state
);
194 /* when this handler is called, the stage indicates what
195 call has just finished */
196 switch (state
->stage
) {
197 case APPENDACL_OPENPATH
:
198 c
->status
= appendacl_open(c
, state
->io
);
202 c
->status
= appendacl_get(c
, state
->io
);
206 c
->status
= appendacl_set(c
, state
->io
);
209 case APPENDACL_GETAGAIN
:
210 c
->status
= appendacl_getagain(c
, state
->io
);
213 case APPENDACL_CLOSEPATH
:
214 c
->status
= appendacl_close(c
, state
->io
);
218 /* We should get here if c->state >= SMBCLI_REQUEST_DONE */
219 if (!NT_STATUS_IS_OK(c
->status
)) {
220 c
->state
= COMPOSITE_STATE_ERROR
;
223 if (c
->state
>= COMPOSITE_STATE_DONE
&&
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
234 struct composite_context
*smb_composite_appendacl_send(struct smbcli_tree
*tree
,
235 struct smb_composite_appendacl
*io
)
237 struct composite_context
*c
;
238 struct appendacl_state
*state
;
240 c
= talloc_zero(tree
, struct composite_context
);
241 if (c
== NULL
) goto failed
;
243 state
= talloc(c
, struct appendacl_state
);
244 if (state
== NULL
) goto failed
;
248 c
->private_data
= state
;
249 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
250 c
->event_ctx
= tree
->session
->transport
->ev
;
252 /* setup structures for opening file */
253 state
->io_open
= talloc_zero(c
, union smb_open
);
254 if (state
->io_open
== NULL
) goto failed
;
256 state
->io_open
->ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
257 state
->io_open
->ntcreatex
.in
.root_fid
.fnum
= 0;
258 state
->io_open
->ntcreatex
.in
.flags
= 0;
259 state
->io_open
->ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
260 state
->io_open
->ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
261 state
->io_open
->ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
262 state
->io_open
->ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
263 state
->io_open
->ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
264 state
->io_open
->ntcreatex
.in
.security_flags
= 0;
265 state
->io_open
->ntcreatex
.in
.fname
= io
->in
.fname
;
267 /* send the open on its way */
268 state
->req
= smb_raw_open_send(tree
, state
->io_open
);
269 if (state
->req
== NULL
) goto failed
;
271 /* setup the callback handler */
272 state
->req
->async
.fn
= appendacl_handler
;
273 state
->req
->async
.private_data
= c
;
274 state
->stage
= APPENDACL_OPENPATH
;
285 composite appendacl call - recv side
287 NTSTATUS
smb_composite_appendacl_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
)
291 status
= composite_wait(c
);
293 if (NT_STATUS_IS_OK(status
)) {
294 struct appendacl_state
*state
= talloc_get_type(c
->private_data
, struct appendacl_state
);
295 state
->io
->out
.sd
= security_descriptor_copy (mem_ctx
, state
->io
->out
.sd
);
304 composite appendacl call - sync interface
306 NTSTATUS
smb_composite_appendacl(struct smbcli_tree
*tree
,
308 struct smb_composite_appendacl
*io
)
310 struct composite_context
*c
= smb_composite_appendacl_send(tree
, io
);
311 return smb_composite_appendacl_recv(c
, mem_ctx
);