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 */ 9enum appendacl_stage {APPENDACL_OPENPATH, APPENDACL_GET, 10 APPENDACL_SET, APPENDACL_GETAGAIN, APPENDACL_CLOSEPATH}; 11 12static void appendacl_handler(struct smbcli_request *req); 13 14struct 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 26static NTSTATUS appendacl_open(struct composite_context *c, 27 struct smb_composite_appendacl *io) 28{ 29 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); 30 struct smbcli_tree *tree = state->req->tree; 31 NTSTATUS status; 32 33 status = smb_raw_open_recv(state->req, c, state->io_open); 34 NT_STATUS_NOT_OK_RETURN(status); 35 36 /* setup structures for getting fileinfo */ 37 state->io_fileinfo = talloc(c, union smb_fileinfo); 38 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo); 39 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; 43 44 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo); 45 NT_STATUS_HAVE_NO_MEMORY(state->req); 46 47 /* set the handler */ 48 state->req->async.fn = appendacl_handler; 49 state->req->async.private_data = c; 50 state->stage = APPENDACL_GET; 51 52 talloc_free (state->io_open); 53 54 return NT_STATUS_OK; 55} 56 57static NTSTATUS appendacl_get(struct composite_context *c, 58 struct smb_composite_appendacl *io) 59{ 60 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); 61 struct smbcli_tree *tree = state->req->tree; 62 int i; 63 NTSTATUS status; 64 65 status = smb_raw_fileinfo_recv(state->req, state->io_fileinfo, state->io_fileinfo); 66 NT_STATUS_NOT_OK_RETURN(status); 67 68 /* setup structures for setting fileinfo */ 69 state->io_setfileinfo = talloc(c, union smb_setfileinfo); 70 NT_STATUS_HAVE_NO_MEMORY(state->io_setfileinfo); 71 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; 74 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); 78 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])); 84 } 85 } 86 87 status = smb_raw_setfileinfo(tree, state->io_setfileinfo); 88 NT_STATUS_NOT_OK_RETURN(status); 89 90 state->req = smb_raw_setfileinfo_send(tree, state->io_setfileinfo); 91 NT_STATUS_HAVE_NO_MEMORY(state->req); 92 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; 97 98 talloc_free (state->io_fileinfo); 99 100 return NT_STATUS_OK; 101} 102 103static NTSTATUS appendacl_set(struct composite_context *c, 104 struct smb_composite_appendacl *io) 105{ 106 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); 107 struct smbcli_tree *tree = state->req->tree; 108 NTSTATUS status; 109 110 status = smbcli_request_simple_recv(state->req); 111 NT_STATUS_NOT_OK_RETURN(status); 112 113 /* setup structures for getting fileinfo */ 114 state->io_fileinfo = talloc(c, union smb_fileinfo); 115 NT_STATUS_HAVE_NO_MEMORY(state->io_fileinfo); 116 117 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; 121 122 state->req = smb_raw_fileinfo_send(tree, state->io_fileinfo); 123 NT_STATUS_HAVE_NO_MEMORY(state->req); 124 125 /* set the handler */ 126 state->req->async.fn = appendacl_handler; 127 state->req->async.private_data = c; 128 state->stage = APPENDACL_GETAGAIN; 129 130 talloc_free (state->io_setfileinfo); 131 132 return NT_STATUS_OK; 133} 134 135 136static NTSTATUS appendacl_getagain(struct composite_context *c, 137 struct smb_composite_appendacl *io) 138{ 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; 142 NTSTATUS status; 143 144 status = smb_raw_fileinfo_recv(state->req, c, state->io_fileinfo); 145 NT_STATUS_NOT_OK_RETURN(status); 146 147 io->out.sd = state->io_fileinfo->query_secdesc.out.sd; 148 149 /* setup structures for close */ 150 io_close = talloc(c, union smb_close); 151 NT_STATUS_HAVE_NO_MEMORY(io_close); 152 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; 156 157 state->req = smb_raw_close_send(tree, io_close); 158 NT_STATUS_HAVE_NO_MEMORY(state->req); 159 160 /* call the handler */ 161 state->req->async.fn = appendacl_handler; 162 state->req->async.private_data = c; 163 state->stage = APPENDACL_CLOSEPATH; 164 165 talloc_free (state->io_fileinfo); 166 167 return NT_STATUS_OK; 168} 169 170 171 172static NTSTATUS appendacl_close(struct composite_context *c, 173 struct smb_composite_appendacl *io) 174{ 175 struct appendacl_state *state = talloc_get_type(c->private_data, struct appendacl_state); 176 NTSTATUS status; 177 178 status = smbcli_request_simple_recv(state->req); 179 NT_STATUS_NOT_OK_RETURN(status); 180 181 c->state = COMPOSITE_STATE_DONE; 182 183 return NT_STATUS_OK; 184} 185 186/* 187 handler for completion of a sub-request in appendacl 188*/ 189static void appendacl_handler(struct smbcli_request *req) 190{ 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); 193 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); 199 break; 200 201 case APPENDACL_GET: 202 c->status = appendacl_get(c, state->io); 203 break; 204 205 case APPENDACL_SET: 206 c->status = appendacl_set(c, state->io); 207 break; 208 209 case APPENDACL_GETAGAIN: 210 c->status = appendacl_getagain(c, state->io); 211 break; 212 213 case APPENDACL_CLOSEPATH: 214 c->status = appendacl_close(c, state->io); 215 break; 216 } 217 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; 221 } 222 223 if (c->state >= COMPOSITE_STATE_DONE && 224 c->async.fn) { 225 c->async.fn(c); 226 } 227} 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*/ 234struct composite_context *smb_composite_appendacl_send(struct smbcli_tree *tree, 235 struct smb_composite_appendacl *io) 236{ 237 struct composite_context *c; 238 struct appendacl_state *state; 239 240 c = talloc_zero(tree, struct composite_context); 241 if (c == NULL) goto failed; 242 243 state = talloc(c, struct appendacl_state); 244 if (state == NULL) goto failed; 245 246 state->io = io; 247 248 c->private_data = state; 249 c->state = COMPOSITE_STATE_IN_PROGRESS; 250 c->event_ctx = tree->session->transport->socket->event.ctx; 251 252 /* setup structures for opening file */ 253 state->io_open = talloc_zero(c, union smb_open); 254 if (state->io_open == NULL) goto failed; 255 256 state->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX; 257 state->io_open->ntcreatex.in.root_fid = 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; 266 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; 270 271 /* setup the callback handler */ 272 state->req->async.fn = appendacl_handler; 273 state->req->async.private_data = c; 274 state->stage = APPENDACL_OPENPATH; 275 276 return c; 277 278failed: 279 talloc_free(c); 280 return NULL; 281} 282 283 284/* 285 composite appendacl call - recv side 286*/ 287NTSTATUS smb_composite_appendacl_recv(struct composite_context *c, TALLOC_CTX *mem_ctx) 288{ 289 NTSTATUS status; 290 291 status = composite_wait(c); 292 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); 296 } 297 298 talloc_free(c); 299 return status; 300} 301 302 303/* 304 composite appendacl call - sync interface 305*/ 306NTSTATUS smb_composite_appendacl(struct smbcli_tree *tree, 307 TALLOC_CTX *mem_ctx, 308 struct smb_composite_appendacl *io) 309{ 310 struct composite_context *c = smb_composite_appendacl_send(tree, io); 311 return smb_composite_appendacl_recv(c, mem_ctx); 312} 313 314