static void smb2srv_ioctl_send(struct ntvfs_request *ntvfs) { struct smb2srv_request *req; union smb_ioctl *io; SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_ioctl); SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x30, True, 0)); SSVAL(req->out.body, 0x02, io->smb2.out._pad); SIVAL(req->out.body, 0x04, io->smb2.out.function); if (io->smb2.level == RAW_IOCTL_SMB2_NO_HANDLE) { struct smb2_handle h; h.data[0] = UINT64_MAX; h.data[1] = UINT64_MAX; smb2_push_handle(req->out.body + 0x08, &h); } else { smb2srv_push_handle(req->out.body, 0x08,io->smb2.in.file.ntvfs); } SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x18, io->smb2.out.in)); SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x20, io->smb2.out.out)); SIVAL(req->out.body, 0x28, io->smb2.out.unknown2); SIVAL(req->out.body, 0x2C, io->smb2.out.unknown3); smb2srv_send_reply(req); }
static void smb2srv_create_send(struct ntvfs_request *ntvfs) { struct smb2srv_request *req; union smb_open *io; SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open); SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, True, io->smb2.out.blob.length)); SSVAL(req->out.body, 0x02, io->smb2.out.oplock_flags); SIVAL(req->out.body, 0x04, io->smb2.out.create_action); SBVAL(req->out.body, 0x08, io->smb2.out.create_time); SBVAL(req->out.body, 0x10, io->smb2.out.access_time); SBVAL(req->out.body, 0x18, io->smb2.out.write_time); SBVAL(req->out.body, 0x20, io->smb2.out.change_time); SBVAL(req->out.body, 0x28, io->smb2.out.alloc_size); SBVAL(req->out.body, 0x30, io->smb2.out.size); SIVAL(req->out.body, 0x38, io->smb2.out.file_attr); SIVAL(req->out.body, 0x3C, io->smb2.out._pad); smb2srv_push_handle(req->out.body, 0x40, io->smb2.out.file.ntvfs); SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, io->smb2.out.blob)); /* also setup the chained file handle */ req->chained_file_handle = req->_chained_file_handle; smb2srv_push_handle(req->chained_file_handle, 0, io->smb2.out.file.ntvfs); smb2srv_send_reply(req); }
/* send a create request */ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create *io) { struct smb2_request *req; NTSTATUS status; DATA_BLOB blob = data_blob(NULL, 0); req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, True, 0); if (req == NULL) return NULL; SSVAL(req->out.body, 0x02, io->in.oplock_flags); SIVAL(req->out.body, 0x04, io->in.impersonation); SIVAL(req->out.body, 0x08, io->in.unknown3[0]); SIVAL(req->out.body, 0x0C, io->in.unknown3[1]); SIVAL(req->out.body, 0x10, io->in.unknown3[2]); SIVAL(req->out.body, 0x14, io->in.unknown3[3]); SIVAL(req->out.body, 0x18, io->in.access_mask); SIVAL(req->out.body, 0x1C, io->in.file_attr); SIVAL(req->out.body, 0x20, io->in.share_access); SIVAL(req->out.body, 0x24, io->in.open_disposition); SIVAL(req->out.body, 0x28, io->in.create_options); status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } if (io->in.eas.num_eas != 0) { DATA_BLOB b = data_blob_talloc(req, NULL, ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas)); ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas); status = smb2_create_blob_add(req, &blob, CREATE_TAG_EXTA, b, False); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } data_blob_free(&b); } /* an empty MxAc tag seems to be used to ask the server to return the maximum access mask allowed on the file */ status = smb2_create_blob_add(req, &blob, CREATE_TAG_MXAC, data_blob(NULL, 0), True); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } status = smb2_push_o32s32_blob(&req->out, 0x30, blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } smb2_transport_send(req); return req; }
static void smb2srv_create_send(struct ntvfs_request *ntvfs) { struct smb2srv_request *req; union smb_open *io; DATA_BLOB blob; SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open); /* setup the blobs we should give in the reply */ if (io->smb2.out.maximal_access != 0) { uint32_t data[2]; SIVAL(data, 0, 0); SIVAL(data, 4, io->smb2.out.maximal_access); SMB2SRV_CHECK(smb2_create_blob_add(req, &io->smb2.out.blobs, SMB2_CREATE_TAG_MXAC, data_blob_const(data, 8))); } SMB2SRV_CHECK(smb2_create_blob_push(req, &blob, io->smb2.out.blobs)); SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, blob.length)); SCVAL(req->out.body, 0x02, io->smb2.out.oplock_level); SCVAL(req->out.body, 0x03, io->smb2.out.reserved); SIVAL(req->out.body, 0x04, io->smb2.out.create_action); SBVAL(req->out.body, 0x08, io->smb2.out.create_time); SBVAL(req->out.body, 0x10, io->smb2.out.access_time); SBVAL(req->out.body, 0x18, io->smb2.out.write_time); SBVAL(req->out.body, 0x20, io->smb2.out.change_time); SBVAL(req->out.body, 0x28, io->smb2.out.alloc_size); SBVAL(req->out.body, 0x30, io->smb2.out.size); SIVAL(req->out.body, 0x38, io->smb2.out.file_attr); SIVAL(req->out.body, 0x3C, io->smb2.out.reserved2); smb2srv_push_handle(req->out.body, 0x40, io->smb2.out.file.ntvfs); SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, blob)); /* also setup the chained file handle */ req->chained_file_handle = req->_chained_file_handle; smb2srv_push_handle(req->chained_file_handle, 0, io->smb2.out.file.ntvfs); smb2srv_send_reply(req); }
/* send a create request */ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create *io) { struct smb2_request *req; NTSTATUS status; DATA_BLOB blob; struct smb2_create_blobs blobs; int i; ZERO_STRUCT(blobs); req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0); if (req == NULL) return NULL; SCVAL(req->out.body, 0x02, io->in.security_flags); SCVAL(req->out.body, 0x03, io->in.oplock_level); SIVAL(req->out.body, 0x04, io->in.impersonation_level); SBVAL(req->out.body, 0x08, io->in.create_flags); SBVAL(req->out.body, 0x10, io->in.reserved); SIVAL(req->out.body, 0x18, io->in.desired_access); SIVAL(req->out.body, 0x1C, io->in.file_attributes); SIVAL(req->out.body, 0x20, io->in.share_access); SIVAL(req->out.body, 0x24, io->in.create_disposition); SIVAL(req->out.body, 0x28, io->in.create_options); status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } /* now add all the optional blobs */ if (io->in.eas.num_eas != 0) { DATA_BLOB b = data_blob_talloc(req, NULL, ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas, 4)); ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas, 4); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_EXTA, b); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } data_blob_free(&b); } /* an empty MxAc tag seems to be used to ask the server to return the maximum access mask allowed on the file */ if (io->in.query_maximal_access) { /* TODO: MS-SMB2 2.2.13.2.5 says this can contain a timestamp? What to do with that if it doesn't match? */ status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_MXAC, data_blob(NULL, 0)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.alloc_size != 0) { uint8_t data[8]; SBVAL(data, 0, io->in.alloc_size); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_ALSI, data_blob_const(data, 8)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.durable_open) { status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_DHNQ, data_blob_talloc_zero(req, 16)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.durable_handle) { uint8_t data[16]; smb2_push_handle(data, io->in.durable_handle); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_DHNC, data_blob_const(data, 16)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.timewarp) { uint8_t data[8]; SBVAL(data, 0, io->in.timewarp); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_TWRP, data_blob_const(data, 8)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.sec_desc) { enum ndr_err_code ndr_err; DATA_BLOB sd_blob; ndr_err = ndr_push_struct_blob(&sd_blob, req, io->in.sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(req); return NULL; } status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_SECD, sd_blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.query_on_disk_id) { status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_QFID, data_blob(NULL, 0)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } if (io->in.lease_request) { uint8_t data[32]; memcpy(&data[0], &io->in.lease_request->lease_key, 16); SIVAL(data, 16, io->in.lease_request->lease_state); SIVAL(data, 20, io->in.lease_request->lease_flags); SBVAL(data, 24, io->in.lease_request->lease_duration); status = smb2_create_blob_add(req, &blobs, SMB2_CREATE_TAG_RQLS, data_blob_const(data, 32)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } /* and any custom blobs */ for (i=0;i<io->in.blobs.num_blobs;i++) { status = smb2_create_blob_add(req, &blobs, io->in.blobs.blobs[i].tag, io->in.blobs.blobs[i].data); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } } status = smb2_create_blob_push(req, &blob, blobs); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } status = smb2_push_o32s32_blob(&req->out, 0x30, blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } data_blob_free(&blob); smb2_transport_send(req); return req; }