/**************************************************************************** raw echo interface (async recv) ****************************************************************************/ NTSTATUS smb_raw_echo_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, struct smb_echo *p) { if (!smbcli_request_receive(req) || smbcli_request_is_error(req)) { goto failed; } SMBCLI_CHECK_WCT(req, 1); p->out.count++; p->out.sequence_number = SVAL(req->in.vwv, VWV(0)); p->out.size = req->in.data_size; talloc_free(p->out.data); p->out.data = talloc_array(mem_ctx, uint8_t, p->out.size); NT_STATUS_HAVE_NO_MEMORY(p->out.data); if (!smbcli_raw_pull_data(&req->in.bufinfo, req->in.data, p->out.size, p->out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } if (p->out.count == p->in.repeat_count) { return smbcli_request_destroy(req); } return NT_STATUS_OK; failed: return smbcli_request_destroy(req); }
/**************************************************************************** Open a file - async recv ****************************************************************************/ _PUBLIC_ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, union smb_open *parms) { NTSTATUS status; if (!smbcli_request_receive(req) || smbcli_request_is_error(req)) { goto failed; } switch (parms->openold.level) { case RAW_OPEN_T2OPEN: return smb_raw_t2open_recv(req, mem_ctx, parms); case RAW_OPEN_OPEN: SMBCLI_CHECK_WCT(req, 7); parms->openold.out.file.fnum = SVAL(req->in.vwv, VWV(0)); parms->openold.out.attrib = SVAL(req->in.vwv, VWV(1)); parms->openold.out.write_time = raw_pull_dos_date3(req->transport, req->in.vwv + VWV(2)); parms->openold.out.size = IVAL(req->in.vwv, VWV(4)); parms->openold.out.rmode = SVAL(req->in.vwv, VWV(6)); break; case RAW_OPEN_OPENX: SMBCLI_CHECK_MIN_WCT(req, 15); parms->openx.out.file.fnum = SVAL(req->in.vwv, VWV(2)); parms->openx.out.attrib = SVAL(req->in.vwv, VWV(3)); parms->openx.out.write_time = raw_pull_dos_date3(req->transport, req->in.vwv + VWV(4)); parms->openx.out.size = IVAL(req->in.vwv, VWV(6)); parms->openx.out.access = SVAL(req->in.vwv, VWV(8)); parms->openx.out.ftype = SVAL(req->in.vwv, VWV(9)); parms->openx.out.devstate = SVAL(req->in.vwv, VWV(10)); parms->openx.out.action = SVAL(req->in.vwv, VWV(11)); parms->openx.out.unique_fid = IVAL(req->in.vwv, VWV(12)); if (req->in.wct >= 19) { parms->openx.out.access_mask = IVAL(req->in.vwv, VWV(15)); parms->openx.out.unknown = IVAL(req->in.vwv, VWV(17)); } else { parms->openx.out.access_mask = 0; parms->openx.out.unknown = 0; } break; case RAW_OPEN_MKNEW: SMBCLI_CHECK_WCT(req, 1); parms->mknew.out.file.fnum = SVAL(req->in.vwv, VWV(0)); break; case RAW_OPEN_CREATE: SMBCLI_CHECK_WCT(req, 1); parms->create.out.file.fnum = SVAL(req->in.vwv, VWV(0)); break; case RAW_OPEN_CTEMP: SMBCLI_CHECK_WCT(req, 1); parms->ctemp.out.file.fnum = SVAL(req->in.vwv, VWV(0)); smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->ctemp.out.name, req->in.data, -1, STR_TERMINATE | STR_ASCII); break; case RAW_OPEN_SPLOPEN: SMBCLI_CHECK_WCT(req, 1); parms->splopen.out.file.fnum = SVAL(req->in.vwv, VWV(0)); break; case RAW_OPEN_NTCREATEX: SMBCLI_CHECK_MIN_WCT(req, 34); parms->ntcreatex.out.oplock_level = CVAL(req->in.vwv, 4); parms->ntcreatex.out.file.fnum = SVAL(req->in.vwv, 5); parms->ntcreatex.out.create_action = IVAL(req->in.vwv, 7); parms->ntcreatex.out.create_time = smbcli_pull_nttime(req->in.vwv, 11); parms->ntcreatex.out.access_time = smbcli_pull_nttime(req->in.vwv, 19); parms->ntcreatex.out.write_time = smbcli_pull_nttime(req->in.vwv, 27); parms->ntcreatex.out.change_time = smbcli_pull_nttime(req->in.vwv, 35); parms->ntcreatex.out.attrib = IVAL(req->in.vwv, 43); parms->ntcreatex.out.alloc_size = BVAL(req->in.vwv, 47); parms->ntcreatex.out.size = BVAL(req->in.vwv, 55); parms->ntcreatex.out.file_type = SVAL(req->in.vwv, 63); parms->ntcreatex.out.ipc_state = SVAL(req->in.vwv, 65); parms->ntcreatex.out.is_directory = CVAL(req->in.vwv, 67); break; case RAW_OPEN_NTTRANS_CREATE: return smb_raw_nttrans_create_recv(req, mem_ctx, parms); case RAW_OPEN_OPENX_READX: SMBCLI_CHECK_MIN_WCT(req, 15); parms->openxreadx.out.file.fnum = SVAL(req->in.vwv, VWV(2)); parms->openxreadx.out.attrib = SVAL(req->in.vwv, VWV(3)); parms->openxreadx.out.write_time = raw_pull_dos_date3(req->transport, req->in.vwv + VWV(4)); parms->openxreadx.out.size = IVAL(req->in.vwv, VWV(6)); parms->openxreadx.out.access = SVAL(req->in.vwv, VWV(8)); parms->openxreadx.out.ftype = SVAL(req->in.vwv, VWV(9)); parms->openxreadx.out.devstate = SVAL(req->in.vwv, VWV(10)); parms->openxreadx.out.action = SVAL(req->in.vwv, VWV(11)); parms->openxreadx.out.unique_fid = IVAL(req->in.vwv, VWV(12)); if (req->in.wct >= 19) { parms->openxreadx.out.access_mask = IVAL(req->in.vwv, VWV(15)); parms->openxreadx.out.unknown = IVAL(req->in.vwv, VWV(17)); } else { parms->openxreadx.out.access_mask = 0; parms->openxreadx.out.unknown = 0; } status = smbcli_chained_advance(req); if (!NT_STATUS_IS_OK(status)) { return status; } SMBCLI_CHECK_WCT(req, 12); parms->openxreadx.out.remaining = SVAL(req->in.vwv, VWV(2)); parms->openxreadx.out.compaction_mode = SVAL(req->in.vwv, VWV(3)); parms->openxreadx.out.nread = SVAL(req->in.vwv, VWV(5)); if (parms->openxreadx.out.nread > MAX(parms->openxreadx.in.mincnt, parms->openxreadx.in.maxcnt) || !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)), parms->openxreadx.out.nread, parms->openxreadx.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } break; case RAW_OPEN_NTCREATEX_READX: SMBCLI_CHECK_MIN_WCT(req, 34); parms->ntcreatexreadx.out.oplock_level = CVAL(req->in.vwv, 4); parms->ntcreatexreadx.out.file.fnum = SVAL(req->in.vwv, 5); parms->ntcreatexreadx.out.create_action = IVAL(req->in.vwv, 7); parms->ntcreatexreadx.out.create_time = smbcli_pull_nttime(req->in.vwv, 11); parms->ntcreatexreadx.out.access_time = smbcli_pull_nttime(req->in.vwv, 19); parms->ntcreatexreadx.out.write_time = smbcli_pull_nttime(req->in.vwv, 27); parms->ntcreatexreadx.out.change_time = smbcli_pull_nttime(req->in.vwv, 35); parms->ntcreatexreadx.out.attrib = IVAL(req->in.vwv, 43); parms->ntcreatexreadx.out.alloc_size = BVAL(req->in.vwv, 47); parms->ntcreatexreadx.out.size = BVAL(req->in.vwv, 55); parms->ntcreatexreadx.out.file_type = SVAL(req->in.vwv, 63); parms->ntcreatexreadx.out.ipc_state = SVAL(req->in.vwv, 65); parms->ntcreatexreadx.out.is_directory = CVAL(req->in.vwv, 67); status = smbcli_chained_advance(req); if (!NT_STATUS_IS_OK(status)) { return status; } SMBCLI_CHECK_WCT(req, 12); parms->ntcreatexreadx.out.remaining = SVAL(req->in.vwv, VWV(2)); parms->ntcreatexreadx.out.compaction_mode = SVAL(req->in.vwv, VWV(3)); parms->ntcreatexreadx.out.nread = SVAL(req->in.vwv, VWV(5)); if (parms->ntcreatexreadx.out.nread > MAX(parms->ntcreatexreadx.in.mincnt, parms->ntcreatexreadx.in.maxcnt) || !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)), parms->ntcreatexreadx.out.nread, parms->ntcreatexreadx.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } break; case RAW_OPEN_SMB2: req->status = NT_STATUS_INTERNAL_ERROR; break; } failed: return smbcli_request_destroy(req); }
/**************************************************************************** low level read operation (async recv) ****************************************************************************/ _PUBLIC_ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms) { if (!smbcli_request_receive(req) || smbcli_request_is_error(req)) { goto failed; } switch (parms->generic.level) { case RAW_READ_READBRAW: parms->readbraw.out.nread = req->in.size - NBT_HDR_SIZE; if (parms->readbraw.out.nread > MAX(parms->readx.in.mincnt, parms->readx.in.maxcnt)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; goto failed; } memcpy(parms->readbraw.out.data, req->in.buffer + NBT_HDR_SIZE, parms->readbraw.out.nread); break; case RAW_READ_LOCKREAD: SMBCLI_CHECK_WCT(req, 5); parms->lockread.out.nread = SVAL(req->in.vwv, VWV(0)); if (parms->lockread.out.nread > parms->lockread.in.count || !smbcli_raw_pull_data(&req->in.bufinfo, req->in.data+3, parms->lockread.out.nread, parms->lockread.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } break; case RAW_READ_READ: /* there are 4 reserved words in the reply */ SMBCLI_CHECK_WCT(req, 5); parms->read.out.nread = SVAL(req->in.vwv, VWV(0)); if (parms->read.out.nread > parms->read.in.count || !smbcli_raw_pull_data(&req->in.bufinfo, req->in.data+3, parms->read.out.nread, parms->read.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } break; case RAW_READ_READX: /* there are 5 reserved words in the reply */ SMBCLI_CHECK_WCT(req, 12); parms->readx.out.remaining = SVAL(req->in.vwv, VWV(2)); parms->readx.out.compaction_mode = SVAL(req->in.vwv, VWV(3)); parms->readx.out.nread = SVAL(req->in.vwv, VWV(5)); /* handle oversize replies for non-chained readx replies with CAP_LARGE_READX. The snia spec has must to answer for. */ if ((req->tree->session->transport->negotiate.capabilities & CAP_LARGE_READX) && CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE && req->in.size >= 0x10000) { parms->readx.out.nread += (SVAL(req->in.vwv, VWV(7)) << 16); if (req->in.hdr + SVAL(req->in.vwv, VWV(6)) + parms->readx.out.nread <= req->in.buffer + req->in.size) { req->in.data_size += (SVAL(req->in.vwv, VWV(7)) << 16); /* update the bufinfo with the new size */ smb_setup_bufinfo(req); } } if (parms->readx.out.nread > MAX(parms->readx.in.mincnt, parms->readx.in.maxcnt) || !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)), parms->readx.out.nread, parms->readx.out.data)) { req->status = NT_STATUS_BUFFER_TOO_SMALL; } break; case RAW_READ_SMB2: req->status = NT_STATUS_INTERNAL_ERROR; break; } failed: return smbcli_request_destroy(req); }