/* recv a create reply */ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_create *io) { NTSTATUS status; if (!smb2_request_receive(req) || !smb2_request_is_ok(req)) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x58, True); io->out.oplock_flags = SVAL(req->in.body, 0x02); io->out.create_action = IVAL(req->in.body, 0x04); io->out.create_time = smbcli_pull_nttime(req->in.body, 0x08); io->out.access_time = smbcli_pull_nttime(req->in.body, 0x10); io->out.write_time = smbcli_pull_nttime(req->in.body, 0x18); io->out.change_time = smbcli_pull_nttime(req->in.body, 0x20); io->out.alloc_size = BVAL(req->in.body, 0x28); io->out.size = BVAL(req->in.body, 0x30); io->out.file_attr = IVAL(req->in.body, 0x38); io->out._pad = IVAL(req->in.body, 0x3C); smb2_pull_handle(req->in.body+0x40, &io->out.file.handle); status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &io->out.blob); if (!NT_STATUS_IS_OK(status)) { smb2_request_destroy(req); return status; } return smb2_request_destroy(req); }
/* recv a keepalive reply */ NTSTATUS smb2_keepalive_recv(struct smb2_request *req) { if (!smb2_request_receive(req) || !smb2_request_is_ok(req)) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x04, False); return smb2_request_destroy(req); }
/* recv a write reply */ NTSTATUS smb2_write_recv(struct smb2_request *req, struct smb2_write *io) { if (!smb2_request_receive(req) || !smb2_request_is_ok(req)) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x10, true); io->out._pad = SVAL(req->in.body, 0x02); io->out.nwritten = IVAL(req->in.body, 0x04); io->out.unknown1 = BVAL(req->in.body, 0x08); return smb2_request_destroy(req); }
/* Receive a Lease Break Response */ NTSTATUS smb2_lease_break_ack_recv(struct smb2_request *req, struct smb2_lease_break_ack *io) { if (!smb2_request_receive(req) || !smb2_request_is_ok(req)) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x24, false); io->out.reserved = IVAL(req->in.body, 0x02); io->out.lease.lease_flags = IVAL(req->in.body, 0x04); memcpy(&io->out.lease.lease_key, req->in.body+0x8, sizeof(struct smb2_lease_key)); io->out.lease.lease_state = IVAL(req->in.body, 0x18); io->out.lease.lease_duration = IVAL(req->in.body, 0x1C); return smb2_request_destroy(req); }
/* recv a find reply */ NTSTATUS smb2_find_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_find *io) { NTSTATUS status; if (!smb2_request_receive(req) || smb2_request_is_error(req)) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x08, true); status = smb2_pull_o16s32_blob(&req->in, mem_ctx, req->in.body+0x02, &io->out.blob); if (!NT_STATUS_IS_OK(status)) { return status; } return smb2_request_destroy(req); }
/* recv a read reply */ NTSTATUS smb2_read_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_read *io) { NTSTATUS status; if (!smb2_request_receive(req) || !smb2_request_is_ok(req)) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x10, true); status = smb2_pull_o16s32_blob(&req->in, mem_ctx, req->in.body+0x02, &io->out.data); if (!NT_STATUS_IS_OK(status)) { smb2_request_destroy(req); return status; } io->out.remaining = IVAL(req->in.body, 0x08); io->out.reserved = IVAL(req->in.body, 0x0C); return smb2_request_destroy(req); }
/** recv a session setup reply */ NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_session_setup *io) { NTSTATUS status; if (!smb2_request_receive(req) || (smb2_request_is_error(req) && !NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED))) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x08, true); io->out.session_flags = SVAL(req->in.body, 0x02); io->out.uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID); status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x04, &io->out.secblob); if (!NT_STATUS_IS_OK(status)) { smb2_request_destroy(req); return status; } return smb2_request_destroy(req); }
/* recv a create reply */ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct smb2_create *io) { NTSTATUS status; DATA_BLOB blob; int i; if (!smb2_request_receive(req) || !smb2_request_is_ok(req)) { return smb2_request_destroy(req); } SMB2_CHECK_PACKET_RECV(req, 0x58, true); ZERO_STRUCT(io->out); io->out.oplock_level = CVAL(req->in.body, 0x02); io->out.reserved = CVAL(req->in.body, 0x03); io->out.create_action = IVAL(req->in.body, 0x04); io->out.create_time = smbcli_pull_nttime(req->in.body, 0x08); io->out.access_time = smbcli_pull_nttime(req->in.body, 0x10); io->out.write_time = smbcli_pull_nttime(req->in.body, 0x18); io->out.change_time = smbcli_pull_nttime(req->in.body, 0x20); io->out.alloc_size = BVAL(req->in.body, 0x28); io->out.size = BVAL(req->in.body, 0x30); io->out.file_attr = IVAL(req->in.body, 0x38); io->out.reserved2 = IVAL(req->in.body, 0x3C); smb2_pull_handle(req->in.body+0x40, &io->out.file.handle); status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &blob); if (!NT_STATUS_IS_OK(status)) { smb2_request_destroy(req); return status; } status = smb2_create_blob_parse(mem_ctx, blob, &io->out.blobs); if (!NT_STATUS_IS_OK(status)) { smb2_request_destroy(req); return status; } /* pull out the parsed blobs */ for (i=0;i<io->out.blobs.num_blobs;i++) { if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) { /* TODO: this also contains a status field in first 4 bytes */ if (io->out.blobs.blobs[i].data.length != 8) { smb2_request_destroy(req); return NT_STATUS_INVALID_NETWORK_RESPONSE; } io->out.maximal_access = IVAL(io->out.blobs.blobs[i].data.data, 4); } if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) { if (io->out.blobs.blobs[i].data.length != 32) { smb2_request_destroy(req); return NT_STATUS_INVALID_NETWORK_RESPONSE; } memcpy(io->out.on_disk_id, io->out.blobs.blobs[i].data.data, 32); } if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_RQLS) == 0) { uint8_t *data; if (io->out.blobs.blobs[i].data.length != 32) { smb2_request_destroy(req); return NT_STATUS_INVALID_NETWORK_RESPONSE; } data = io->out.blobs.blobs[i].data.data; memcpy(&io->out.lease_response.lease_key, data, 16); io->out.lease_response.lease_state = IVAL(data, 16); io->out.lease_response.lease_flags = IVAL(data, 20); io->out.lease_response.lease_duration = BVAL(data, 24); } } data_blob_free(&blob); return smb2_request_destroy(req); }